In a database there is string encrypted with glibc's xencrypt which is using internally cbc_crypt and the decryption was happening with xdecrypt function which also uses cbc_crypt.
Since glibc 2.32 there is no way to enable again xencrypt and xdecrypt functions. So I am trying to decrypt the encrypted string with openssl with command:
openssl enc -des-cbc -d -in encrypted.enc -out decrypted.txt -iv 0000000000000000 -K <my key in hex>
But I get:
bad decrypt 140401522647424:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:../openssl-1.1.1k/crypto/evp/evp_enc.c:599
What am I doing wrong and is there an openssl command or function call that can provide the same result as xdecrypt (cbc_encrypt)?
***** UPDATE *****
I tried to solve the above question also programmatically. So I used the following code in order to be also in topic as @dave_thompson_085 mentioned in comment.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>
#include <openssl/des.h>
#include <openssl/pkcs7.h>
#define BUFFSIZE 420
int glibc_encrypt(const char *, const char *, const char *, char **, unsigned int *);
int glibc_decrypt(const char *, const char *, const char *, char **);
int openssl_encrypt(const char *, const char *, const char *, unsigned int, char *, unsigned int *);
int openssl_decrypt(const char *, const char *, char *, unsigned int, char **);
int main(void) {
const char *key = "abcdefgh";
const char *ivec = "87654321";
const char *data = "mypass1234test";
char *dst_buf;
unsigned int dst_size;
char *final_buf;
glibc_encrypt(key, ivec, data, &dst_buf, &dst_size);
glibc_decrypt(key, ivec, (const char *) dst_buf, &final_buf);
openssl_encrypt(key, ivec, data, strlen(data), dst_buf, &dst_size);
openssl_decrypt(key, ivec, dst_buf, dst_size, &final_buf);
return 0;
}
int glibc_encrypt(const char *key, const char *ivec, const char *data, char **dst, unsigned int *dst_size) {
char tmpkey[BUFFSIZE], tmpivec[BUFFSIZE];
unsigned int rawsize, i, result, pading;
printf("*** glibc encrytion ***\n");
strncpy(tmpkey, key, strlen(key));
strncpy(tmpivec, ivec, strlen(ivec));
des_setparity(tmpkey);
rawsize = strlen(data);
printf("data to be ecrypted is : %s\n", data);
printf("size of data to be encrypted is : %d\n", rawsize);
/* Add to data to ensure size is divisable by 8. */
pading = 8 - (rawsize % 8);
*dst_size = rawsize + pading;
printf("data size were rounded to : %d\n", *dst_size);
/* Allocate the containing ecryption buffer */
*dst = malloc(*dst_size);
memcpy(*dst, data, *dst_size);
for (i = rawsize ; i < *dst_size; i++)
dst[i] = '\0';
result = cbc_crypt(tmpkey, *dst, *dst_size, DES_ENCRYPT | DES_SW, tmpivec);
if (DES_FAILED(result) || strcmp(*dst, "") == 0) {
if(strcmp(*dst, "") == 0)
printf("*** Null Output ***\n");
else
printf("*** Encryption Error ***\n");
} else {
snprintf(tmpkey, *dst_size, "%s", *dst);
printf("glibc encrypted data : %s\n", tmpkey);
}
return 0;
}
int glibc_decrypt(const char *key, const char *ivec, const char *data, char **dst) {
char tmpkey[BUFFSIZE], tmpivec[BUFFSIZE];
unsigned int dstsize;
int result;
printf("\n*** glibc decryption ***\n");
strncpy(tmpkey, key, strlen(key));
strncpy(tmpivec, ivec, strlen(ivec));
des_setparity(tmpkey);
dstsize = strlen(data);
printf("data to be decrypted is : %s\n", data);
printf("size of data to be decrypted is : %d\n", dstsize);
/* Allocate the containing ecryption buffer */
*dst = malloc(dstsize);
memcpy(*dst, data, dstsize);
result = cbc_crypt(tmpkey, *dst, dstsize, DES_DECRYPT | DES_SW, tmpivec);
if(DES_FAILED(result) || strcmp(*dst, "") == 0) {
if(strcmp(*dst, "") == 0)
printf("*** Null Output ***\n");
else
printf("*** Decryption Error ***\n");
} else {
snprintf(tmpkey, dstsize, "%s", *dst);
printf("glibc decrypted data : %s\n", tmpkey);
}
return 0;
}
int openssl_encrypt(const char *key, const char *ivec, const char *_raw_ptr, unsigned int _raw_size, char *_dst_buf, unsigned int *_dst_size) {
DES_key_schedule schedule;
char tmpkey[BUFFSIZE];
DES_cblock *iv3;
int pading;
size_t i, vt_size;
char *mid_buf;
printf("\n*** openssl ecryption ***\n");
strncpy(tmpkey, key, strlen(key));
printf("data to be ecrypted is : %s\n", _raw_ptr);
printf("size of data to be encrypted is : %d\n", _raw_size);
DES_set_key_unchecked((const_DES_cblock*) &tmpkey, &schedule);
vt_size = strlen(ivec);
iv3 = (DES_cblock *) malloc(vt_size * sizeof(unsigned char));
memcpy(iv3, ivec, vt_size);
pading = 8 - (_raw_size % 8);
*_dst_size = _raw_size + pading;
printf("data size were rounded to : %d\n", *_dst_size);
mid_buf = malloc(*_dst_size);
memcpy(mid_buf, _raw_ptr, _raw_size );
/* Add to data to ensure size is divisable by 8. */
for (i = _raw_size ; i < *_dst_size; i++ )
mid_buf[i] = '\0';
DES_ncbc_encrypt((const unsigned char*) mid_buf, (unsigned char *) _dst_buf, *_dst_size, &schedule, iv3, DES_ENCRYPT);
printf("openssl ecrypted data : %s\n", _dst_buf);
printf("openssl ecrypted data size : %d\n", *_dst_size);
free(iv3);
free(mid_buf);
return 0;
}
int openssl_decrypt(const char *key, const char *ivec, char *_raw_ptr, unsigned int _raw_size, char **_dst_buf) {
DES_key_schedule schedule;
char tmpkey[BUFFSIZE];
DES_cblock *iv3;
size_t vt_size;
printf("\n*** openssl decryption ***\n");
strncpy(tmpkey, key, strlen(key));
printf("data to be decrypted is : %s\n", _raw_ptr);
printf("size of data to be dencrypted is: %d\n", _raw_size);
DES_set_key_unchecked((const_DES_cblock*) &tmpkey, &schedule);
vt_size = strlen(ivec);
iv3 = (DES_cblock *) malloc(vt_size * sizeof(unsigned char));
memcpy(iv3, ivec, vt_size);
*_dst_buf = (char*) malloc(_raw_size);
DES_ncbc_encrypt((const unsigned char*) _raw_ptr, (unsigned char *) *_dst_buf, _raw_size, &schedule, iv3, DES_DECRYPT);
printf("openssl decrypted data : %s\n", *_dst_buf);
free(iv3);
return 0;
}
And here is the output:
*** glibc encrytion ***
data to be ecrypted is : mypass1234test
size of data to be encrypted is : 14
data size were rounded to : 16
glibc encrypted data :▒!▒e͛▒4▒ k
▒▒
*** glibc decryption ***
data to be decrypted is :▒!▒e͛▒4▒ k
▒▒d
size of data to be decrypted is : 16
glibc decrypted data : mypass1234test
*** openssl ecryption ***
data to be ecrypted is : mypass1234test
size of data to be encrypted is : 14
data size were rounded to : 16
openssl ecrypted data : ▒▒▒▒˛▒▒▒uc▒
openssl ecrypted data size : 16
*** openssl decryption ***
data to be decrypted is : ▒▒▒▒˛▒▒▒uc▒
size of data to be dencrypted is: 16
openssl decrypted data : mypass1234test
Both openssl and glibc implementations encrypt and decrypt the data. But if used interchangeably the outcome if not correct.
I would expect the encrypted data from both of them to be exactly the same if the DES implementation is the same, as it should be I guess since the algorithm should produce the same output.
So why openssl and glibc produce seemingly different encrypted data when the same algorithm is used?