C ++ AES-шифрование усекается до 16 символов - PullRequest
1 голос
/ 16 октября 2019

У меня есть функция, над которой я работал некоторое время назад в C ++, которая выполняет шифрование AES 256 с использованием CBC.

Я написал метод некоторое время назад, поэтому, к сожалению, не могу вспомнить, откуда я взял код, но с тех пор я обнаружил, что у меня есть проблема, где, если зашифрованная строка превышает 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_len - это 768 (фактическая строка - 752), так что я считаю, что это +16 для заполнения, но я не уверен, должно ли это быть 768, но так как метод сам устанавливает это неконечно.

Указатель int final_size, который передается в EVP_CipherFinal_ex, становится 16, когда этот метод завершается, и actual_size также равен 768, поэтому не уверен, где проблема.

1 Ответ

0 голосов
/ 16 октября 2019

Я думаю, что понял проблему, хотя не уверен на 100%, почему это работает, а оригинальный способ - нет.

Я не верю, что просмотр содержимого буфера при отладке является нулевым байтом, но я изменил его на следующий, который, кажется, разрешает это.

Вместо

string encryptedString = buff_str;

Я изменил его на следующее

int i = 0;
stringstream encryptedStringStream;

for (i = 0; i < index; i++)
{
    encryptedStringStream << buff_str[i];
}
string encryptedString = encryptedStringStream.str();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...