AES CBC加密/解密仅解密前16个字节 [英] AES CBC encrypt/decrypt only decrypts the first 16 bytes

查看:158
本文介绍了AES CBC加密/解密仅解密前16个字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AES CBC和openssl进行一些工作,现在,我陷入了一个问题,即我无法像往常一样猜出问题所在.

I'm doing some work with AES CBC and openssl and for now, I'm stuck on a problem that i cannot guess what's wrong (as always).

给出小于16个字节长度的消息,则加密和解密过程可以正常工作,但是,如果消息大于16个字节,则解密仅对第16个第一个字节起作用.

Given a message less than 16 bytes length the process of encryption and decryption works fine, but when the message is greater than 16 bytes the decryption works only on the 16th first bytes.

当我呼叫aes.exe stackoverflow stackoverflow时,输出为:

Using:
IVector   = |000102030405060708090a0b0c0d0e0f|
Key       = |737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f|
Encrypted = |6c65219594c0dae778f9b5e84f018db6|

Encrypting : stackoverflow
With Key   : stackoverflow
Becomes    :  ??????¤le!òö++þx¨ÁÞO?ìÂ.

Using:
IVector   = |000102030405060708090a0b0c0d0e0f|
Key       = |737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f|
Decrypted = |737461636b6f766572666c6f77|

Decrypting :  ??????¤le!òö++þx¨ÁÞO?ìÂ
With Key   : stackoverflow
Becomes    : stackoverflow

当我呼叫aes.exe stackoverflowstackoverflow stackoverflow时,输出为:

Using:
IVector   = |000102030405060708090a0b0c0d0e0f|
Key       = |737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f|
Encrypted = |46172e3f7fabdcfc6c8b3e65aef175cddf8164236faf706112c15f5e765e49a5|

Encrypting : stackoverflowstackoverflow
With Key   : stackoverflow
Becomes    :  ??????¤F?.?¦½_³lï>e«±u-¯üd#o»pa?-_^v^IÑ.

Using:
IVector   = |000102030405060708090a0b0c0d0e0f|
Key       = |737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f|
Decrypted = |737461636b6f766572666c6f77737461257d434a1edcbc970bf5346ea2fc7bc2|

Decrypting :  ??????¤F?.?¦½_³lï>e«±u-¯üd#o»pa?-_^v^IÑ
With Key   : stackoverflow
Becomes    : stackoverflowsta%}CJ?_+ù?§4nó³{-.

我将为每个加密/解密调用提供随机IV,并在两种情况下将密码规范化为32个字节;我想念的是什么?有人知道吗?

I'm providing a random IV for each encryption/decryption call and normalizing the password at 32 bytes in both cases; what I'm missing? anyone knows?

源代码:

#include <vector>
#include <string>
#include <iostream>

// Make a Key of exactly 32 bytes, truncates or adds values if it's necessary
std::string AES_NormalizeKey(const void *const apBuffer, size_t aSize)
{
    static const unsigned char key32[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
    const char *const Buffer = reinterpret_cast<const char *>(apBuffer);
    std::string Result(reinterpret_cast<const char *>(key32), 32);
    std::copy(Buffer, Buffer + ((aSize < 32)? aSize: 32), Result.begin());
    return Result;
}

// Encrypt using AES cbc
std::string AESEncrypt(const void *const apBuffer, size_t aBufferSize, const void *const apKey, size_t aKeySize, std::string &aIVector)
{
    // Create IVector.
    unsigned char AES_IVector[16] = {0};
    std::srand(static_cast<int>(time(NULL)));
    std::generate(std::begin(AES_IVector), std::end(AES_IVector), std::rand);
    std::copy(std::begin(AES_IVector), std::end(AES_IVector), aIVector.begin());

    // Create key.
    const std::string Key(AES_NormalizeKey(apKey, aKeySize));
    AES_KEY EncryptKey;
    AES_set_encrypt_key(reinterpret_cast<const unsigned char *>(Key.c_str()), 256, &EncryptKey);

    // Encrypt.
    unsigned char AES_Encrypted[1024] = {0};
    AES_cbc_encrypt(static_cast<const unsigned char *>(apBuffer), AES_Encrypted, aBufferSize, &EncryptKey, AES_IVector, AES_ENCRYPT);
    const std::string Encrypted(reinterpret_cast<const char *>(AES_Encrypted), ((aBufferSize / 16) + 1) * 16);

    // Finish.
    return Encrypted;
};

// Decrypt using AES cbc
std::string AESDecrypt(const void *const apBuffer, size_t aBufferSize, const void *const apKey, size_t aKeySize, std::string &aIVector)
{
    // Read IVector.
    unsigned char AES_IVector[16] = {0};
    std::copy(aIVector.begin(), aIVector.end(), std::begin(AES_IVector));

    // Create Key.
    const std::string Key(AES_NormalizeKey(apKey, aKeySize));
    AES_KEY DecryptKey;
    AES_set_decrypt_key(reinterpret_cast<const unsigned char *>(Key.c_str()), 256, &DecryptKey);

    // Decrypt.
    unsigned char AES_Decrypted[1024] = {0};
    AES_cbc_encrypt(static_cast<const unsigned char *>(apBuffer), AES_Decrypted, aBufferSize, &DecryptKey, AES_IVector, AES_DECRYPT);
    const std::string Decrypted(reinterpret_cast<const char *>(AES_Decrypted));

    // Finish.
    return Decrypted;
};

// Entry point
int main(unsigned int argc, char **argv)
{
    typedef std::vector<const std::string> vs;
    vs a;

    for (vs::size_type Index = 0; Index < argc; ++Index)
    {
        a.push_back(argv[Index]);
    }

    if (a.size() == 3)
    {
        std::string IV("");

        std::string e(AESEncrypt(a.at(1).c_str(), a.at(1).size(), a.at(2).c_str(), a.at(2).size()), IV);
            std::cout << "Encrypting : " << a.at(1) << "\n"
                      << "With Key   : " << a.at(2) << "\n"
                      << "Becomes    : " << e << ".\n";

        std::string d(AESDecrypt(e.c_str(), e.size(), a.at(2).c_str(), a.at(2).size()), IV);
            std::cout << "Decrypting : " << e << "\n"
                      << "With Key   : " << a.at(2) << "\n"
                      << "Becomes    : " << d << ".\n";
    }

    return 0;
}

推荐答案

您的代码几乎是正确的,除了初始化向量由于内存损坏而被覆盖,密文的长度舍入不正确,并且std :: string当使用std :: string作为字节数组时,应使用:: data()代替std :: string :: c_str().将初始化向量复制到覆盖堆栈的空字符串中.然后,初始化向量被覆盖,因此AESDecrypt使用不同的值.我已包含源代码,其中包含了indiv的建议并解决了这些问题.与

Your code is almost correct, except that the initialization vector is being overwritten due to memory corruption, the length of the ciphertext is rounded incorrectly, and std::string::data() should be used instead of std::string::c_str() when using std::string as a byte array. The Initialization Vector is copied into the empty string overwriting the stack. Then the Initialization Vector gets overwritten so different value is used by AESDecrypt. I've included source code that incorporates indiv's suggestions and fixes these problems. When run with

aes "Hello World!" stackoverflow

一起运行时,将产生以下输出:

it produces the following output:


(Normalized key: 737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f)
Encrypting : Hello World!
With Key   : stackoverflow
Init Vec   : d8b1657d9e2317c93430994f59bb54eb
Becomes    : ��Йw�H���}�;E
(Normalized key: 737461636b6f766572666c6f770d0e0f101112131415161718191a1b1c1d1e1f)
Decrypting : ��Йw�H���}�;E
With Key   : stackoverflow
Init Vec   : d8b1657d9e2317c93430994f59bb54eb
Becomes    : Hello World!

#include <vector>
#include <string>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <initializer_list>
#include <openssl/aes.h>

typedef unsigned char byte;

template <size_t multiple> size_t round_up(const size_t len)
{
    if (len % multiple == 0) return len;
    else return ((len / multiple) + 1) * multiple;
}

std::ostream &print_buffer_as_hex(std::ostream &o, const unsigned char *buf, size_t size)
{
    o << std::hex << std::setfill('0');
    for( size_t i = 0; i < size; ++i )
    {
        o << std::setw(2) << static_cast<unsigned int>(buf[i]);
    }
    return o << std::dec;
}

inline std::ostream &operator<<(std::ostream &o, const std::vector<byte> &buf)
{
    return print_buffer_as_hex(o, reinterpret_cast<const unsigned char*>(&buf[0]), buf.size());
}

// Make a Key of exactly 32 bytes, truncates or adds values if it's necessary
std::string AES_NormalizeKey(const void *const apBuffer, size_t aSize)
{
    static const unsigned char key32[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
    const char *const Buffer = reinterpret_cast<const char *>(apBuffer);
    std::string Result(reinterpret_cast<const char *>(key32), 32);
    std::copy(Buffer, Buffer + ((aSize < 32)? aSize: 32), Result.begin());
    return Result;
}

// Encrypt using AES cbc
std::string AESEncrypt(const void *const apBuffer, size_t aBufferSize, const void *const apKey, size_t aKeySize, std::vector<byte> &aIVector)
{
    // Create IVector.
    unsigned char AES_IVector[AES_BLOCK_SIZE] = {0};
    std::srand(static_cast<int>(time(NULL)));
    std::generate(std::begin(AES_IVector), std::end(AES_IVector), std::rand);
    aIVector.resize(sizeof(AES_IVector));
    std::copy(std::begin(AES_IVector), std::end(AES_IVector), aIVector.begin());

    // Create key.
    const std::string Key(AES_NormalizeKey(apKey, aKeySize));
    std::cout << "(Normalized key: ";
    print_buffer_as_hex(std::cout, (const unsigned char*)Key.data(), Key.size()) << ")\n";
    AES_KEY EncryptKey;
    AES_set_encrypt_key(reinterpret_cast<const unsigned char *>(Key.data()), 256, &EncryptKey);

    // Encrypt.
    unsigned char AES_Encrypted[1024] = {0};
    AES_cbc_encrypt(static_cast<const unsigned char *>(apBuffer), AES_Encrypted, aBufferSize, &EncryptKey, AES_IVector, AES_ENCRYPT);
    const std::string Encrypted(reinterpret_cast<const char *>(AES_Encrypted), round_up<AES_BLOCK_SIZE>(aBufferSize));

    // Finish.
    return Encrypted;
};

// Decrypt using AES cbc
std::string AESDecrypt(const void *const apBuffer, size_t aBufferSize, const void *const apKey, size_t aKeySize, std::vector<byte> &aIVector)
{
    // Read IVector.
    unsigned char AES_IVector[AES_BLOCK_SIZE] = {0};
    std::copy(aIVector.begin(), aIVector.end(), std::begin(AES_IVector));

    // Create Key.
    const std::string Key(AES_NormalizeKey(apKey, aKeySize));
    std::cout << "(Normalized key: ";
    print_buffer_as_hex(std::cout, (const unsigned char*)Key.data(), Key.size()) << ")\n";
    AES_KEY DecryptKey;
    AES_set_decrypt_key(reinterpret_cast<const unsigned char *>(Key.data()), 256, &DecryptKey);

    // Decrypt.
    unsigned char AES_Decrypted[1024] = {0};
    AES_cbc_encrypt(static_cast<const unsigned char *>(apBuffer), AES_Decrypted, aBufferSize, &DecryptKey, AES_IVector, AES_DECRYPT);
    const std::string Decrypted(reinterpret_cast<const char *>(AES_Decrypted));

    // Finish.
    return Decrypted;
};

// Entry point
int main(int argc, char **argv)
{
    typedef std::vector<std::string> vs;
    vs a;

    for (vs::size_type Index = 0; Index < static_cast<unsigned>(argc); ++Index)
    {
        a.push_back(argv[Index]);
    }

    if (a.size() == 3)
    {
        std::vector<byte> IV;

        std::string e(AESEncrypt(a.at(1).data(), a.at(1).size(), a.at(2).data(), a.at(2).size(), IV));
            std::cout << "Encrypting : " << a.at(1) << "\n"
                      << "With Key   : " << a.at(2) << "\n"
                      << "Init Vec   : " << IV << "\n"
                      << "Becomes    : " << e << "\n";

        std::string d(AESDecrypt(e.data(), e.size(), a.at(2).data(), a.at(2).size(), IV));
            std::cout << "Decrypting : " << e << "\n"
                      << "With Key   : " << a.at(2) << "\n"
                      << "Init Vec   : " << IV << "\n"
                      << "Becomes    : " << d << "\n";
    }
    std::cout.flush();

    return 0;
}

这篇关于AES CBC加密/解密仅解密前16个字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆