我使用openssl生成了一个RSA私钥。
我需要在普通C中使用OpenSSL库的HMAC _ *()函数来散列/签名数据,但我不确定如何从该文件中正确提取私钥数据。
据我所知,该文件是B64编码的,因此我将其编码并将其存储在缓冲区中。但是,在我看来,HMAC _ *()函数虽然散列和签名不使用实际密钥,因为结果不是我所期望的。
我认为我应该丢弃标题?或者用户是否能够自己阅读密钥而不是自己动手?
我遇到了PEM_read_PrivateKey()但是那个创建了一个EVP_PKEY结构,它不能直接被HMAC *()函数使用。
任何提示? 谢谢!
答案 0 :(得分:4)
你误解了HMAC。 HMAC使用共享(对称)密钥来创建数据的安全密钥哈希。它需要相同的密钥才能将其验证为生成它(这是不是签名)。关键是一系列随机位,没有特定的结构。
RSA签名基于正常的无键哈希。您应该使用EVP_SignInit()
/ EVP_SignUpdate()
/ EVP_SignFinal()
函数来创建RSA签名。例如,要初始化RSA-with-SHA256签名的EVP上下文,您需要执行以下操作:
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);
由openssl
命令行实用程序创建的base64编码的RSA密钥采用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;
}