在命令行和 C++ 程序中使用 OpenSSL 时的不同密钥和 IV

问题描述 投票:0回答:1

我有一个加密文件,我知道使用的密码和盐。该文件已使用以下凭据加密:

  • 密码:
    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++ 代码。这我不明白。我缺少什么?

c++ encryption openssl
1个回答
0
投票

我可以解决我的问题。事实证明,这是我的错,因为我的密码输入错误。但我想澄清一些事情。

函数

EVP_BytesToKey()
在openssl中没有改变。使用哪个版本的 openssl 并不重要。如果您使用我的代码示例中的参数调用此函数,结果始终相同。

在我的示例中,您会看到摘要固定为

sha1
并且给出了盐。这意味着默认选项(可能在版本中发生更改)将被覆盖。示例中调用函数的方式保证结果保持不变。

如果摘要、密码和盐正确,则可以成功解密该文件(前提是该文件使用相同的凭据加密)。这就是我的问题。密码正确后,就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.