使用Openssl EVP库加密和使用openssl enc terminal命令解密失败

时间:2019-07-09 16:47:02

标签: 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;
}

密钥和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

1 个答案:

答案 0 :(得分:0)

我怀疑这是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;
    }