Как прочитать файл ключа для использования с HMAC_Init_ex()

Я сгенерировал закрытый ключ RSA, используя openssl.

Мне нужно использовать функции HMAC_*() библиотеки OpenSSL в простом C для хеширования/подписи данных, но я не знаю, как правильно извлечь данные закрытого ключа из этого файла.

Насколько я знаю, этот файл закодирован в B64, поэтому я раскодировал его и сохранил в буфере. Однако мне кажется, что функции HMAC_*(), несмотря на хеширование и подписание, не используют фактический ключ, поскольку результат не такой, как я ожидаю.

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

Я столкнулся с PEM_read_PrivateKey(), но он создает структуру EVP_PKEY, которая не может использоваться непосредственно функциями HMAC*().

Любой намек? Спасибо !


person SCO    schedule 12.01.2010    source источник


Ответы (1)


Вы неправильно понимаете HMAC. HMAC использует общий (симметричный) ключ для создания безопасного хэша с ключом данных. Для проверки требуется тот же ключ, что и при его создании (это не подпись). Ключ — это просто последовательность случайных битов без определенной структуры.

Подпись RSA основана на обычном хэше без ключа. Вы должны использовать функции EVP_SignInit() / EVP_SignUpdate() / EVP_SignFinal() для создания подписей RSA. Например, чтобы инициализировать контекст EVP для подписей RSA-with-SHA256, вы должны сделать:

EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
EVP_SignInit(&ctx, EVP_sha256());

(Если ваша версия OpenSSL не включает SHA256, вы можете использовать EVP_sha1() для подписей RSA-with-SHA1).

Чтобы получить EVP_PKEY *, необходимый для EVP_SignFinal(), вы инициализируете его из своего ключа RSA:

EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);

Ключи RSA в кодировке base64, созданные утилитой командной строки openssl, имеют формат PEM, поэтому вы можете просто использовать PEM_read_RSAPrivateKey(), чтобы прочитать их непосредственно из файла в дескриптор RSA *.

Вот пример чтения файла закрытого ключа RSA и его использования для создания подписи другого файла:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>

int do_evp_sign(FILE *rsa_pkey_file, FILE *in_file)
{
    RSA *rsa_pkey = NULL;
    EVP_PKEY *pkey = EVP_PKEY_new();
    EVP_MD_CTX ctx;
    unsigned char buffer[4096];
    size_t len;
    unsigned char *sig;
    unsigned int siglen;
    int i;

    if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL))
    {
        fprintf(stderr, "Error loading RSA Private Key File.\n");
        return 2;
    }

    if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
    {
        fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
        return 3;
    }

    EVP_MD_CTX_init(&ctx);

    if (!EVP_SignInit(&ctx, EVP_sha1()))
    {
        fprintf(stderr, "EVP_SignInit: failed.\n");
        EVP_PKEY_free(pkey);
        return 3;
    }

    while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
    {
        if (!EVP_SignUpdate(&ctx, buffer, len))
        {
            fprintf(stderr, "EVP_SignUpdate: failed.\n");
            EVP_PKEY_free(pkey);
            return 3;
        }
    }

    if (ferror(in_file))
    {
        perror("input file");
        EVP_PKEY_free(pkey);
        return 4;
    }

    sig = malloc(EVP_PKEY_size(pkey));
    if (!EVP_SignFinal(&ctx, sig, &siglen, pkey))
    {
        fprintf(stderr, "EVP_SignFinal: failed.\n");
        free(sig);
        EVP_PKEY_free(pkey);
        return 3;
    }

    printf("Signature: \n");
    for (i = 0; i < siglen; i++)
    {
        printf("%02x", sig[i]);
        if (i % 16 == 15)
            printf("\n");
    }
    printf("\n");

    free(sig);
    EVP_PKEY_free(pkey);
    return 0;
}
person caf    schedule 13.01.2010