You misunderstand HMAC. HMAC uses a shared (symmetric) key to create a secure keyed hash of the data. It requires the same key to verify it as produced it (this is not a signature). The key is just a sequence of random bits with no particular structure.
A RSA signature is based on a normal, unkeyed hash. You should use the EVP_SignInit()
/ EVP_SignUpdate()
/ EVP_SignFinal()
functions to create RSA signatures. For example, to intialise an EVP context for RSA-with-SHA256 signatures, you'd do:
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
EVP_SignInit(&ctx, EVP_sha256());
(If your version of OpenSSL doesn't include SHA256, you can use EVP_sha1()
for RSA-with-SHA1 signatures).
To obtain the EVP_PKEY *
needed by EVP_SignFinal()
, you'll initialise it from your RSA key:
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);
The base64-encoded RSA keys created by the openssl
commandline utility are in PEM format, so you can just use PEM_read_RSAPrivateKey()
to read it directly from the file into an RSA *
handle.
Here's an example of reading an RSA private key file and using it to generate a signature of another file:
#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;
}