C++ OpenSSL AES 128 CBC\0崩溃加密字符*

C++ OpenSSL AES 128 CBC\0崩溃加密字符*,c++,openssl,char,aes,C++,Openssl,Char,Aes,我对OpenSSL AES有问题(我使用AES.h): 获取大约5000个字符的二进制文件(.pdf、.jpg)或一些.xml、.txt,然后我加密base64 当我尝试enrypt AES时,我得到了错误的大小(随机400、200、50),我的AESKey是来自chars的随机128位:[abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyzo123456789,.-@#和*oeOE'] 我认为问题是“\0”加密字符,但我不知道我可以勒索输入吗 (

我对OpenSSL AES有问题(我使用AES.h):

  • 获取大约5000个字符的二进制文件(.pdf、.jpg)或一些.xml、.txt,然后我加密base64

  • 当我尝试enrypt AES时,我得到了错误的大小(随机400、200、50),我的AESKey是来自chars的随机128位:[abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyzo123456789,.-@#和*oeOE']

  • 我认为问题是“\0”加密字符,但我不知道我可以勒索输入吗 (字符串可以使用\0元素保存字符数组,但未签名字符*和字符*被中止)

    这是我的代码:

    std::string PFHelper::ASE_encode(std::string in, wchar_t* KS)
    {
    //const unsigned char* aes_input = reinterpret_cast<const unsigned char *> (in.c_str());
    unsigned char* aes_input = new unsigned char[in.length()];
    strcpy((char*)aes_input, in.c_str());
    std::string KS_string = PFHelper::ConvertFromUtf8ToString(KS);
    unsigned char* aes_key = new unsigned char[16];
    strcpy((char*)aes_key, KS_string.c_str());
    /* Input data to encrypt */
    unsigned char iv[AES_BLOCK_SIZE];
    memset(iv, 0x00, AES_BLOCK_SIZE);
    const size_t encslength = ((in.length() + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
    /* Buffers for Encryption and Decryption */
    unsigned char * enc_out = new unsigned char [encslength];
    //unsigned char * dec_out = new unsigned char[in.length()];
    memset(enc_out, 0, encslength);
    //memset(dec_out, 0, in.length());
    AES_KEY enc_key;
    AES_set_encrypt_key(aes_key, 128, &enc_key);
    AES_cbc_encrypt(aes_input, enc_out, encslength, &enc_key, iv, AES_ENCRYPT);
    
    //AES_KEY decrypt;
    //memset(iv, 0x00, AES_BLOCK_SIZE);
    
    
    //AES_cbc_encrypt((unsigned char*)enc_out, dec_out, encslength, &decrypt, iv, AES_DECRYPT);
    //std::string returned = ConvertFromUnsignedCharToString(enc_out);
    memset(aes_key, 0x00, 16);
    memset(aes_input, 0x00, in.length());
    return ConvertFromUnsignedCharToString(enc_out);
    }
    
    std::string PFHelper::ASE_encode(std::string in,wchar_t*KS)
    {
    //const unsigned char*aes_input=reinterpret_cast(in.c_str());
    无符号字符*aes_输入=新的无符号字符[in.length()];
    strcpy((char*)aes_输入,在.c_str()中);
    std::string KS_string=PFHelper::ConvertFromUtf8ToString(KS);
    无符号字符*aes_key=新的无符号字符[16];
    strcpy((char*)aes_key,KS_string.c_str());
    /*输入要加密的数据*/
    无符号字符iv[AES_块大小];
    内存集(iv,0x00,AES_块大小);
    const size_t encslength=((in.length()+AES_BLOCK_size)/AES_BLOCK_size)*AES_BLOCK_size;
    /*用于加密和解密的缓冲区*/
    unsigned char*enc_out=新的unsigned char[encslength];
    //unsigned char*dec_out=新的unsigned char[in.length()];
    memset(enc_out,0,encslength);
    //memset(dec_out,0,in.length());
    AES_键和enc_键;
    AES_设置_加密_密钥(AES_密钥、128和enc_密钥);
    AES_cbc_加密(AES_输入、加密输出、加密长度和加密密钥、iv、AES_加密);
    //AES_密钥解密;
    //内存集(iv,0x00,AES_块大小);
    //AES_cbc_encrypt((无符号字符*)enc_out、dec_out、encslength和decrypt、iv、AES_decrypt);
    //返回的字符串=ConvertFromUnsignedCharToString(enc_out);
    memset(aes_键,0x00,16);
    memset(aes_输入,0x00,in.length());
    返回ConvertFromUnsignedCharToString(enc_out);
    }
    
    样本值:

    KS(埃斯基):L“F-ZTNW meOJLK1s5”

    输入(5464个字符):PD94BWGDMVYC2LVBJ0IMS4WIBLBMNVZGLUZZ0IVVR

    out(51chars):“阿尔法·奥克萨恩·瓦克萨伊·伊克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊·瓦克萨伊

    我尝试EVP和典型的字符键,问题是一样的

    //set back to normal
    unsigned char* aes_input = new unsigned char[in.length()];
    strcpy((char*)aes_input, in.c_str());
    
    unsigned char* dec_out = new unsigned char[in.length()];
    memset(dec_out, 0, in.length());
    dec_out[in.length()] = '\0';
    
    /* A 256 bit key */
    unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
    
    /* A 128 bit IV */
    unsigned char *iv = (unsigned char *)"01234567890123456";
    
    int lenght;
    int c_len = in.length() + AES_BLOCK_SIZE;
    //Set up encryption
    int f_len = 0;
    EVP_CIPHER_CTX *ctx;
    ctx = EVP_CIPHER_CTX_new();
    if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)
    {
        wcout << L"1";
    }
    if (EVP_EncryptUpdate(ctx, dec_out, &lenght, aes_input, in.length()) != 1)
    {
        wcout << L"2";
    }
    if (EVP_EncryptFinal_ex(ctx, dec_out, &lenght) != 1)
    {
        wcout << L"3";
    }
    return ConvertFromUnsignedCharToString(dec_out);
    }
    
    //恢复正常
    无符号字符*aes_输入=新的无符号字符[in.length()];
    strcpy((char*)aes_输入,在.c_str()中);
    unsigned char*dec_out=新的unsigned char[in.length()];
    memset(dec_out,0,in.length());
    dec_out[in.length()]='\0';
    /*256位密钥*/
    无符号字符*键=(无符号字符*)“012345678901234567890123456789012345678901”;
    /*128位IV*/
    无符号字符*iv=(无符号字符*)“01234567890123456”;
    内部长度;
    int c_len=in.length()+AES_BLOCK_SIZE;
    //设置加密
    int f_len=0;
    EVP_CIPHER_CTX*CTX;
    ctx=EVP_CIPHER_ctx_new();
    if(EVP_EncryptInit_ex(ctx,EVP_aes_256_cbc(),NULL,key,iv)!=1)
    {
    
    wcout下面的示例演示了如何在使用OpenSSL的EVP接口时使用
    std::strings
    来管理缓冲区。它还避免了您正在进行的额外复制。您仍然需要改进密钥策略

    你应该提供一个ZooZeIe分配器。你应该考虑一个.< /P> 用

    g++-std=c++11 test.cxx-o test.exe-lcrypto编译它

    #include <iostream>
    #include <string>
    #include <memory>
    #include <stdexcept>
    using namespace std;
    
    #include <openssl/evp.h>
    #include <openssl/rand.h>
    
    static const unsigned int KEY_SIZE = 16;
    static const unsigned int BLOCK_SIZE = 16;
    
    typedef unsigned char byte;
    using EVP_CIPHER_CTX_free_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>;
    
    void gen_keys(byte key[KEY_SIZE], byte iv[BLOCK_SIZE]);
    void encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ptext, string& ctext);
    void decrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ctext, string& rtext);
    
    int main(int argc, char* argv[])
    {
      // plaintext, ciphertext, recovered text
      string ptext = "Now is the time for all good men to come to the aide of their country";
      string ctext, rtext;
    
      byte key[KEY_SIZE], iv[BLOCK_SIZE];
      gen_keys(key, iv);
    
      encrypt(key, iv, ptext, ctext);
      decrypt(key, iv, ctext, rtext);
    
      cout << "Recovered message:\n" << rtext << endl;
    
      return 0;
    }
    
    void gen_keys(byte key[KEY_SIZE], byte iv[BLOCK_SIZE])
    {
        int rc = RAND_bytes(key, KEY_SIZE);
        if (rc != 1)
          throw runtime_error("RAND_bytes key failed");
    
        rc = RAND_bytes(iv, BLOCK_SIZE);
        if (rc != 1)
          throw runtime_error("RAND_bytes for iv failed");
    }
    
    void encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ptext, string& ctext)
    {
        EVP_CIPHER_CTX_free_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
        int rc = EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL, key, iv);
        if (rc != 1)
          throw runtime_error("EVP_EncryptInit_ex failed");
    
        // Cipher text will be upto 16 bytes larger than plain text
        ctext.resize(ptext.size()+16);
    
        int out_len1 = (int)ctext.size();    
        rc = EVP_EncryptUpdate(ctx.get(), (byte*)&ctext[0], &out_len1, (const byte*)&ptext[0], (int)ptext.size());
        if (rc != 1)
          throw runtime_error("EVP_EncryptUpdate failed");
    
        int out_len2 = (int)ctext.size() - out_len1;
        rc = EVP_EncryptFinal_ex(ctx.get(), (byte*)&ctext[0]+out_len1, &out_len2);
        if (rc != 1)
          throw runtime_error("EVP_EncryptFinal_ex failed");
    
        ctext.resize(out_len1 + out_len2);
    }
    
    void decrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ctext, string& rtext)
    {
        EVP_CIPHER_CTX_free_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
        int rc = EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL, key, iv);
        if (rc != 1)
          throw runtime_error("EVP_DecryptInit_ex failed");
    
        // Recovered text will be smaller than cipher text, not larger
        rtext.resize(ctext.size());
    
        int out_len1 = (int)rtext.size();    
        rc = EVP_DecryptUpdate(ctx.get(), (byte*)&rtext[0], &out_len1, (const byte*)&ctext[0], (int)ctext.size());
        if (rc != 1)
          throw runtime_error("EVP_DecryptUpdate failed");
    
        int out_len2 = (int)rtext.size() - out_len1;
        rc = EVP_DecryptFinal_ex(ctx.get(), (byte*)&rtext[0]+out_len1, &out_len2);
        if (rc != 1)
          throw runtime_error("EVP_DecryptFinal_ex failed");
    
        rtext.resize(out_len1 + out_len2);
    }
    
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    #包括
    #包括
    静态常量无符号整数键大小=16;
    静态常量无符号整数块大小=16;
    typedef无符号字符字节;
    使用EVP_CIPHER_CTX_free_ptr=std::unique_ptr;
    无效gen_键(字节键[键大小],字节iv[块大小]);
    无效加密(常量字节密钥[密钥大小]、常量字节iv[块大小]、常量字符串和ptext、字符串和ctext);
    无效解密(常量字节密钥[密钥大小]、常量字节iv[块大小]、常量字符串和ctext、字符串和rtext);
    int main(int argc,char*argv[])
    {
    //明文、密文、恢复文本
    string ptext=“现在是所有好人来帮助他们国家的时候了”;
    字符串ctext,rtext;
    字节键[键大小],iv[块大小];
    通用钥匙(钥匙,iv);
    加密(密钥、iv、ptext、ctext);
    解密(密钥、iv、ctext、rtext);
    
    cout下面的示例演示了如何在使用OpenSSL的EVP接口时使用
    std::strings
    来管理缓冲区。它还避免了您正在进行的额外复制。您仍然需要改进密钥策略

    你应该提供一个ZooZeIe分配器。你应该考虑一个.< /P> 用

    g++-std=c++11 test.cxx-o test.exe-lcrypto编译它

    #include <iostream>
    #include <string>
    #include <memory>
    #include <stdexcept>
    using namespace std;
    
    #include <openssl/evp.h>
    #include <openssl/rand.h>
    
    static const unsigned int KEY_SIZE = 16;
    static const unsigned int BLOCK_SIZE = 16;
    
    typedef unsigned char byte;
    using EVP_CIPHER_CTX_free_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>;
    
    void gen_keys(byte key[KEY_SIZE], byte iv[BLOCK_SIZE]);
    void encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ptext, string& ctext);
    void decrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ctext, string& rtext);
    
    int main(int argc, char* argv[])
    {
      // plaintext, ciphertext, recovered text
      string ptext = "Now is the time for all good men to come to the aide of their country";
      string ctext, rtext;
    
      byte key[KEY_SIZE], iv[BLOCK_SIZE];
      gen_keys(key, iv);
    
      encrypt(key, iv, ptext, ctext);
      decrypt(key, iv, ctext, rtext);
    
      cout << "Recovered message:\n" << rtext << endl;
    
      return 0;
    }
    
    void gen_keys(byte key[KEY_SIZE], byte iv[BLOCK_SIZE])
    {
        int rc = RAND_bytes(key, KEY_SIZE);
        if (rc != 1)
          throw runtime_error("RAND_bytes key failed");
    
        rc = RAND_bytes(iv, BLOCK_SIZE);
        if (rc != 1)
          throw runtime_error("RAND_bytes for iv failed");
    }
    
    void encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ptext, string& ctext)
    {
        EVP_CIPHER_CTX_free_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
        int rc = EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL, key, iv);
        if (rc != 1)
          throw runtime_error("EVP_EncryptInit_ex failed");
    
        // Cipher text will be upto 16 bytes larger than plain text
        ctext.resize(ptext.size()+16);
    
        int out_len1 = (int)ctext.size();    
        rc = EVP_EncryptUpdate(ctx.get(), (byte*)&ctext[0], &out_len1, (const byte*)&ptext[0], (int)ptext.size());
        if (rc != 1)
          throw runtime_error("EVP_EncryptUpdate failed");
    
        int out_len2 = (int)ctext.size() - out_len1;
        rc = EVP_EncryptFinal_ex(ctx.get(), (byte*)&ctext[0]+out_len1, &out_len2);
        if (rc != 1)
          throw runtime_error("EVP_EncryptFinal_ex failed");
    
        ctext.resize(out_len1 + out_len2);
    }
    
    void decrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const string& ctext, string& rtext)
    {
        EVP_CIPHER_CTX_free_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
        int rc = EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL, key, iv);
        if (rc != 1)
          throw runtime_error("EVP_DecryptInit_ex failed");
    
        // Recovered text will be smaller than cipher text, not larger
        rtext.resize(ctext.size());
    
        int out_len1 = (int)rtext.size();    
        rc = EVP_DecryptUpdate(ctx.get(), (byte*)&rtext[0], &out_len1, (const byte*)&ctext[0], (int)ctext.size());
        if (rc != 1)
          throw runtime_error("EVP_DecryptUpdate failed");
    
        int out_len2 = (int)rtext.size() - out_len1;
        rc = EVP_DecryptFinal_ex(ctx.get(), (byte*)&rtext[0]+out_len1, &out_len2);
        if (rc != 1)
          throw runtime_error("EVP_DecryptFinal_ex failed");
    
        rtext.resize(out_len1 + out_len2);
    }
    
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    #包括
    #包括
    静态常量无符号整数键大小=16;
    静态常量无符号整数块大小=16;
    typedef无符号字符字节;
    使用EVP_CIPHER_CTX_free_ptr=std::unique_ptr;
    无效gen_键(字节键[键大小],字节iv[块大小]);
    无效加密(常量字节密钥[密钥大小]、常量字节iv[块大小]、常量字符串和ptext、字符串和ctext);
    无效解密(常量字节密钥[密钥大小]、常量字节iv[块大小]、常量字符串和ctext、字符串和rtext);
    int main(int argc,char*argv[])
    {
    //明文、密文、恢复文本
    string ptext=“现在是所有好人来帮助他们国家的时候了”;
    字符串ctext,rtext;
    字节键[键大小],iv[块大小];
    通用钥匙(钥匙,iv);
    加密(密钥、iv、ptext、ctext);
    解密(密钥、iv、ctext、rtext);
    难道你不应该使用
    AES\u encrypt
    和friends。这是一个只使用软件的实现,因此你不会像AES-NI那样享受硬件支持。你应该使用
    EVP\u*
    函数。请参阅OpenSSL wiki上的。事实上,你可能应该使用经过身份验证的加密,因为它既提供了机密性,也提供了身份验证y、 请参见OpenSSL wiki上的。
    KS(AESKey):L“F-ZTNW meOJLK1s5”
    -Windows使用UTF-16,Linux使用UTF-32。这意味着Windows上一半的密钥位为0(实际上是64位密钥),Linux上四分之三的密钥位为0(实际上是32位密钥)。你需要用HKDF之类的东西来消化你的密钥字符串,以提取熵,然后为密码设置密钥。其他