如何用openssl解密用cbc_crypt(xencrypt)加密的东西?
在数据库中,存在使用 glibc 的 xencrypt 加密的字符串它在内部使用 cbc_crypt 并且解密是通过 xdecrypt 函数也使用 cbc_crypt。
从 glibc 2.32 开始,无法再次启用 xencrypt 和 xdecrypt 功能。 所以我尝试使用 openssl 命令解密加密的字符串:
openssl enc -des-cbc -d -in encrypted.enc -out decrypted.txt -iv 0000000000000000 -K <my key in hex>
但我得到:
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
我做错了什么,是否有 openssl 命令或函数调用可以提供与 xdecrypt (cbc_encrypt) 相同的结果?
***** 更新 *****
我也尝试以编程方式解决上述问题。 因此,我使用了以下代码,以便也能进入评论中提到的@dave_thompson_085 主题。
#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;
}
这是输出:
*** 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
openssl 和 glibc 实现都会加密和解密数据。 但如果互换使用,结果就会不正确。
如果 DES 实现相同,我希望它们的加密数据完全相同,我猜应该是这样,因为算法应该产生相同的输出。
那么为什么当使用相同的算法时,openssl 和 glibc 会产生看似不同的加密数据呢?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
免责声明
这不是正确的答案,而是我在其他人想使用相同解决方案的情况下发现并使用的工作。
主要问题是,最近的GLIBC版本不再提供函数CBC_CRYPT,因此不再提供Xencrypt和XdeCrypt。
但是libtirpc( http://sourceforge.net/projects/projects/projects/libtirpc )包括丢失的cbc _crypt formic。
因此,我没有使用openssl来解密CBC_Crypt的员工,而是使用了libtirp库。
DISCLAIMER
This is not the correct answer but rather a work around I found and used in case some else wants to use the same solution.
The main problem is that recent glibc version do not provide any more the function cbc_crypt and hence xencrypt and xdecrypt.
But libtirpc (http://sourceforge.net/projects/libtirpc) includes the missing cbc_crypt function.
So instead of using openssl to decrypt the cbc_crypted staff I used the libtirp library.