如何读取密钥文件以与HMAC_Init_ex()一起使用

时间:2010-01-12 10:15:27

标签: openssl rsa

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

我需要在普通C中使用OpenSSL库的HMAC _ *()函数来散列/签名数据,但我不确定如何从该文件中正确提取私钥数据。

据我所知,该文件是B64编码的,因此我将其编码并将其存储在缓冲区中。但是,在我看来,HMAC _ *()函数虽然散列和签名不使用实际密钥,因为结果不是我所期望的。

我认为我应该丢弃标题?或者用户是否能够自己阅读密钥而不是自己动手?

我遇到了PEM_read_PrivateKey()但是那个创建了一个EVP_PKEY结构,它不能直接被HMAC *()函数使用。

任何提示? 谢谢!

1 个答案:

答案 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;
}