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

标签 c++ openssl aes

我正在尝试使用来自 OpenSSL 的 AES 加密文件,然后将输出写入文件。但是我得到的输出很乱,有时可以破译,有时则不能。

主要代码基于这里:https://github.com/shanet/Crypto-Example/blob/master/crypto-example.cpp

代码如下:

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...

谢谢。

最佳答案

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

我不太喜欢 C++,所以我会使用 fwrite 以 C 方式将数据写入文件,但如果您想以 C++ 方式进行,我认为您正在寻找 ifstream 而不是 stringstream

旁注,我打赌这只是为了调试,但无论如何我都会指出它只是为了确保:硬编码你的 AES key 和 IV (strncpy((char*)aesKey, (const char *)"B374A26A71490437AA024E4FADD5B4AA", AES_KEYLEN/8)) 完全违背了加密的目的。如果您想避免 PBKDF (EVP_BytesToKey),您可以使用 RAND_Bytes 来获取 AES key 的随机数据。

关于c++ - 为什么我的 OpenSSL C++ 代码会创建二进制加密输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17980743/

相关文章:

android - IV 用于加密转换。预期 IV 长度为 16 但实际为 24

c# 格式保留整数加密

javax.crypto.Cipher - 如何获取包含前 128 个 ASCII 字符的密文

java - 用 java/c++ 扩展 php?

C++ 协变和引用

c - AES CTR OpenSSL 命令行与 EVP_aes_128_ctr C 代码不匹配

c - 围绕 MD5 代码的段错误

c++ - cbegin函数的返回值

c++ - 线程可以被重用来运行可变参数函数吗?

android - 选项 -no-engine 导致 Android 的 OpenSSL 构建出现问题