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