C++ 为什么我的OpenSSL C++;代码创建二进制加密输出?

C++ 为什么我的OpenSSL C++;代码创建二进制加密输出?,c++,openssl,aes,C++,Openssl,Aes,我正在尝试使用OpenSSL中的AES加密一个文件,然后将输出写入一个文件。但我得到的是杂乱无章的输出,有时是可破译的,有时是不可破译的 主要代码基于以下内容: 代码如下: int Crypt::__aesEncrypt(const unsigned char *msg, size_t msgLen, unsigned char **encMsg) { EVP_CIPHER_CTX *aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHE

我正在尝试使用OpenSSL中的AES加密一个文件,然后将输出写入一个文件。但我得到的是杂乱无章的输出,有时是可破译的,有时是不可破译的

主要代码基于以下内容:

代码如下:

int Crypt::__aesEncrypt(const unsigned char *msg, size_t msgLen, unsigned char **encMsg) {
EVP_CIPHER_CTX *aesEncryptCtx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(aesEncryptCtx);

unsigned char *aesKey = (unsigned char*)malloc(AES_KEYLEN/8);
unsigned char *aesIV = (unsigned char*)malloc(AES_KEYLEN/8);

unsigned char *aesPass = (unsigned char*)malloc(AES_KEYLEN/8);
unsigned char *aesSalt = (unsigned char*)malloc(8);

if(RAND_bytes(aesPass, AES_KEYLEN/8) == 0) {
    return FAILURE;
}

if(RAND_bytes(aesSalt, 8) == 0) {
    return FAILURE;
}

if(EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), aesSalt, aesPass, AES_KEYLEN/8, AES_ROUNDS, aesKey, aesIV) == 0) {
    return FAILURE;
}

strncpy((char*)aesKey, (const char*)"B374A26A71490437AA024E4FADD5B4AA", AES_KEYLEN/8);
strncpy((char*)aesIV, (const char*)"7E892875A52C59A3B588306B13C31FBD", AES_KEYLEN/16);

size_t blockLen = 0;
size_t encMsgLen = 0;

*encMsg = (unsigned char*)malloc(msgLen + AES_BLOCK_SIZE);
if(encMsg == NULL) return FAILURE;

if(!EVP_EncryptInit_ex(aesEncryptCtx, EVP_aes_256_cbc(), NULL, aesKey, aesIV)) {
    return FAILURE;
}

if(!EVP_EncryptUpdate(aesEncryptCtx, *encMsg, (int*)&blockLen, (unsigned char*)msg, msgLen)) {
    return FAILURE;
}
encMsgLen += blockLen;

if(!EVP_EncryptFinal_ex(aesEncryptCtx, *encMsg + encMsgLen, (int*)&blockLen)) {
    return FAILURE;
}

EVP_CIPHER_CTX_cleanup(aesEncryptCtx);
free(aesEncryptCtx);

free(aesKey);
free(aesIV);

return encMsgLen + blockLen;
}

我是这样打电话的:

unsigned char *encMsg = NULL;
    __aesEncrypt((const unsigned char*)decrypted_string.c_str(), decrypted_string.size(), &encMsg);

    std::stringstream ss;
    ss << encMsg;
    //write ss to file...
无符号字符*encMsg=NULL;
__aesEncrypt((const unsigned char*)解密的_string.c_str()、解密的_string.size()、和encMsg);
std::stringstream-ss;

ss事实上,我是基于代码的示例的作者。正如WhozCraig在上面的评论中指出的,您正在使用
stringstream
将加密消息写入文件。问题在于加密消息不是常规的ASCII字符串。它们是二进制数据(值大于127,因此需要无符号字符数组),二进制数据不能被视为ASCII字符串

<>我不是一个C++的人,所以我会用C++的方式写数据到代码 < /c>代码,但是如果你想用C++的方式来做,我想你在寻找<代码> IFSturi而不是<代码> StrugSuth
旁注,我打赌这只是为了调试,但我还是要指出这一点,以确保:硬编码AES密钥和IV(
strncpy((char*)aesKey,(const char*)“B374A26A71490437AA024E4FADD5B4AA”,AES_KEYLEN/8)
)完全违背了加密的目的。如果你想避免PBKDF(
EVP_BytesToKey
),你可以使用
RAND_Bytes
来获取AES密钥的随机数据。

我实际上是你基于代码的示例的作者。正如WhozCraig在上面的评论中指出的,您正在使用
stringstream
将加密消息写入文件。问题在于加密消息不是常规的ASCII字符串。它们是二进制数据(值大于127,因此需要无符号字符数组),二进制数据不能被视为ASCII字符串

<>我不是一个C++的人,所以我会用C++的方式写数据到代码 < /c>代码,但是如果你想用C++的方式来做,我想你在寻找<代码> IFSturi而不是<代码> StrugSuth
旁注,我打赌这只是为了调试,但我还是要指出这一点,以确保:硬编码AES密钥和IV(
strncpy((char*)aesKey,(const char*)“B374A26A71490437AA024E4FADD5B4AA”,AES_KEYLEN/8)
)完全违背了加密的目的。如果您想避免PBKDF(
EVP_BytesToKey
),您可以使用
RAND_Bytes
获取AES密钥的随机数据。

您希望加密为可读的十六进制文本(如Base64编码或BinHex)?在将加密消息块写入文本流之前,您必须自己在加密消息块上执行此操作。此外,看起来您希望将密钥用作字节,但您正在传递一个ascii密钥字符串。我已经有一段时间没有使用OpenSSL了,但我不认为它会在加密之前为您翻译它。我认为对我来说没有区别,谢谢。我认为您没有领会我的意思。文本流,通过
操作符哦,是的,没错。很抱歉我可以更改一些标志来执行此操作?呃,它不应该“创建二进制加密输出”吗?您是否希望加密为可读的十六进制文本(如Base64编码或BinHex)?在将加密消息块写入文本流之前,您必须自己在加密消息块上执行此操作。此外,看起来您希望将密钥用作字节,但您正在传递一个ascii密钥字符串。我已经有一段时间没有使用OpenSSL了,但我不认为它会在加密之前为您翻译它。我认为对我来说没有区别,谢谢。我认为您没有领会我的意思。文本流,通过
操作符哦,是的,没错。很抱歉我可以更改一些标志来完成它?呃,它不是应该“创建二进制加密输出”吗?+1。使用带十六进制编码的格式化字符串流(实际上是bin hex)是文本写入的一个选项。另一种方法是为OpenSSL使用内置的Base64编码器。我可能会使用后者,因为您的解密过程可以在解密之前使用相同的API集进行字节解码(正如我所说,这已经有一段时间了,但如果OpenSSL在其API中的某个地方有一个选项可以在一个步骤中同时执行这两个操作,我一点也不会感到惊讶)。@WhozCraig使用base64是个好主意。我将把它添加到我的示例中,因为我一直都有关于加密消息是二进制数据的问题。这很好。如果您认为可行,我唯一会做的另一件事是“std-lib-reroll”示例以自由地使用
std:vector
std::string
,消除接近或所有这些C-lib内存管理函数。这样做将大大简化代码。如果我有时间,我会在休息日做这件事,并在这条消息中删除一个链接。祝你一切顺利。使用带十六进制编码的格式化字符串流(实际上是bin hex)是文本写入的一个选项。另一种方法是为OpenSSL使用内置的Base64编码器。我可能会使用后者,因为您的解密过程可以在解密之前使用相同的API集进行字节解码(正如我所说,这已经有一段时间了,但如果OpenSSL在其API中的某个地方有一个选项可以在一个步骤中同时执行这两个操作,我一点也不会感到惊讶)。@WhozCraig使用base64是个好主意。我将把它添加到我的示例中,因为我一直都有关于加密消息是二进制数据的问题。这很好。如果您认为可行,我唯一会做的另一件事是“std-lib-reroll”示例以自由地使用
std:vector
std::string
,消除接近或所有这些C-lib内存管理函数。这样做将大大简化代码。如果我有时间,我会在休息日做这件事,并在这条消息中删除一个链接。祝你一切顺利。