[英]C++ Openssl Encryption routines generates different output on each run
我有一個必須加密數據的應用程序。
但是,當我運行以下命令時,它將在同一執行中返回不同的輸出。 當我重復執行時,輸出模式完全相同,請參見我的問題的結尾。
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
且我執行該應用程序3次時,它將輸出以下內容:
//execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
//Execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
//execute Test.exe
mJOjOk2wIe5D4oA=
GTvRQb8IZtFYbLI=
plOJA083gOSfVrs=
這怎么可能?我的錯誤在哪里?
關鍵和四是短。 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
或之后提供值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.