c++ - 使用 C++、Openssl 和 aes 加密和解密字符串

标签 c++ encryption dll openssl aes

我正在尝试使用 C++ openssl 和 aes cbc 加密和解密字符串。

奇怪的是,在一台电脑上它可以工作,而在另一台电脑上却不能。我只有原始字符串的 3/4,所以结尾是错误的。

另一个奇怪的事情是,当我在第二台电脑上的 exe 文件目录中添加一个名为“libeay32.dll”的 dll 时,它可以工作,但在第一台电脑上不行。

总而言之,第一台电脑只在没有 dll 的情况下工作,第二台电脑只在有 dll 的情况下工作。

我的问题是,这段代码可以改进吗,为什么一台电脑需要这个dll,另一台电脑不需要。

这是我已经写的:

KEY 和 Iv 定义:

#define KEY "abc"
#define Iv  "abc"

加密函数:

string aes_encrypt(string _InStr)
{
    string  EncKey,
            EncIV;

    AES_KEY enc_key;

    unsigned char * aes_key   = (unsigned char *) malloc (sizeof(unsigned char) * (32)),
                  * iv_enc    = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE),
                  * aes_input = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size ()),
                  * enc_out   = (unsigned char *) malloc (sizeof(unsigned char) * ((_InStr.size () + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);



    memcpy ((char *) aes_input, _InStr.c_str (), _InStr.size ());

    memset (aes_key, 0, 32);

    EncKey = KEY;
    EncIV  = Iv;

    for (int i = 0; i < 50; i++)
        EncKey = md5 (EncKey.c_str ());


    for (int i = 0; i < 305; i++)
        EncIV = md5 (EncIV.c_str ());

    EncIV.erase (16);

    memcpy (aes_key, EncKey.c_str (), 32);
    memcpy (iv_enc,  EncIV.c_str  (), 16);


    AES_set_encrypt_key (aes_key, 128, &enc_key);
    AES_cbc_encrypt     (aes_input, enc_out, _InStr.size (), &enc_key, iv_enc, AES_ENCRYPT);


    free (aes_key);
    free (aes_input);
    free (iv_enc); 

    aes_key     = NULL;
    aes_input   = NULL;
    iv_enc      = NULL;

    return string ((char *) enc_out);

}

解密函数:

string aes_decrypt (string _InStr)
{
    string  EncKey,
            EncIV;

    AES_KEY dec_key;

    unsigned char * aes_key   = (unsigned char *) malloc (sizeof(unsigned char) * (32)),
                  * iv_dec    = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE),
                  * enc_out   = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size ()),
                  * dec_out   = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size ());


    memcpy (enc_out, _InStr.c_str (), _InStr.size ());

    memset (aes_key, 0, 32);

    EncKey = KEY;
    EncIV  = Iv;

    for (int i = 0; i < 50; i++)
        EncKey = md5 (EncKey.c_str ());

    for (int i = 0; i < 305; i++)
        EncIV = md5 (EncIV.c_str ());

    EncIV.erase (16);

    memcpy (aes_key, EncKey.c_str (), 32);
    memcpy (iv_dec,  EncIV.c_str  (), 16);

    AES_set_decrypt_key(aes_key, 128, &dec_key);
    AES_cbc_encrypt(enc_out, dec_out, _InStr.size (), &dec_key, iv_dec, AES_DECRYPT);

    free (aes_key);
    free (iv_dec); 
    free (enc_out);  

    aes_key     = NULL;
    iv_dec      = NULL;
    enc_out     = NULL;

    return string ((char *) dec_out);

}

第一台电脑的输出:

输入:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

加密:

S^Wo◄┘"â▼~¼\é╣$╨L╡`aC♠·ñZ½h╠∟≥ä°╪╥=αp╙IφoCYN°☺§)↨XwY+☼▀╤M▓÷√NÉk┼≡<ák◄Ä┬÷∙z ¼üt@¥≈╟∙¶√Ñù°7å²²²²½½½½½½½½ε■ε■

解密:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

第二台电脑的输出:

输入:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

加密:

S^Wo?+"â?~¼\é¦$ðLÁ`aC?·ñZ½h¦?=ä°ÏÊ=ÓpËIÝoCYN°?§)?XwY+¤¯ÐM¦÷¹NÉk+­<ák?Ä-÷¨zð+BñFb YÙ]?s

解密:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?WλH+²²²²¦¦¦¦¦¦w$ö?ó:

最佳答案

这两个肯定坏了....

for (int i = 0; i < 50; i++)
    EncKey = md5 (EncKey.c_str ());

for (int i = 0; i < 305; i++)
    EncIV = md5 (EncIV.c_str ());

你需要这样的东西:

EncKey = string(md5 (EncKey.c_str ()), 16);

否则,MD5 生成的字符串将在 string 构造函数遇到的第一个 0x00 处被截断。


这些都是麻烦:

memcpy (aes_key, EncKey.c_str (), 32);
memcpy (iv_enc,  EncIV.c_str  (), 16);

充其量,MD5 生成一个 16 字节的字符串。您不能从 EncKey 中的 16 字节字符串中提取 32 个字节。

如果 EncKeyEncIV 嵌入了空值,您就有麻烦了。如果其中一个有一个,那么该字符串甚至不到 16 个字节。


正如吉姆在下面的评论中指出的那样,这也是个麻烦:

return string ((char *) dec_out);

它需要类似于:

string aes_encrypt(string _InStr)
{
    ...
    return string ((char *) dec_out, <some size>);
}

而且您对 AES_cbc_encrypt 的使用看起来不对。您应该坚持使用 EVP_* 接口(interface)。有关示例,请参阅 EVP Symmetric Encryption and Decryption在 OpenSSL wiki 上。

更好的是,使用像 GCM 这样经过身份验证的加密模式,这样您也可以获得真实性/完整性保证。有关示例,请参阅 EVP Authenticated Encryption and Decryption在 OpenSSL wiki 上。


最后,使用更大的散列,如 SHA256SHA512。除了向后兼容性外,不再需要 MD5。

关于c++ - 使用 C++、Openssl 和 aes 加密和解密字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24458185/

相关文章:

c++ - 在 VS 中编译程序,无需任何外部运行时 dll

python - 将英特尔的 __attribute__((vector)) 与 swig 一起使用

c++ - 试图让 CUDA 7.5 与 GCC 5.x 一起工作

java - 我应该如何正确地将Java加密算法移植到Python?

java - AES 加密 : Encrypt using Arduino and decrypt using Java

c++ - 新手 : Determinate CRT lib used by library

c++ - 如何在 C++ 中实现非静态、非虚方法?

c++ - Tcl:解释器创建被跟踪对象的拷贝,当它发生变化时

java - 如何最大限度地减少 HTTP 请求中的大量数据?

c++ - 如何使用def文件在de dll中使用mfc