Openssl 如何读取用于HMAC_Init_ex()的密钥文件

Openssl 如何读取用于HMAC_Init_ex()的密钥文件,openssl,rsa,Openssl,Rsa,我使用openssl生成了一个RSA私钥 我需要使用普通C中OpenSSL库的HMAC_*()函数对数据进行哈希/签名,但我不确定如何正确地从该文件中提取私钥数据 据我所知,该文件是B64编码的,所以我将其解压缩并存储在缓冲区中。然而,在我看来,HMAC_*()函数,尽管散列和签名不使用实际的密钥,因为结果不是我所期望的 我想我应该放弃标题?或者用户函数读取密钥而不是自己做 我来这里是因为我读了PrivateKey(),但是它创建了一个EVP_PKEY结构,它不能直接由HMAC*()函数使用 有

我使用openssl生成了一个RSA私钥

我需要使用普通C中OpenSSL库的HMAC_*()函数对数据进行哈希/签名,但我不确定如何正确地从该文件中提取私钥数据

据我所知,该文件是B64编码的,所以我将其解压缩并存储在缓冲区中。然而,在我看来,HMAC_*()函数,尽管散列和签名不使用实际的密钥,因为结果不是我所期望的

我想我应该放弃标题?或者用户函数读取密钥而不是自己做

我来这里是因为我读了PrivateKey(),但是它创建了一个EVP_PKEY结构,它不能直接由HMAC*()函数使用

有什么提示吗?
谢谢

你误解了HMAC。HMAC使用共享(对称)密钥创建数据的安全密钥散列。它需要与生成的密钥相同的密钥来验证它(这不是签名)。密钥只是一个没有特定结构的随机位序列

RSA签名基于普通的、未加密的散列。您应该使用
EVP\u SignInit()
/
EVP\u SignUpdate()
/
EVP\u 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\u SignFinal()
所需的
EVP\u PKEY*
,您需要从RSA密钥对其进行初始化:

EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);
openssl
命令行实用程序创建的base64编码RSA密钥是PEM格式的,因此您可以使用
PEM\u read\u 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;
}
#包括
#包括
#包括
#包括
#包括
int do_evp_签名(文件*rsa_pkey_文件,文件*in_文件)
{
RSA*RSA_pkey=NULL;
EVP_PKEY*PKEY=EVP_PKEY_new();
执行副总裁MD CTX CTX;
无符号字符缓冲区[4096];
尺寸透镜;
无符号字符*sig;
无符号整数符号;
int i;
if(!PEM_read_RSAPrivateKey(rsa_pkey_文件和rsa_pkey,NULL,NULL))
{
fprintf(stderr,“加载RSA私钥文件时出错。\n”);
返回2;
}
如果(!EVP_PKEY_assign_RSA(PKEY,RSA_PKEY))
{
fprintf(标准,“EVP\u PKEY\u assign\u RSA:失败。\n”);
返回3;
}
EVP_MD_CTX_init(&CTX);
如果(!EVP_SignInit(&ctx,EVP_sha1()))
{
fprintf(标准,“执行副总裁签名:失败。\n”);
免费执行副总裁(PKEY);
返回3;
}
而((len=fread(buffer,1,sizeof buffer,in_file))>0)
{
if(!EVP_SignUpdate(&ctx,buffer,len))
{
fprintf(标准,“EVP\U SignUpdate:失败。\n”);
免费执行副总裁(PKEY);
返回3;
}
}
如果(ferror(在文件中))
{
perror(“输入文件”);
免费执行副总裁(PKEY);
返回4;
}
sig=malloc(执行副总裁(PKEY)尺寸(PKEY));
如果(!EVP_SignFinal(&ctx,sig,&siglen,pkey))
{
fprintf(标准,“EVP\U SignFinal:失败。\n”);
免费(sig);
免费执行副总裁(PKEY);
返回3;
}
printf(“签名:\n”);
对于(i=0;i