我有一个加密文件,我知道使用的密码和盐。该文件已使用以下凭据加密:
aes-128-cbc
sha1
5
8P0puxB5OVUFI6uX
MarkRobs
--> 十六进制:4d61726b526f6273
以下所有命令和代码均在 Linux 上使用 openssl 3.1 进行了测试。
当我使用命令行时:
openssl enc -aes-128-cbc -k "8P0puxB5OVUFI6uX" -S 4d61726b526f6273 -d -p -iter 5 -md sha1 -bufsize 1024 -in file.enc -out prj.xma -nosalt
我得到以下密钥和iv:
key=5864BC3B9AAD200975546C1B0FF6F4CF
iv =FB14855AC59E4C541C48D78891B14495
通过我的小程序,我得到以下密钥和 IV:
Using passw.: 8P0puxB5OVUFI6uX (38 50 30 70 75 78 42 35 4f 56 55 46 49 36 75 58)
Using salt: MarkRobs (4d 61 72 6b 52 6f 62 73)
Using key: 14 14 1d 8a 68 ba c6 2b 76 5e ff 05 86 b8 e8 55
Using IV: c0 be c4 96 c9 1b 77 ed 3a 1c 53 f7 18 8f d5 98
这是我实现的代码:
#include <iostream>
#include <fstream>
#include <cstring>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "scramble.h"
#include "utils.h"
using std::string;
using std::ifstream;
using std::ios_base;
using std::ios;
using std::exception;
using std::min;
using std::cout;
using std::cerr;
using std::endl;
#define CHUNK_SIZE 1024
#define OSSL_SUCCESS 1
#define OSSL_ERROR 0
#define AES128_KEY_SIZE 16
#define AES128_SALT_SIZE 8
Scramble::Scramble()
{
mCtx = EVP_CIPHER_CTX_new();
if (!mCtx)
cerr << "Error getting new context!" << endl;
}
bool Scramble::aesInit(const string& key, const string& salt, bool encrypt)
{
if (mAesInitialized)
return true;
if (!mCtx)
{
cerr << "No context available! Initialisation failed!" << endl;
return false;
}
int keySize;
int count = 5; // Number iterations
const EVP_MD *md = EVP_sha1();
const EVP_CIPHER *pCipher = EVP_aes_128_cbc();
if (!md)
{
cerr << "Error getting SHA1 hash function!" << endl;
return false;
}
if (!pCipher)
{
cerr << "Error getting the AES128-CBC cipher algorithm!" << endl;
return false;
}
memset(mAesSalt, 0, AES128_SALT_SIZE);
memcpy(mAesSalt, salt.c_str(), min((size_t)AES128_SALT_SIZE, salt.length()));
// Initialize the key and IV with 0
memset(mAesKey, 0, AES128_KEY_SIZE);
memset(mAesIV, 0, AES128_KEY_SIZE);
keySize = EVP_BytesToKey(pCipher, md, (unsigned char *)salt.c_str(), (unsigned char *)key.c_str(), key.length(), count, mAesKey, mAesIV);
if (keySize == AES128_KEY_SIZE)
{
EVP_CIPHER_CTX_init(mCtx);
if (encrypt)
{
if (EVP_EncryptInit_ex(mCtx, pCipher, nullptr, mAesKey, mAesIV) != OSSL_SUCCESS)
{
cerr << "Error initializing decrypting!" << endl;
return false;
}
}
else
{
if (EVP_DecryptInit_ex(mCtx, pCipher, nullptr, mAesKey, mAesIV) != OSSL_SUCCESS)
{
cerr << "Error initializing decrypting!" << endl;
return false;
}
}
}
else
{
cerr << "Key size is " << (keySize * 8) << " bits - should be 128 bits" << endl;
return false;
}
mAesInitialized = true;
return mAesInitialized;
}
为什么会出现这种差异?我必须更改什么才能获得相同的密钥和 IV?
顺便说一句:原始文件在 Windows 上使用库
LIBEAY32.DLL
进行加密,密钥和 IV 与 Linux 上不同,尽管使用了与上面所示相同的 C++ 代码。这我不明白。我缺少什么?
我可以解决我的问题。事实证明,这是我的错,因为我的密码输入错误。但我想澄清一些事情。
函数
EVP_BytesToKey()
在openssl中没有改变。使用哪个版本的 openssl 并不重要。如果您使用我的代码示例中的参数调用此函数,结果始终相同。
在我的示例中,您会看到摘要固定为
sha1
并且给出了盐。这意味着默认选项(可能在版本中发生更改)将被覆盖。示例中调用函数的方式保证结果保持不变。
如果摘要、密码和盐正确,则可以成功解密该文件(前提是该文件使用相同的凭据加密)。这就是我的问题。密码正确后,就可以了。