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



我正在尝试使用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] = '';
        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;
}

密钥和 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);
}

以下是密钥大小和盐派生:

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

案例1:

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:

案例2:

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 字符串。

问题可以通过以下途径解决

  • -A 选项添加到 openssl 语句以进行解密:-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;
    }
    

最新更新