C++;AES加密被截断为16个字符 我已经在C++中工作过一个函数,它使用CBC做AES 256加密。p>

C++;AES加密被截断为16个字符 我已经在C++中工作过一个函数,它使用CBC做AES 256加密。p>,c++,encryption,C++,Encryption,我不久前写过这个方法,所以很遗憾我记不起代码是从哪里来的,但后来我发现我有一个问题,如果要加密的字符串超过16个字符,那么只有字符串的前16个字符被加密 代码如下: string Encryption::encryptOrDecrypt(string stringToEncrypt, Mode mode) { HelperMethods helperMethods; try { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_ne

我不久前写过这个方法,所以很遗憾我记不起代码是从哪里来的,但后来我发现我有一个问题,如果要加密的字符串超过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;
    }

}
string Encryption::encryptOrDecrypt(string stringToEncrypt,模式)
{
帮助方法帮助方法;
尝试
{
EVP_CIPHER_CTX*CTX=EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(CTX);
无符号字符密钥[33]=“我的密钥”;
无符号字符iv[17]=“我的四”;
如果(模式==解密)
{
stringToEncrypt=helperMethods.base64解码(stringToEncrypt);
}
矢量加密;
大小\u t最大\u输出长度=stringToEncrypt.length()+16-(stringToEncrypt.length()%16);
//大小\u t最大输出长度=16-(stringToEncrypt.length()%16);
加密。调整大小(最大输出长度);
EVP_CipherInit_ex(ctx,EVP_aes_256_cbc(),NULL,密钥,iv,模式);
//EVP_CipherUpdate可以一次加密您的所有数据,您也可以这样做
//一次一小块。
int实际_大小=0;
执行副总裁密码更新(ctx,
&加密的[0],&U实际大小,
重新解释强制转换(&stringToEncrypt[0]),stringToEncrypt.size();
//EVP\u CipherFinal\u ex是应用填充的。如果您的数据
//块大小的倍数,您将得到一个额外的AES块填充
//除了填充物什么都没有。
int final_size=0;
执行副总裁(ctx、加密[实际大小]、最终大小);
实际_尺寸+=最终_尺寸;
加密。调整大小(实际大小);
char*buff_str=(char*)malloc(加密的.size()*2+1);
memset(buff_str,0,(encrypted.size()*2+1));
char*buff_ptr=buff_str;
尺寸指数=0;
对于(索引=0;索引
我已经仔细阅读了代码,看看问题可能出在哪里,但我看不出任何原因,这可能是一个愚蠢的简单问题

size\u t max\u output\u len
是768(实际字符串是752),所以我认为这是+16填充,但我不确定这是否也应该是768,但由于方法本身设置了它,所以不确定


当该方法完成时,传递到EVP\u CipherFinal\u ex的指针
int final\u size
变为16,并且
实际\u size
也是768,因此不确定问题出在哪里

我想我已经解决了这个问题,尽管我不能100%确定为什么这个方法有效,而原来的方法却没有

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

而不是

string encryptedString = buff_str;
我已将其更改为以下内容

int i = 0;
stringstream encryptedStringStream;

for (i = 0; i < index; i++)
{
    encryptedStringStream << buff_str[i];
}
string encryptedString = encryptedStringStream.str();
inti=0;
stringstream加密stringstream;
对于(i=0;iencryptedStringStream我想我已经解决了这个问题,尽管不是100%确定为什么这个方法有效,而原来的方法无效

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

而不是

string encryptedString = buff_str;
我已将其更改为以下内容

int i = 0;
stringstream encryptedStringStream;

for (i = 0; i < index; i++)
{
    encryptedStringStream << buff_str[i];
}
string encryptedString = encryptedStringStream.str();
inti=0;
stringstream加密stringstream;
对于(i=0;i
EVP\u CipherFinal\u ex(ctx,&加密的[实际大小],&最终大小)中的encryptedStringStream;actual_size+=final_size;
实际_size
是否更新为大于0?如果是这样,您将在远离数据开头的位置传递输出缓冲区。我仅假设
实际_size
EVP_CipherUpdate
中更改以获得“实际大小”我不确定您使用的密码函数是如何工作的。
actual_size
最初为0,然后当
EVP_CipherUpdate
接收到作为指针的实际_size时,它变为752,然后在
EVP_CipherFinal_ex
之后被称为
actual_size
变为768。不确定您所说的
actual_size是什么意思
仅用于调整向量大小,它不会再次作为输出的一部分使用?您正在从包含加密数据的
char*
创建
encryptedString
。是否有可能加密数据在位置17处有
\0
字节,因此您会得到截断的字符串?从外观上看,它不像t调试时的内容我想我已经找到了解决方法,因此添加了一个答案。感谢您的建议,我不确定为什么我的工作方法在
EVP\u CipherFinal\u ex(ctx,&加密[实际大小],&最终大小)中有效;actual_size+=final_size;
实际_size
是否更新为大于0?如果是这样,您将在远离数据开头的位置传递输出缓冲区。我仅假设
实际_size
EVP_CipherUpdate
中更改以获得“实际大小”我不确定您正在使用的密码功能是如何工作的。
actual_size
最初为0,然后当
EVP_CipherUpdate
接收到作为指针的实际_size时,它变为75