не могу расшифровать сообщение с помощью openssl CLI, который был зашифрован с использованием openssl API - PullRequest
0 голосов
/ 14 января 2020

Я использовал приведенный выше код из Linux libcrypto AES-128 CB C Шифрование / дешифрование работает на Ubuntu, но не на 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 11 сентября 2018

Оригинал: 00 01 02 03 04 05 06 07 08 09 0A 0B 0 C 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 0 C 0D 0E 0F

Моя цель - расшифровать зашифрованный выходной файл [с именем id_encrypted в коде] с помощью openssl CLI.

Команда, которую я использовал, это

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 Ответ

2 голосов
/ 14 января 2020

Не пишите свой код шифрования таким образом. Вы используете низкоуровневый AES API, предназначенный для опытных пользователей, которые очень хорошо знают, что они делают. В частности, они не:

  • выполняют заполнение - что требуется в большинстве случаев (и ожидается при расшифровке с помощью CLI OpenSSL)
  • Использование оптимизированного и постоянного времени (т. Е. Наиболее безопасного ) реализации по умолчанию

Их также очень легко неправильно использовать и выстрелить себе в ногу. По этой и вышеприведенным причинам низкоуровневый AES API долгое время не поощрялся командой проекта OpenSSL и не рекомендуется в следующей версии OpenSSL:

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

Вместо этого вы должны использовать API-интерфейсы EVP. См. На этой странице пример кода:

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

Помимо этого у вас есть некоторые дополнительные проблемы, связанные с указанием ключа и iv в OpenSSL. CLI. Аргумент "-K" ожидает ключ в шестнадцатеричном виде. Каждый шестнадцатеричный ди git представляет 4 бита (не восемь). Таким образом, ключ, который вы дали, эквивалентен:

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 для расшифровки без заполнения. Тем не менее, это все же предпочтительно переписать ваш код, чтобы не требовать этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...