【问题标题】:AES decryption result varies after openssl upgradeopenssl升级后AES解密结果不同
【发布时间】:2015-12-23 17:04:10
【问题描述】:

我链接到 openssl 0.98 的代码具有 AES 解密功能,运行良好。

这是代码。

   const int bits = 256;
        AES_KEY key;
        iRes = AES_set_decrypt_key((const unsigned char *)szSecretKey, bits, &key);

        unsigned char szSigBytes[MAX_PATH] = "";
        unsigned char *pSigBytes = szSigBytes;
        unsigned char *pSignature = szSignature;
        AES_decrypt(pSignature, pSigBytes, &key);
        AES_decrypt(pSignature + 16, pSigBytes + 16, &key);

        cout<<pSigBytes<<endl;

但是,在迁移到 openssl 1.0.1p 后,我不得不使用 EVP 函数,因为非 EVP 函数在 FIPS 模式下失败。于是我将代码修改为

EVP_CIPHER_CTX *ctx;    
            int len;


            int plaintext_len;
            int ciphertext_len = strlen((const char*)in);

            if(!(ctx = EVP_CIPHER_CTX_new()));


            if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
            return;

          if(1 != EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len))
            return;

          if(1 != EVP_DecryptUpdate(ctx, out + 16, &len, in + 16, ciphertext_len - len))
            return; 

          EVP_DecryptFinal_ex(ctx, out + len, &len); 

          EVP_CIPHER_CTX_free(ctx);

结果几乎是匹配的,但是对于最后几个字符中的一些。 任何想法,我在这里做错了什么?

编辑:我看到在使用 EVP_DecryptUpdate 时,后 16 个字节没有被解密。

我已将第二个 16 字节提取到一个数组中并尝试对其进行解密。我看到它在我使用 AES_decrypt 时成功,但在我使用 EVP_DecryptUpdate 时返回“”。 密码长度只有 2 个字节。这会是解密失败的原因吗?

请看下面修改后的代码。

    unsigned char temp[MAX_PATH] = "BoQ=\n";
    unsigned char result[MAX_PATH] = "";

    unsigned char data[MAX_PATH] = "";
    Decode(temp, data);


    //Decrypting with AES_Decrypt


   AES_KEY key;

unsigned char DecodedSecretKey[MAX_PATH];
ZeroMemory(DecodedSecretKey, MAX_PATH);
Decode(secretKey, DecodedSecretKey);


AES_set_decrypt_key((const unsigned char *)DecodedSecretKey, 256, &key);

AES_decrypt(data, result, &key);//result returns the proper result

/////////////////////////////////////// ///////////////////////////////////////// ///////////

//Decrypting with EVP_DecryptUpdate

EVP_CIPHER_CTX *ctx;    
        int len;


        int plaintext_len;
        int ciphertext_len = strlen((const char*)data);

        if(!(ctx = EVP_CIPHER_CTX_new()));


        if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, SecretKey, NULL))
        return;

      if(1 != EVP_DecryptUpdate(ctx, result, &len, data, ciphertext_len))
        return;


      EVP_DecryptFinal_ex(ctx, result + len, &len); 

      EVP_CIPHER_CTX_free(ctx);
//Here the array result is always empty

【问题讨论】:

  • 不推荐ECB模式,见ECB模式example image
  • 那么我应该使用哪种模式?对于非 EVP 版本,即 AES_decrypt,没有指定模式。那么如何确定 EVP_Decrypt 函数应该使用哪种模式呢?
  • 通常使用 CBC ode,这有时是默认值。存在 iv 的问题,它通常应该是随机字节,通常预先添加到加密数据中。但所有这些问题只有在需要安全性时才需要,只是加密不会产生安全性。
  • 你应该使用AES_encrypt和朋友。这是一个纯软件实现,因此您不会享受硬件支持,如 AES-NI。您应该使用EVP_* 函数。请参阅 OpenSSL wiki 上的 EVP Symmetric Encryption and Decryption。事实上,您可能应该使用经过身份验证的加密,因为它提供 机密性和真实性。请参阅 OpenSSL wiki 上的 EVP Authenticated Encryption and Decryption

标签: c visual-c++ openssl aes


【解决方案1】:

EVP_DecryptUpdate(ctx, out, &amp;len, in, ciphertext_len) 的用法是错误的。

这里,len 必须初始化为out 数组中的字节数。据我所知,如果您使用len 作为全长和cipthertext_len 调用一次,它必须解密所有加密文本。不需要第二次调用。要么:

len = <full length of buffer>;
EVP_DecryptUpdate(ctx, out, &len, in, ciphertext_len);

len = 16;
EVP_DecryptUpdate(ctx, out, &len, in, len);
len = 16;
EVP_DecryptUpdate(ctx, out+16, &len, in+16, len);

我更喜欢第一种方法。如果您需要特殊填充,则可以使用附加调用来处理最后一个块。

【讨论】:

  • 它没有用。使用 EVP_DecryptUpdate 解密时的第二个 16 字节数据始终返回一个空字符串。我认为这就是问题所在。我已经修改了问题以指定这一点。请看一下
【解决方案2】:

我刚刚发现了问题。这真是一个非常愚蠢的事情。

int ciphertext_len = strlen((const char*)data);

我正在使用 strlen 确定加密字符串的长度,这是错误的,我只是通过艰难的方式学会了它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 2018-12-31
    • 2012-03-12
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多