使用c++、Openssl和aes加密和解密字符串
Encrypt and decrypt string with c++, Openssl and aes
我正在尝试用c++ openssl和aes cbc加密和解密字符串。
奇怪的是,在一台电脑上它可以工作,而在另一台电脑上它不能。我只有原来字符串的3/4,所以结尾是错误的。
另一个奇怪的事情是,当我在第二台pc上的exe文件目录中添加一个名为"libeay32.dll"的dll时,它可以工作,但在第一台pc上不行。
总而言之,第一台pc只能在没有dll的情况下工作,第二台pc只能在有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);
}
第一台pc的输出:
输入:加密:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
S ^我们◄┘"▼~¼ e╣╨L╡美元的aC♠·新西兰½h╠∟≥一°╪╥=α我╙φoCYN°☺§)↨XwY +☼▀╤M▓÷√山峡┼≡& lt; ak◄一┬÷∙z¼ut@¥≈╟∙¶√ν7° ²²²²½½½½½½½½ ε■ε■
解密:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
第二台pc的输出:
输入:加密:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
S ^我? +"? ~¼ e¦ðLA 'aC美元?·新西兰½h¦? =°IE = OpEIYoCYN°?§)? XwY +¤¯ÐM¦÷¹山峡+ & lt; ak党?A -÷¨zð+ BnFbYU) ?s
解密:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ? WI»H +²²²²¦¦¦¦¦¦ w美元啊?o:
这两个肯定坏了....
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字节。
如果EncKey
或EncIV
有嵌入的null,您就会遇到麻烦。如果有一个,那么该字符串甚至不是16字节。
正如Jim在下面的评论中指出的,这也是一个麻烦:
return string ((char *) dec_out);
它需要类似于:
string aes_encrypt(string _InStr)
{
...
return string ((char *) dec_out, <some size>);
}
你对AES_cbc_encrypt
的使用看起来是错误的。您应该坚持使用EVP_*
接口。参考OpenSSL wiki上的EVP对称加密与解密。
最好使用像GCM这样的经过身份验证的加密模式,这样您也可以获得真实性/完整性保证。参考OpenSSL wiki上的"EVP认证加解密"。
最后,使用较大的散列,如SHA256
或SHA512
。除了向后兼容之外,MD5不再用于任何其他用途。
- POCO C++加密/解密
- 异或字符串加密/解密输出错误
- 简单仿射密码加密解密
- QT:AES-256-CBC 根据 PHP 代码在C++中加密/解密
- AES加密/解密接收所有明文
- 牡丹AES CBC PKCS7加密解密
- 加密/解密字节数组加密++
- 使用EVP_*进行加密/解密
- 使用 rsa 和 Windows 加密 API 加密/解密字符串和文件
- 使用 <wincrypt.h 加密解密期间丢失字符>
- RSA 加密/解密 Polarssl C++.
- 简单C++加密 - 解密库
- 在Qt中使用博坦加密大文件时如何获得加密/解密进度
- AES-128加密/解密
- C++RSA使用XML密钥进行加密/解密
- 无法使用英特尔 AES-NI 示例库以 32 字节块大小加密/解密
- 程序集asm x86加密/解密程序
- Mupdf加密解密问题
- 如何使用RSA/AES加密/解密较大的文件
- AES CBC 加密/解密仅解密前 16 个字节