2010-01-12 1 views
2

Я создал секретный ключ RSA с помощью openssl.Как читать файл ключа для использования с HMAC_Init_ex()

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

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

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

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

Подсказка? Спасибо!

ответ

4

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

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

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

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

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

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

В кодировке base64 RSA ключей, созданных с помощью утилиты командной строки 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; 
}