错误的加密(QT c++ OpenSSL AES 256 CBC)
Posted
技术标签:
【中文标题】错误的加密(QT c++ OpenSSL AES 256 CBC)【英文标题】:Wrong Encryption (QT c++ OpenSSL AES 256 CBC) 【发布时间】:2019-04-14 06:35:00 【问题描述】:我编写了一个小程序来使用 OpenSSL AES 256 CBC 加密和解密数据,但在解密加密数据后,我最终得到了垃圾数据,所以代码中一定有问题,但我无法弄清楚你能不能看看代码,告诉我我做错了什么:
主要功能:
/* Message to be encrypted */
unsigned char* plaintext =
(unsigned char*)"The quick brown fox jumps over the lazy dog";
EVP_CIPHER_CTX *en, *de;
en = EVP_CIPHER_CTX_new();
de = EVP_CIPHER_CTX_new();
/* 8 bytes to salt the key_data during key generation. This is an example of
compiled in salt. We just read the bit pattern created by these two 4 byte
integers on the stack as 64 bits of contigous salt material -
ofcourse this only works if sizeof(int) >= 4 */
unsigned int salt[] = 12345, 54321;
unsigned char *key_data;
int key_data_len, i;
key_data = (unsigned char*)"01234567890123456789012345678901";
key_data_len = strlen((const char*)key_data);
Encryption AES;
/* gen key and iv. init the cipher ctx object */
if (AES.Init(key_data, key_data_len, (unsigned char *)&salt, en, de))
qDebug() << "Couldn't initialize AES cipher ";
unsigned char *ciphertext;
int olen, len;
/* The enc/dec functions deal with binary data and not C strings. strlen() will
return length of the string without counting the '\0' string marker. We always
pass in the marker byte to the encrypt/decrypt functions so that after decryption
we end up with a legal C string */
olen = len = strlen((const char*)plaintext)+1;
ciphertext = AES.Encrypt(en, plaintext, &len);
plaintext = (unsigned char*)"";
plaintext = AES.Decrypt(de, ciphertext, &len);
QString s;
QString result = "";
int rev = strlen((const char*)ciphertext);
for ( int i = 0; i<rev; i++)
s = QString("%1").arg(ciphertext[i],0,16);
if(s == "0")
s="00";
result.append(s);
ui->label_7->setText(result);
rev = len;
result = "";
for ( int i = 0; i<rev; i++)
s = QString("%1").arg(plaintext[i],0,16);
if(s == "0")
s="00";
result.append(s);
ui->label_8->setText(result);
free(ciphertext);
free(plaintext);
EVP_CIPHER_CTX_free(en);
EVP_CIPHER_CTX_free(de);
初始化函数:
int Encryption::Init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx,
EVP_CIPHER_CTX *d_ctx)
int i, nrounds = 5;
unsigned char key[32], iv[32];
/*
* Generate key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
* nrounds is the number of times we hash the material. More rounds are more secure but
* slower.
*/
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv);
if (i != 32)
QMessageBox::warning(this, tr("Error while generating the key"), tr("The key isn't 256 bit!"));
return -1;
EVP_CIPHER_CTX_init(e_ctx);
EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_CIPHER_CTX_init(d_ctx);
EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv);
return 0;
加密函数:
inline unsigned char* Encryption:: Encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len)
// max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE bytes
int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
ciphertext = new unsigned char[c_len];
// allows reusing of 'e' for multiple encryption cycles
EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL);
/* update ciphertext, c_len is filled with the length of ciphertext generated,
*len is the size of plaintext in bytes */
int encrypted_bytes = 0;
for(int i=0;i<*len/AES_BLOCK_SIZE;++i)
EVP_EncryptUpdate(e, ciphertext+encrypted_bytes, &c_len, plaintext+encrypted_bytes, AES_BLOCK_SIZE);
encrypted_bytes += AES_BLOCK_SIZE;
float counter = i , size = *len/AES_BLOCK_SIZE+1;
emit Encryption_Percentage_Changed(counter/size * 100);
// update ciphertext with the final remaining bytes
EVP_EncryptFinal_ex(e, ciphertext+*len, &f_len);
*len = *len + f_len;
emit Encryption_Finished();
return ciphertext;
解密函数:
inline unsigned char* Encryption::Decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
// plaintext will always be equal to or lesser than length of ciphertext
int p_len = *len+AES_BLOCK_SIZE, f_len = 0;
plaintext = new unsigned char[p_len];
EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
int decrypted_bytes = 0;
for(int i=0;i<*len/AES_BLOCK_SIZE;++i)
EVP_DecryptUpdate(e, plaintext+decrypted_bytes, &p_len, ciphertext+decrypted_bytes, AES_BLOCK_SIZE);
decrypted_bytes += AES_BLOCK_SIZE;
float counter = i , size = *len/AES_BLOCK_SIZE;
emit Decryption_Percentage_Changed(counter/size * 100);
EVP_DecryptFinal_ex(e, plaintext+*len, &f_len);
*len = *len + f_len;
emit Decryption_Finished();
return plaintext;
编辑:我现在已经用实际代码替换了图像。
任何帮助将不胜感激。 提前致谢。
【问题讨论】:
理想情况下,无论如何,您都应该在一个大块中提供代码,这样其他人就可以复制粘贴它,然后用最少的工作量编译和运行它。所以不要忘记添加编译所需的包含。顺便说一句,具有足够声誉的其他人可以编辑您的问题,因此如果您无法正确格式化问题,其他人可以为您解决。 @Eelke 非常感谢您提供的信息,但代码编译得很好,这不是我面临的编译错误,而是逻辑错误。因为当我加密文本并尝试解密它时,我不会't get the original text. 【参考方案1】:当我尝试 result=QString::fromLocal8Bit((char*)ciphertext); 时,我终于意识到在显示加密和解密字符串时出现了什么问题。 它运行良好并显示了原始文本。
【讨论】:
以上是关于错误的加密(QT c++ OpenSSL AES 256 CBC)的主要内容,如果未能解决你的问题,请参考以下文章
OpenSSL AES_cfb128_encrypt C++