简体   繁体   中英

AES | Encrypt with OpenSSL, decrypt with mcrypt

I am using the following function to encrypt my data via the OpenSSL Library in Qt:

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" is in that case "12345678901234567890123456789012abc" .
"password" is "1hA!dh==sJAh48S8Ak!?skiitFi120xX" .

So....if I got that right, then EVP_BytesToKey() should generate a key out of the password and supplied data to decrypt the string with later.

To Base64-Encoded that key would be: "aQkrZD/zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE="
I don't use a salt, so no IV (should be null).

So QByteArray bkey in Base64 leaves me with "aQkrZD/zwMFU0VAqjYSWsrkfJfS28pQJXym20UEYNnE="
QByteArray bvi is giving me Null

The encryptet text is "CiUqILbZo+WJBr19IiovRVc1dqGvrastwo0k67TTrs51HB8AbJe8S4uxvB2D7Dkr" .

Now I am using the following PHP function to decrypt the ciphertext with the generated key again:

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

Now I'd expect a response like "12345678901234567890123456789012abc" .
What I get is "7890123456789012abc" .

My string seems to be decrypted in the right way, but it's cut in half and only the last 19 characters are displayed. Can someone please help me with that? I'm new to encryption and can't really figure out where exactly I went wrong.

This is probably because of a misinterpretation from your part. You say:

I don't use a salt, so no IV (should be null).

But there is no reason at all why that would be the case. The EVP_BytesToKey method provided both a key and an IV. The key is obviously correct, but the IV is not. This will result in random characters in your plain text (the IV only changes the first block). As this block will likely contain control characters and what more, it may not display well.

Remember that a salt and IV may have a few things in common (should not be repeated, can be public etc.) but that they are entirely different concepts in cryptography.

Please try again with your Qt code, and this time print out the IV as well as the key...

I solved the problem with the empty initialisation vector by trial and error now, though I have no clue why the following was a problem at all. Maybe someone can explain that to me.

Changing the line: int nrounds = 28; did the trick.

If i put any other number than 28 in there, an IV is generated and when I use it afterwards in mcrypt the ciphertext is decrypted in the correct way. Why was it a problem to generate the key with 28 rounds with the openssl-function EVP_BytesToKey() ? I reduced it to 5 rounds now, but I'm curious whether this problem might happen again with a password-rounds-combination that has the possibility to generate such a Null-IV.

I don't realy know how the process of the IV generation is handled in this function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM