解密文件AES_256_CBC返回"bad decrypt"错误
Decrypting a file with AES_256_CBC return "bad decrypt" error
这是这个问题的后续问题:
OpenSSL EVP_DecryptFinal_ex在解密文件时返回"错误的最终块长度"错误
我正在尝试解密文件。起初,我将其读取为ASCII文件而不是二进制文件。修复此问题(我希望)并将其作为二进制文件读取,我总是收到"bad decrypt"
错误:
15208:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:cryptoevpevp_enc.c:570:
以下是我如何加密和解密的示例:
加密:
Cipher cipher;
ifstream f("d:/test.YML");
ofstream out("d:/temp.YML");
byte key[KEY_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2};
byte iv[BLOCK_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
secure_string line;
secure_string temp;
while (getline(f, line)) {
cipher.Encrypt(key, iv, line, temp);
out << temp << endl;
}
解密:
Cipher cipher;
ifstream f("d:/temp.YML", ifstream::binary);
ofstream out("d:/tempDecrypt.YML");
byte key[KEY_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2};
byte iv[BLOCK_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
secure_string temp;
vector<char> buffer(1024, 0);
while (!f.eof()) {
f.read(buffer.data(), buffer.size());
streamsize dataSize = f.gcount();
secure_string chunk = { buffer.begin(), buffer.begin() + dataSize };
cipher.Decrypt(key, iv, chunk, temp);
}
现在我不确定从哪里开始这项调查:
有加密问题吗?加密文件已生成,我没有看到任何问题。
我读取文件块并解密它们的方式有问题吗?同样,我在这里看不到问题。(错误在
EVP_DecryptFinal_ex
)我还听说填充可能有问题。我没有做任何与填充相关的事情,所以我不确定这是否是一个问题。
我在Windows上使用相同的OpenSsl版本,我有2个Visual Studio项目,所以不兼容的OpenSsl库应该没有问题。
如果有人有任何指示请求,请告诉我。我以前从未使用过加密,所以有些事情很难理解。
PS:我没有包括Encrypt
和Decrypt
方法,它们与Openssl Wiki网站上的方法相同,如果我应该,请告诉我。
您的代码中存在许多问题...仅举几例:
ofstream out("d:/temp.YML");
应以二进制模式打开。out << temp << endl;
会通过不必要地添加换行符来损坏二进制(加密)数据。- 输出缓冲区应包含足够的空间以适合(输入缓冲区 + block_size)。
- 区块中的加密/解密必须遵循
update
/final
模式。您无法独立加密/解密区块。 - IV 应该是随机的,并且应该与密文一起存储。
请查看以下示例应用程序,它有效:
#include <cstdint>
#include <fstream>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>
static const size_t KEY_SIZE = 256 / 8, BLOCK_SIZE = 128 / 8;
class AESBase {
protected:
const uint8_t *key, *iv;
EVP_CIPHER_CTX *ctx;
AESBase(const uint8_t *key, const uint8_t *iv) : key(key), iv(iv) {
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
}
~AESBase() {
EVP_CIPHER_CTX_free(ctx);
}
static void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
};
class Encrypt : AESBase {
public:
Encrypt(const uint8_t *key, const uint8_t *iv) : AESBase(key, iv) {
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
int update(const char *plaintext, int plaintext_len, char *ciphertext) {
int len;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)ciphertext, &len, (const uint8_t*)plaintext, plaintext_len))
handleErrors();
return len;
}
int final(char *ciphertext) {
int len;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)ciphertext, &len))
handleErrors();
return len;
}
};
class Decrypt : AESBase {
public:
Decrypt(const uint8_t *key, const uint8_t *iv) : AESBase(key, iv) {
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
int update(const char *ciphertext, int ciphertext_len, char *plaintext) {
int len;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)plaintext, &len, (const uint8_t*)ciphertext, ciphertext_len))
handleErrors();
return len;
}
int final(char *plaintext) {
int len;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)plaintext, &len))
handleErrors();
return len;
}
};
void test_encrypt(const uint8_t *key, const char* in, const char* out) {
std::ifstream fin(in, std::ios_base::binary);
std::ofstream fout(out, std::ios_base::binary);
uint8_t iv[BLOCK_SIZE];
RAND_bytes(iv, sizeof(iv));
char buf[1024], temp[sizeof(buf) + BLOCK_SIZE];
Encrypt aes(key, iv);
fout.write((char*)iv, sizeof(iv));
while (fin) {
fin.read(buf, sizeof(buf));
int len = (int)fin.gcount();
if (len <= 0)
break;
len = aes.update(buf, len, temp);
fout.write(temp, len);
}
int len = aes.final(temp);
fout.write(temp, len);
}
void test_decrypt(const uint8_t *key, const char* in, const char* out) {
std::ifstream fin(in, std::ios_base::binary);
std::ofstream fout(out, std::ios_base::binary);
uint8_t iv[BLOCK_SIZE];
fin.read((char*)iv, sizeof(iv));
char buf[1024], temp[sizeof(buf) + BLOCK_SIZE];
Decrypt aes(key, iv);
while (fin) {
fin.read(buf, sizeof(buf));
int len = (int)fin.gcount();
if (len <= 0)
break;
len = aes.update(buf, len, temp);
fout.write(temp, len);
}
int len = aes.final(temp);
fout.write(temp, len);
}
int main()
{
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
uint8_t key[KEY_SIZE] = { 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2 };
test_encrypt(key, "main.cpp", "main.cpp.enc");
test_decrypt(key, "main.cpp.enc", "main.cpp.txt");
}
相关文章:
- 使用来自 Excel VBA 的 C++ dll 时"Bad DLL calling convention" - 如何解决?
- C++17 编解码器在将标准::字符串转换为标准::字符串时抛出"bad conversion"
- 对于代理容器上的迭代器来说,"least bad implementation"可能是什么?
- 获取错误:在抛出"std::bad::alloc"的实例后终止调用 what(): std::bad_alloc
- 为什么 GetSystemMetrics (SM_CXVIRTUALSCREEN) 返回'bad'值?
- 将 lambda 传递给 STL 集时出错"bad function call"
- 新的 C++14 位分隔符处"Bad Character" Eclipse Oxygen 错误
- 使用 #define 被认为是"bad practice"吗?
- "400 Bad request"使用 OpenSSL BIO 进行请求时
- 解密文件AES_256_CBC返回"bad decrypt"错误
- 在C++流中,eof(),fail(),bad()和good()有什么区别
- make / gcc:"bad build"的可能原因是什么?
- 什么是地址0xbaddc0dedeadbead "Bad decode dead bead"
- 在多线程环境中,什么可能导致"bad file descriptor"?
- "std::vector"在调整大小时引发"bad allocation"异常
- 尝试使用 execp、dup2 和管道实现 shell,挂起或"bad file descriptor"
- OpenCV SVM 在火车上抛出异常,"Bad argument (There is only a single class)"
- 成员函数 bad() 的 std::ftsream 用于检查
- 使用 boost::asio 和 boost::thread 时"Bad file descriptor"
- OpenCV C++神经网络 predict() 函数抛出"Bad argument"错误