我有一个必须加密数据的应用程序。
但是,当我运行以下命令时,它会在同一个执行中返回不同的输出。当我重复执行时,输出模式完全相同,请参阅我的问题的结尾。
int Encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cfb(), NULL, key, iv)) {
handleErrors();
}
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
handleErrors();
}
ciphertext_len = len;
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
handleErrors();
}
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
string EncryptThis(string Data, string Key, string IV, long long Buffer) {
unsigned char *key = (unsigned char *)Key.c_str();
unsigned char *iv = (unsigned char *)IV.c_str();
unsigned char *plaintext = (unsigned char *)Data.c_str();
unsigned char* ciphertext = new unsigned char[Buffer];
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
//cout << Data << endl; //ALWAYS THE SAME
//cout << Key << endl; //ALWAYS THE SAME
//cout << IV << endl; //ALWAYS THE SAME
int ciphertext_len = Encrypt(plaintext, (int)strlen((char *)plaintext), key, iv, ciphertext);
string Encrypted = base64_encode(reinterpret_cast<const unsigned char *>(ciphertext), ciphertext_len);
EVP_cleanup();
ERR_free_strings();
return Encrypted;
}
int main() {
cout << EncryptThis("ThisisATest", "Test", "Test2", 11) << endl;
cout << EncryptThis("ThisisATest", "Test", "Test2", 11) << endl;
cout << EncryptThis("ThisisATest", "Test", "Test2", 11) << endl;
}
在此测试中结果如下:
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
但是,当我再次运行相同的应用程序时,即使按相同的顺序,它也会返回完全相同的输出。所以在执行脚本时重复似乎是一个问题?
澄清。当这个应用程序被称为Test.exe
并且我执行该应用程序三次时,它将输出以下内容:
//execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
//Execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
//execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
这怎么可能,我的错误在哪里?
答案 0 :(得分:5)
关键和IV要简短。 EVP_aes_256_cfb
的密钥需要为256位(32字节),IV需要为块大小,AES为128位(16字节)。
由于键和IV要短,额外的长度以某种方式组成,没有标准定义。对于其中一个或两个使用的字节。在调用main时,每次存储器都是相同的(可能为零),因此结果相同。在内部调用中,内存已通过执行更改,但每次都以相同的方式更改输出。
缓冲区太短。它需要是要加密的数据的长度+块长度:11 + 16 - > 27.最好是加密函数(Encrypt
)创建缓冲区而不是调用者。 EVP_EncryptUpdate
函数将返回加密+填充的最终长度。
解决方案:使用密钥和IV的全长值,并在内部使用正确的长度处理缓冲区。
提示1:CBC模式更常用于CFB模式。
提示2:使用随机IV,只需在加密数据前加上IV用于解密,它不需要保密。这样,用户无需提供IV。
注意:如果您对全长密钥存在问题,并且IV更新问题并在EVP_EncryptUpdate
之后和之后的电话中提供评估。