无法使用openssl CLI解密消息,该消息已使用openssl API

时间:2020-01-13 21:07:31

标签: c linux shell openssl

我正在使用Linux libcrypto AES-128 CBC Encryption/Decryption works on Ubuntu but not Raspberry Pi

中的上述代码

在这里稍作修改了代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/crypto.h>  

unsigned char aes_key[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};

/* Print Encrypted and Decrypted data packets */
void print_data(const char *tittle, const void* data, int len);

int main( )
{
    /* Input data to encrypt */
    unsigned char aes_input[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};

    fprintf(stderr,"%s\n",SSLeay_version(SSLEAY_VERSION));

    /* Init vector */
    //unsigned char iv[AES_BLOCK_SIZE];
    unsigned char iv[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};
    //memset(iv, 0x00, AES_BLOCK_SIZE);

    /* Buffers for Encryption and Decryption */
    unsigned char enc_out[sizeof(aes_input)];
    unsigned char dec_out[sizeof(aes_input)];

    /* AES-128 bit CBC Encryption */
    AES_KEY enc_key, dec_key;
    AES_set_encrypt_key(aes_key, sizeof(aes_key)*8, &enc_key);
    AES_cbc_encrypt(aes_input, enc_out, sizeof(aes_input), &enc_key, iv,         AES_ENCRYPT);

    FILE *fp = fopen("id_encrypted","w");
    fwrite(enc_out, sizeof(enc_out), 1, fp); // write all the new buffer
    fclose(fp);

    /* AES-128 bit CBC Decryption */
    //memset(iv, 0x00, AES_BLOCK_SIZE); // don't forget to set iv vector again, else you can't decrypt data properly
    //unsigned char iv[AES_BLOCK_SIZE];
    unsigned char iv2[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};
    AES_set_decrypt_key(aes_key, sizeof(aes_key)*8, &dec_key); // Size of key is in bits
    AES_cbc_encrypt(enc_out, dec_out, sizeof(aes_input), &dec_key, iv2, AES_DECRYPT);

    /* Printing and Verifying */    
    print_data("\n Original ",aes_input, sizeof(aes_input)); // you can not print data as a string, because after Encryption its not ASCII

    print_data("\n Encrypted",enc_out, sizeof(enc_out));

    print_data("\n Decrypted",dec_out, sizeof(dec_out));

    return 0;
}

void print_data(const char *tittle, const void* data, int len)
{
    printf("%s : ",tittle);
    const unsigned char * p = (const unsigned char*)data;
    int i = 0;

    for (; i<len; ++i)
        printf("%02X ", *p++);

    printf("\n");
}

如果运行代码,则可以看到以下输出。

OpenSSL 1.1.1 2018年9月11日

原件:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

已加密:C6 A1 3B 37 87 8F 5B 82 6F 4F 81 62 A1 C8 D8 79

解密:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

我的目标是使用openssl CLI解密加密的输出文件[在代码中名为 id_encrypted ]。

我使用的命令是

openssl enc -d -v -aes-128-cbc -in id_encrypted -out id_decrypted -K "0123456789abcdef" -iv "0123456789abcdef"

但是出现以下错误消息,并且输出文件为空。

bufsize=8192
hex string is too short, padding with zero bytes to length
hex string is too short, padding with zero bytes to length
bad decrypt
139861660053952:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:537:

任何人都可以帮助它为什么不起作用吗?我猜想,问题出在我正在使用的openssl命令中,因为我们可以看到该代码可同时用于加密和解密。

1 个答案:

答案 0 :(得分:2)

请勿以这种方式编写您的加密代码。您使用的是低级AES API,该API专供具有高级知识的高级用户使用。特别是它们不会:

  • 执行填充-在大多数情况下是必需的(在OpenSSL CLI解密过程中是必需的)
  • 默认情况下使用优化且固定时间(即最安全)的实施方式

它们也很容易被滥用,并用脚射击自己。由于上述原因,OpenSSL项目团队长期以来一直不鼓励使用低级别的AES API,并将在下一版的OpenSSL中弃用:

https://github.com/openssl/openssl/blob/9ce921f2dacc9f56b8ae932ae9c299670700a297/CHANGES#L394-L413

相反,您应该使用EVP API。请参见此页面以获取示例代码:

https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption

除此之外,在OpenSSL CLI上指定密钥和iv的方式还存在一些其他问题。 “ -K”参数需要十六进制的密钥。每个十六进制数字代表4位(而不是8位)。因此,您提供的密钥等效于:

01 23 45 67 89 ab cd ef

但是您想要的是:

00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f

IV也有类似的问题。因此,您真正想要的是:

$ openssl enc -d -v -aes-128-cbc -in id_encrypted -out id_decrypted -K "000102030405060708090a0b0c0d0e0f" -iv "000102030405060708090a0b0c0d0e0f"

但是在您修复了加密代码以进行适当填充之前,这仍然行不通。

编辑后添加:

您还可以使用-nopad选项进行解密而无需填充。但是,最好还是重写代码以不需要此代码。