簡體   English   中英

AES | 使用OpenSSL加密,使用mcrypt解密

[英]AES | Encrypt with OpenSSL, decrypt with mcrypt

我正在使用以下功能通過Qt中的OpenSSL庫加密我的數據:

QByteArray Crypto::Encrypt(QByteArray source, QString password)
{
  EVP_CIPHER_CTX en;

  unsigned char *key_data;
  int key_data_len;

  QByteArray ba = password.toLatin1();
  key_data = (unsigned char*)ba.data();
  key_data_len = strlen((char*)key_data);

  int nrounds = 28;
  unsigned char key[32], iv[32];

  EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, key_data, key_data_len, nrounds, key, iv);

QByteArray bkey = reinterpret_cast<const char*>(key) //EDIT: Contains the key afterwards
QByteArray biv = reinterpret_cast<const char*>(iv) //EDIT: Is Null afterwards

  EVP_CIPHER_CTX_init(&en);
  EVP_EncryptInit_ex(&en, EVP_aes_256_cbc(), NULL, key, iv);

  char *input = source.data();
  char *out;
  int len = source.size();

  int c_len = len + 16, f_len = 0;
  unsigned char *ciphertext = (unsigned char *)malloc(c_len);

  EVP_EncryptInit_ex(&en, NULL, NULL, NULL, NULL);
  EVP_EncryptUpdate(&en, ciphertext, &c_len, (unsigned char *)input, len);
  EVP_EncryptFinal_ex(&en, ciphertext+c_len, &f_len);

  len = c_len + f_len;

  out = (char*)ciphertext;

  EVP_CIPHER_CTX_cleanup(&en);

  return QByteArray(out, len);
}

在這種情況下, “源”“ 12345678901234567890123456789012abc”
“ password”“ 1hA!dh == sJAh48S8Ak!?skiitFi120xX”

所以....如果我沒做錯,那么EVP_BytesToKey()應該從密碼中生成一個密鑰,並提供數據以便以后解密該字符串。

對於Base64編碼,該密鑰為: “ aQkrZD / zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE =”
我不用鹽,所以沒有靜脈注射(應該為空)。

因此,Base64中的QByteArray bkey給我留下了“ aQkrZD / zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE =“
QByteArray bvi給了我Null

加密文本為“ CiUqILbZo + WJBr19IiovRVc1dqGvrastwo0k67TTrs51HB8AbJe8S4uxvB2D7Dkr”

現在,我使用以下PHP函數再次使用生成的密鑰解密密文:

<?php
function decrypt_data($data, $iv, $key) {
    $cypher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

    //if(is_null($iv)) {
    //    $ivlen = mcrypt_enc_get_iv_size($cypher);
    //    $iv = substr($data, 0, $ivlen);
    //    $data = substr($data, $ivlen);
    //}

    // initialize encryption handle
    if (mcrypt_generic_init($cypher, $key, $iv) != -1) {
            // decrypt
            $decrypted = mdecrypt_generic($cypher, $data);

            // clean up
            mcrypt_generic_deinit($cypher);
            mcrypt_module_close($cypher);

            return $decrypted;
    }

    return false;
}

$ctext = "CiUqILbZo+WJBr19IiovRVc1dqGvrastwo0k67TTrs51HB8AbJe8S4uxvB2D7Dkr";
$key = "aQkrZD/zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE=";

$res = decrypt_data(base64_decode($ctext), null, base64_decode($key));

echo $res;
?>

現在,我希望得到一個類似“ 123456789012345678978934563456789012abc”的響應。
我得到的是“ 7890123456789012abc”

我的字符串似乎以正確的方式解密,但是它被切成兩半,只顯示最后的19個字符。 有人可以幫我嗎? 我是加密技術的新手,無法真正弄清楚我到底出了錯。

這可能是由於您的誤解。 你說:

我不用鹽,所以沒有靜脈注射(應該為空)。

但是完全沒有理由為什么會這樣。 EVP_BytesToKey方法提供了密鑰和IV。 關鍵顯然是正確的,但IV並非正確。 這將導致純文本中出現隨機字符(IV僅更改第一個塊)。 由於此塊可能包含控制字符以及更多內容,因此可能無法正常顯示。

請記住,salt和IV可能有一些共同點(不應重復,可以公開等),但在密碼學中它們是完全不同的概念。

請使用您的Qt代碼再試一次,這一次打印出IV和密鑰。

我現在通過試錯法用空的初始化向量解決了這個問題,盡管我完全不知道為什么以下所有問題都是問題。 也許有人可以向我解釋。

更改行: int nrounds = 28; 做到了。

如果我在其中輸入除28以外的任何其他數字,則會生成IV,並且以后在mcrypt中使用它時,密文將以正確的方式解密。 為什么使用openssl函數EVP_BytesToKey()生成28個回合的密鑰是一個問題? 我現在將其減少到5個回合,但是我很好奇這個問題是否可能通過生成可能產生這種Null-IV的password-rounds-combination再次發生。

我真的不知道如何在此函數中處理IV生成的過程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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