'How do I decrypt with openssl something encrypted with cbc_crypt (xencrypt)?

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?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source