首页 文章

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

提问于
浏览
0

我正在使用以下函数通过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);
}

在这种情况下 "source" "12345678901234567890123456789012abc" .
"password""1hA!dh==sJAh48S8Ak!?skiitFi120xX" .

所以....如果我做对了,那么EVP_BytesToKey()应该生成密码中的密钥并提供数据以便稍后解密该字符串 .

到Base64编码该密钥将是: "aQkrZD/zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE="
我不使用盐,所以没有IV(应该为null) .

所以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;
?>

现在我期待像 "12345678901234567890123456789012abc" 这样的回复 .
我得到的是 "7890123456789012abc" .

我的字符串似乎以正确的方式解密,但它被减半,只显示最后19个字符 . 有人可以帮我吗?我是加密新手,无法确切地知道我哪里出错了 .

2 回答

  • 0

    这可能是因为您的错误解释 . 你说:

    我不使用盐,所以没有IV(应该是null) .

    但根本没有理由为什么会这样 . EVP_BytesToKey 方法提供了密钥和IV . 关键显然是正确的,但IV不是 . 这将导致纯文本中的随机字符(IV仅更改第一个块) . 由于此块可能包含控制字符等等,因此可能无法很好地显示 .

    请记住,盐和IV可能有一些共同点(不应重复,可以公开等),但它们在密码学中是完全不同的概念 .

    请再次尝试使用您的Qt代码,这次打印出IV以及密钥......

  • 0

    我现在通过试验和错误解决了空初始化向量的问题,尽管我不知道为什么以下是一个问题 . 也许有人可以向我解释 .

    换行: int nrounds = 28; 就行了 .

    如果我在其中放入除 28 之外的任何其他数字,则会生成IV,当我在mcrypt中使用它后,密文将以正确的方式解密 . 使用openssl-function EVP_BytesToKey() 生成带有 28 轮的密钥为什么会出现问题?我现在把它减少到 5 轮,但我很好奇这个问题是否可能再次发生,密码轮组合有可能产生这样的Null-IV .

    我真的不知道如何在这个函数中处理IV生成的过程 .

相关问题