簡體   English   中英

C ++ Openssl加密例程在每次運行時生成不同的輸出

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM