首页 > 解决方案 > C++ AES 加密被截断为 16 个字符

问题描述

我有一个不久前在 C++ 中工作过的函数,它使用 CBC 进行 AES 256 加密。

我前段时间写了这个方法,所以不幸的是我不记得我从哪里得到代码,但我发现我有一个问题,如果被加密的字符串超过 16 个字符,它只有前 16 个字符被加密的字符串。

代码如下:

string Encryption::encryptOrDecrypt(string stringToEncrypt, Mode mode)
{
    HelperMethods helperMethods;
    try
    {
        EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
        EVP_CIPHER_CTX_init(ctx);

        unsigned char key[33] = "my_key";
        unsigned char iv[17] = "my_iv";

        if (mode == Decrypt)
        {
            stringToEncrypt = helperMethods.base64Decode(stringToEncrypt);
        }
        vector<unsigned char> encrypted;
        size_t max_output_len = stringToEncrypt.length() + 16 - (stringToEncrypt.length() % 16);
        //size_t max_output_len = 16 - (stringToEncrypt.length() % 16);
        encrypted.resize(max_output_len);

        EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, mode);

        // EVP_CipherUpdate can encrypt all your data at once, or you can do
            // small chunks at a time.
        int actual_size = 0;
        EVP_CipherUpdate(ctx,
            &encrypted[0], &actual_size,
            reinterpret_cast<unsigned char *>(&stringToEncrypt[0]), stringToEncrypt.size());

        // EVP_CipherFinal_ex is what applies the padding.  If your data is
        // a multiple of the block size, you'll get an extra AES block filled
        // with nothing but padding.
        int final_size = 0;
        EVP_CipherFinal_ex(ctx, &encrypted[actual_size], &final_size);
        actual_size += final_size;

        encrypted.resize(actual_size);

        char * buff_str = (char*)malloc(encrypted.size() * 2 + 1);
        memset(buff_str, 0, (encrypted.size() * 2 + 1));
        char * buff_ptr = buff_str;

        size_t index = 0;
        for (index = 0; index < encrypted.size(); ++index)
        {
            buff_ptr += sprintf(buff_ptr, "%c", encrypted[index]);

        }
        EVP_CIPHER_CTX_cleanup(ctx);
        EVP_CIPHER_CTX_free(ctx);
        if (mode == Encrypt)
        {
            string encryptedString = buff_str;
            free(buff_str);
            return helperMethods.base64Encode(encryptedString.c_str(), encryptedString.length());
        }
        else
        {
            string decryptedString = buff_str;
            free(buff_str);
            return decryptedString;
        }
    }
    catch (exception ex)
    {
        return stringToEncrypt;
    }

}

我已经通过代码查看问题可能出在哪里,但我看不出任何原因,这可能是愚蠢的简单。

size_t max_output_len768(实际字符串是 752),所以我相信这是 +16 的填充,但我不确定这是否也应该是 768,但由于方法本身不确定。

int final_size当该方法完成时,传入的指针EVP_CipherFinal_ex变为 16,并且actual_size也是 768,因此不确定问题出在哪里。

标签: c++encryption

解决方案


我想我已经找到了问题所在,尽管不是 100% 确定为什么会这样,而原来的方式却没有。

在调试时查看缓冲区的内容,我不相信它是一个空字节,但我已将其更改为以下似乎可以解决它的内容。

代替

string encryptedString = buff_str;

我已将其更改为以下

int i = 0;
stringstream encryptedStringStream;

for (i = 0; i < index; i++)
{
    encryptedStringStream << buff_str[i];
}
string encryptedString = encryptedStringStream.str();

推荐阅读