Вы неправильно поняли 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;
}