AES 解密结果在 openssl 升级后变化
AES decryption result varies after openssl upgrade
我链接到 openssl 0.98 的代码具有 AES 解密功能,可以正常工作。
这是代码。
const int bits = 256;
AES_KEY key;
iRes = AES_set_decrypt_key((const unsigned char *)szSecretKey, bits, &key);
unsigned char szSigBytes[MAX_PATH] = "";
unsigned char *pSigBytes = szSigBytes;
unsigned char *pSignature = szSignature;
AES_decrypt(pSignature, pSigBytes, &key);
AES_decrypt(pSignature + 16, pSigBytes + 16, &key);
cout<<pSigBytes<<endl;
但是,在迁移到 openssl 1.0.1p 之后,我不得不使用 EVP 函数,因为非 EVP 函数在 FIPS 模式下失败。所以我将代码修改为
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int ciphertext_len = strlen((const char*)in);
if(!(ctx = EVP_CIPHER_CTX_new()));
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
return;
if(1 != EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len))
return;
if(1 != EVP_DecryptUpdate(ctx, out + 16, &len, in + 16, ciphertext_len - len))
return;
EVP_DecryptFinal_ex(ctx, out + len, &len);
EVP_CIPHER_CTX_free(ctx);
结果几乎匹配,但对于最后几个字符中的一些。
知道吗,我在这里做错了什么?
编辑:我看到在使用 EVP_DecryptUpdate 时未解密第二个 16 字节。
我已经将第二个 16 个字节提取到一个数组中并尝试对其进行解密。我看到当我使用 AES_decrypt 时它成功运行,但是当我使用 EVP_DecryptUpdate 时 returns ""
密码长度只有 2 个字节。这可能是解密失败的原因吗?
查看下面修改后的代码。
unsigned char temp[MAX_PATH] = "BoQ=\n";
unsigned char result[MAX_PATH] = "";
unsigned char data[MAX_PATH] = "";
Decode(temp, data);
//Decrypting with AES_Decrypt
AES_KEY key;
unsigned char DecodedSecretKey[MAX_PATH];
ZeroMemory(DecodedSecretKey, MAX_PATH);
Decode(secretKey, DecodedSecretKey);
AES_set_decrypt_key((const unsigned char *)DecodedSecretKey, 256, &key);
AES_decrypt(data, result, &key);//result returns the proper result
////////////////////////////////////////// //////////////////////////////////////////////// /////////////
//Decrypting with EVP_DecryptUpdate
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int ciphertext_len = strlen((const char*)data);
if(!(ctx = EVP_CIPHER_CTX_new()));
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
return;
if(1 != EVP_DecryptUpdate(ctx, result, &len, data, ciphertext_len))
return;
EVP_DecryptFinal_ex(ctx, result + len, &len);
EVP_CIPHER_CTX_free(ctx);
//Here the array result is always empty
EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len)
的用法是错误的。
这里,len
必须初始化为out
数组中的字节数。据我所知,如果您使用 len
作为全长和 cipthertext_len
调用一次,它必须解密所有加密文本。不需要第二次调用。或者:
len = <full length of buffer>;
EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len);
或
len = 16;
EVP_DecryptUpdate(ctx, out, &len, in, len);
len = 16;
EVP_DecryptUpdate(ctx, out+16, &len, in+16, len);
我更喜欢第一种方法。如果你需要特殊的填充,那么你可以使用额外的调用来处理最后一个块。
我刚刚弄清楚了问题所在。这真的是一个非常愚蠢的。
int ciphertext_len = strlen((const char*)data);
我正在使用 strlen 确定加密字符串的长度,这是错误的,我只是通过艰难的方式学习的。
我链接到 openssl 0.98 的代码具有 AES 解密功能,可以正常工作。
这是代码。
const int bits = 256;
AES_KEY key;
iRes = AES_set_decrypt_key((const unsigned char *)szSecretKey, bits, &key);
unsigned char szSigBytes[MAX_PATH] = "";
unsigned char *pSigBytes = szSigBytes;
unsigned char *pSignature = szSignature;
AES_decrypt(pSignature, pSigBytes, &key);
AES_decrypt(pSignature + 16, pSigBytes + 16, &key);
cout<<pSigBytes<<endl;
但是,在迁移到 openssl 1.0.1p 之后,我不得不使用 EVP 函数,因为非 EVP 函数在 FIPS 模式下失败。所以我将代码修改为
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int ciphertext_len = strlen((const char*)in);
if(!(ctx = EVP_CIPHER_CTX_new()));
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
return;
if(1 != EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len))
return;
if(1 != EVP_DecryptUpdate(ctx, out + 16, &len, in + 16, ciphertext_len - len))
return;
EVP_DecryptFinal_ex(ctx, out + len, &len);
EVP_CIPHER_CTX_free(ctx);
结果几乎匹配,但对于最后几个字符中的一些。 知道吗,我在这里做错了什么?
编辑:我看到在使用 EVP_DecryptUpdate 时未解密第二个 16 字节。
我已经将第二个 16 个字节提取到一个数组中并尝试对其进行解密。我看到当我使用 AES_decrypt 时它成功运行,但是当我使用 EVP_DecryptUpdate 时 returns "" 密码长度只有 2 个字节。这可能是解密失败的原因吗?
查看下面修改后的代码。
unsigned char temp[MAX_PATH] = "BoQ=\n";
unsigned char result[MAX_PATH] = "";
unsigned char data[MAX_PATH] = "";
Decode(temp, data);
//Decrypting with AES_Decrypt
AES_KEY key;
unsigned char DecodedSecretKey[MAX_PATH];
ZeroMemory(DecodedSecretKey, MAX_PATH);
Decode(secretKey, DecodedSecretKey);
AES_set_decrypt_key((const unsigned char *)DecodedSecretKey, 256, &key);
AES_decrypt(data, result, &key);//result returns the proper result
////////////////////////////////////////// //////////////////////////////////////////////// /////////////
//Decrypting with EVP_DecryptUpdate
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int ciphertext_len = strlen((const char*)data);
if(!(ctx = EVP_CIPHER_CTX_new()));
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
return;
if(1 != EVP_DecryptUpdate(ctx, result, &len, data, ciphertext_len))
return;
EVP_DecryptFinal_ex(ctx, result + len, &len);
EVP_CIPHER_CTX_free(ctx);
//Here the array result is always empty
EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len)
的用法是错误的。
这里,len
必须初始化为out
数组中的字节数。据我所知,如果您使用 len
作为全长和 cipthertext_len
调用一次,它必须解密所有加密文本。不需要第二次调用。或者:
len = <full length of buffer>;
EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len);
或
len = 16;
EVP_DecryptUpdate(ctx, out, &len, in, len);
len = 16;
EVP_DecryptUpdate(ctx, out+16, &len, in+16, len);
我更喜欢第一种方法。如果你需要特殊的填充,那么你可以使用额外的调用来处理最后一个块。
我刚刚弄清楚了问题所在。这真的是一个非常愚蠢的。
int ciphertext_len = strlen((const char*)data);
我正在使用 strlen 确定加密字符串的长度,这是错误的,我只是通过艰难的方式学习的。