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