Как использовать пользовательский ключ в openssl в AES_set_encrypt_key

#c #c #encryption #openssl

#c #c #шифрование #openssl

Вопрос:

Я пытаюсь реализовать кодирование и декодирование с помощью openssl, используя пример code how, но когда я пытаюсь использовать пользовательский ключ, код нарушается, какова правильная форма для установки пользовательского ключа и пользовательского ввода для использования в openssl (я считаю, что ошибка в моей логике в C ине при использовании openssl)

     const char *in = "test";

    size_t in_len = strlen(in);
    unsigned char aes_input[in_len];
    for (size_t i = 0; i != in_len; i  ) aes_input[i] = in[i];
//
//    const char *my_custom_key = "my_custom_key";
//    size_t key_len = strlen(my_custom_key);
//    unsigned char aes_key[key_len];
//    for (size_t i = 0; i != in_len; i  ) aes_input[i] = my_custom_key[i];
//
    unsigned char aes_key[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
                               0xCC,
                               0xDD, 0xEE, 0xFF};

    /* Init vector */
    unsigned char iv[AES_BLOCK_SIZE];
    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, amp;enc_key);
    AES_cbc_encrypt(aes_input, enc_out, sizeof(aes_input), amp;enc_key, iv, AES_ENCRYPT);
    /* 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
    AES_set_decrypt_key(aes_key, sizeof(aes_key) * 8, amp;dec_key); // Size of key is in bits
    AES_cbc_encrypt(enc_out, dec_out, sizeof(aes_input), amp;dec_key, iv, AES_DECRYPT);
  

Приведенный выше код работает, но если я переключусь на использование своего пользовательского ключа, он сломается

     const char *my_custom_key = "my_custom_key";
    size_t key_len = strlen(my_custom_key);
    unsigned char aes_key[key_len];
    for (size_t i = 0; i != in_len; i  ) aes_input[i] = my_custom_key[i];

//    unsigned char aes_key[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
                               0xCC,
                               0xDD, 0xEE, 0xFF};
  

Ответ №1:

Использование текстовой строки в качестве ключа AES не является хорошей идеей, потому что:

  1. Размер ключа AES должен быть ровно AES_KEY_LENGTH в байтах.
    "my_custom_key" , равный 13 байтам, слишком короткий.

  2. Текст ASCII имеет низкую энтропию и серьезно снизит безопасность шифрования.

Стандартным решением этого является использование функции получения ключа, например, PBKDF2, чтобы «усилить» и дополнить ключ, чтобы сделать его пригодным для шифрования.

Если вас интересует только размер ключа, то функции хеширования, такой как SHA-256, будет достаточно, чтобы превратить пароль в ключ правильного размера.

Что-то вроде этого:

 std::string pass = "my_custom_key";
unsigned char key[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(amp;sha256);
SHA256_Update(amp;sha256, pass.data(), pass.size());
SHA256_Final(key, amp;sha256);
  

Комментарии:

1. «my_custom_key» — это только пример для этого кода, проблема в том, что код прерывается с ошибкой SIGSEGV (ошибка сегментации) при выполнении AES_cbc_encrypt с использованием aes_key с моим пользовательским ключом и работает с ключом из примера.

2. теперь я понимаю. Я меняю длину или ключ и теперь не имеет ошибки сегмента

3. AES_cbc_encrypt segfaults, потому что AES_set_encrypt_key перед сбоем, когда размер ключа неверен. Вы должны проверять возвращаемое значение каждого вызова, чтобы убедиться, что вызов выполнен успешно. Также обратите внимание, что нулевой IV небезопасен.