c - 使用 Openssl EVP 库加密和使用 openssl enc 终端命令解密失败

标签 c security encryption openssl

我正在尝试使用 OpenSSL EVP 库加密字符串,然后使用来自 Linux 终端的 openssl 命令解密。 用于解密的 OpenSSL 命令:

openssl enc -aes-256-cbc -base64 -salt -d -md md5 -k <passphrase> -in encrypt.txt -out plain.txt

加密代码:

int CAES::encrypt(const char* msg, unsigned char** encrypted_message, const size_t msg_len, const unsigned char *key, unsigned char *iv, const unsigned char* salt) 
{
    //this buffer will hold the salt and the cipher
    const int buffer_len ( CAES::salt_info_size + std::max((int)(msg_len * 2), EVP_MAX_KEY_LENGTH) );
    unsigned char* buffer = new unsigned char[buffer_len];
    //this will be a pointer to the cipher only
    unsigned char* cipher = CAES::salt_info_size + buffer;
    size_t bytes_encrypted(0);
    bool encryption_error(true);
    EVP_CIPHER_CTX *cipher_ctx( create_cipher_ctx(encryption, key, iv) );
    (void) EVP_CIPHER_CTX_set_key_length(cipher_ctx, EVP_MAX_KEY_LENGTH);
        size_t cipher_len(0);
    int temp_len(0);
    if( EVP_EncryptUpdate(cipher_ctx, cipher, &temp_len, (unsigned char *)msg, strlen(msg)) )
    {
        cipher_len = temp_len;
        if( EVP_EncryptFinal_ex(cipher_ctx, cipher + temp_len, &temp_len) )
        {
            cipher_len += temp_len;
        }
        cipher[cipher_len] = '\0';
        encryption_error = false;
        bytes_encrypted = cipher_len;
    }
    memcpy(buffer + 0 , CAES::salt_tag, CAES::salt_tag_size);
    memcpy(buffer + CAES::salt_tag_size, salt, CAES::salt_size);
    memcpy(*encrypted_message, buffer, CAES::salt_info_size + bytes_encrypted);
    EVP_CIPHER_CTX_free(cipher_ctx);
    delete[] buffer;
    return CAES::salt_info_size + bytes_encrypted;
}

将上面的加密字符串编码为base64的代码:

int CBase64::encode(const unsigned char* msg, const size_t msg_len, char** b64_msg) {
  size_t bytes_encoded = 0;
  bytes_encoded = EVP_EncodeBlock((unsigned char *) *b64_msg, msg, msg_len);
  return bytes_encoded;
}

key 和IV推导

void CAES::init_key_iv(const std::string& pass, const unsigned char* salt, unsigned char* key, unsigned char* iv )
{
  const unsigned char * pass_key = reinterpret_cast<const unsigned char*>( pass.c_str() );
  const size_t pass_key_len ( pass.size() );
  EVP_BytesToKey(CAES::cipher_type, CAES::msg_digest_type, salt, pass_key, pass_key_len, 1, key, iv);
}

以下是 key 大小和salt推导:

unsigned char salt[8] = {};
unsigned char key[32] = {};
unsigned char iv_enc[16] = {};
RAND_bytes(salt, 8);

案例一:

const char* password = "@N";
const char* msg = "neo4j";

在尝试解密时我得到以下信息:

bad decrypt
140589946300064:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539:

案例二:

const char* password = "eemnsis";
const char* msg = "This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.This is long message, repeating 10 times.";

在尝试解密时我得到以下信息:

error reading input file

最佳答案

我怀疑是 Base64 编码。

在解密的openssl语句中,使用了-base64选项,没有使用-A选项。因此,需要格式化的 Base64 字符串,即在每个 64 字节之后和末尾有换行符,请参见 -A-Option .

但是,当前的 encode 函数不会这样做,而是将整个 Base64 字符串写入单个行。

问题可以解决

  • 要么在openssl语句中加入-A选项进行解密:-base64 -A

    <
  • 或修改 encode 方法以包含换行符,例如与 EVP_EncodeUpdate等):

    int CBase64::encode(const unsigned char* msg, const size_t msg_len, char** b64_msg) {
        int len, total = 0;
        EVP_ENCODE_CTX *ectx = EVP_ENCODE_CTX_new();
        EVP_EncodeInit(ectx);
        EVP_EncodeUpdate(ectx, (unsigned char *)*b64_msg, &len, msg, msg_len);
        total += len;
        EVP_EncodeFinal(ectx, (unsigned char *)*b64_msg + len, &len);
        total += len;
        EVP_ENCODE_CTX_free(ectx);
        return total;
    }
    

关于c - 使用 Openssl EVP 库加密和使用 openssl enc 终端命令解密失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56957238/

相关文章:

c - wchar 和注册表项的问题

c - 源注入(inject)和程序崩溃

c - 指针减法的机制

mysql - 这个 MySQL 查询如何容易受到 SQL 注入(inject)攻击?

.net - 使用 .NET 安全存储身份验证 token

java - 收到 IllegalBlockSizeException : Data must not be longer than 256 bytes when using rsa

encryption - 如何在现有 Realm 数据库上应用加密

c - 串行监视器实现分段故障

java - 如何保护 Java 程序免受黑客攻击

sockets - IPv6:为什么 IPv4 映射地址存在安全风险?