Работа с EVP и OpenSSL, программирование на C

Я видел много вопросов по OpenSSL и EVP, но не очень много четких ответов, но я решил, что все же опубликую свой вопрос здесь и надеюсь на более качественные отзывы.

Материалы, предоставленные мне, представляют собой подписанный файл «симметричный ключ.bin», набор ключей RSA «privatekey_A.pem», «publickey_A.pem» и открытый ключ другого пользователя «publickey_B.pem».

Что мне нужно сделать, это:

  1. Снимите подпись symmetrickey.bin и сохраните ее в текстовом файле.
  2. Зашифруйте message.txt с помощью symmetrickey.txt и некоторого алгоритма, например, AES.
  3. Подпишите зашифрованное сообщение с помощью privatekey_A.pem и запишите в файл cipher.bin.
  4. После этого мне нужно отписаться и проверить подпись на cipher.bin.
  5. Затем расшифруйте сообщение с помощью нашего симметричного ключа, а затем запишите его в другой файл.

У меня возникают проблемы с пониманием того, как реализовать библиотеки OpenSSL EVP. На странице API не очень понятно, откуда берутся значения для каждой функции. Например, EVP_OpenInit() где взять ek или длину ek "ekl"? Является ли «prvi» закрытым ключом? И как мне узнать тип? Это вещи, которые мне не даны.

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


person Chris Wendling    schedule 26.04.2015    source источник


Ответы (1)


Для части ключа подписи/отмены подписи мне нужна дополнительная информация, как делается эта подпись? Например, является ли эта подпись длиной X байтов в конце файла, и ее можно легко удалить?

Для пунктов 2-5 в вашем списке наверняка поможет следующий код, он основан на примерах из документации openssl с дополнительными комментариями и адаптациями для ваших нужд. Не стесняйтесь спрашивать, если у вас есть какие-либо вопросы, которые не прокомментированы!

crpytor.c

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <openssl/evp.h>

#define APPNAME "C"

#define CHUNK_SIZE 512
int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
    /* Allow enough space in output buffer for additional block */
    unsigned char inbuf[CHUNK_SIZE];
    unsigned char outbuf[CHUNK_SIZE + EVP_MAX_BLOCK_LENGTH];
    int inlen;
    int outlen;
    EVP_CIPHER_CTX ctx;
    /* Bogus key and IV: we'd normally set these from
     * another source.
     */
    unsigned char key[] = { 0x13, 0xa3, 0xb4, 0xc1, 0x24, 0x19, 0xf5, 0x23, 0x18, 0xef, 0xca, 0x12, 0x4c, 0x9f, 0x14, 0xfe };
    unsigned char iv[] = { 0x92, 0x1c, 0x23, 0x3f, 0x5e, 0x10, 0x3d, 0x9a };
    /* Don't set key or IV because we will modify the parameters */
    EVP_CIPHER_CTX_init(&ctx);
    /* Using Blowfish encryption with cbc algorithm, you can use whichever is supported in openssl if you wish */
    EVP_CipherInit_ex(&ctx, EVP_bf_cbc(), NULL, NULL, NULL, do_encrypt);
    EVP_CIPHER_CTX_set_key_length(&ctx, 16);
    /* We finished modifying parameters so now we can set key and IV */
    EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
    for(;;)
    {
        inlen = fread(inbuf, 1, CHUNK_SIZE, in);
        if(inlen <= 0) break;
        if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
        {
            /* Error */
            EVP_CIPHER_CTX_cleanup(&ctx);
            return -1;
        }
        fwrite(outbuf, 1, outlen, out);
    }
    if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
    {
        /* Error */
        EVP_CIPHER_CTX_cleanup(&ctx);
        return -1;
    }
    fwrite(outbuf, 1, outlen, out);
    EVP_CIPHER_CTX_cleanup(&ctx);
    rewind(in);
    rewind(out);
    return 0;
}

/* This is the standalone encryptor entry point */
int main(int argc, char** argv)
{
    FILE *encode_file;
    FILE *decode_file;
    int enc_or_dec;
    if (argc < 4)
    {
        printf("Usage: %s [plain file] [encrypted file] [0/1 deccrypt/encrypt]\n", argv[0]);
        return -1;
    }
    encode_file = fopen(argv[1], "r");
    decode_file = fopen(argv[2], "w+");
    /* Stupid decimal translation */
    enc_or_dec = *argv[3]-48;

    do_crypt(encode_file, decode_file, enc_or_dec);
    return 0;
}

И Makefile:

all:
    gcc cryptor.c -o cryptor -g -lcrypto -I ../openssl-1.0.1f-host/include
clean:
    rm cryptor

Этот код не использует EVP_OpenInit(), потому что он используется только для расшифровки, в то время как мой метод (и ваши потребности) требуют как шифрования, так и расшифровки. Хотя вы можете использовать EVP_OpenInit() для инициализации контекста дешифрования, я заменил один вызов, подходящий только для дешифрования, двумя вызовами, подходящими как для шифрования, так и для дешифрования.

Со страницы руководства:

EVP_OpenInit() инициализирует контекст шифрования ctx для расшифровки с типом шифрования. Он расшифровывает зашифрованный симметричный ключ длиной ekl байт, переданный в параметре ek, используя закрытый ключ priv. IV предоставляется в параметре iv. EVP_OpenUpdate() и EVP_OpenFinal() имеют те же свойства, что и подпрограммы EVP_DecryptUpdate() и EVP_DecryptFinal(), как описано на странице руководства EVP_EncryptInit(3).

EVP_OpenInit() для ключевых файлов

Если подписанный файл, на который вы ссылаетесь, является файлом открытого ключа в RSA/DSA или аналогичном формате, вы можете использовать этот вопрос StackOverflow для лучшего метода, чем мой, поскольку он автоматически извлекает ключ из файла (и использует EVP_OpenInit(), как вам нужно )

person Ishay Peled    schedule 26.04.2015
comment
Что касается части 1, мне точно не сказали, как файл был подписан. Пара ключей, которую мне дали использовать как мою собственную (privatekey_A.pem и publickey_A.pem), была сгенерирована как ключи RSA. Симметричный ключ.bin содержит симметричный сеансовый ключ. Затем файл был подписан закрытым ключом отправителя. Я предполагаю, что у них также есть набор ключей RSA, и, возможно, они использовали библиотеки EVP, чтобы запечатать его. Моя работа на этом этапе заключается в использовании EVP_open() для отмены подписи и сохранения сессионного ключа в файле .txt. Насколько я понимаю, после отмены подписи этот файл будет использоваться в качестве нашего ключа для шифрования. - person Chris Wendling; 28.04.2015
comment
Привет, Крис, ты проверил ссылку на StackOverflow, которую я предоставил? Он включает в себя довольно полный пример с полными пояснениями для вашего случая. - person Ishay Peled; 28.04.2015
comment
Я думаю, что да, на этой странице была ссылка, по которой я перешел, и она дала пример для EVP_Seal() и EVP_Open(). Я начну компилировать код в ближайшие несколько дней, чтобы убедиться, что все работает вместе, но на данный момент это дало мне гораздо больше ясности. Я опубликую редактирование, как только все заработает для следующего человека, сбитого с толку страницей man evp. :) - person Chris Wendling; 29.04.2015
comment
Я помню, как сам не раз боролся с документацией openssl... Это действительно требует некоторой работы. - person Ishay Peled; 29.04.2015