加密错误(QT c++ OpenSSL AES 256 CBC)
Wrong Encryption (QT c++ OpenSSL AES 256 CBC)
我写了一个小程序来使用 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 '[=10=]' 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;
}
编辑:我现在已经用实际代码替换了图像。
如有任何帮助,我们将不胜感激。
提前致谢。
当我尝试 result=QString::fromLocal8Bit((char*)ciphertext); 时,我终于意识到显示加密和解密字符串的问题是什么。
它运行良好并显示了原文。
我写了一个小程序来使用 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 '[=10=]' 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;
}
编辑:我现在已经用实际代码替换了图像。
如有任何帮助,我们将不胜感激。 提前致谢。
当我尝试 result=QString::fromLocal8Bit((char*)ciphertext); 时,我终于意识到显示加密和解密字符串的问题是什么。 它运行良好并显示了原文。