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

发布于 2024-08-17 12:50:30 字数 339 浏览 5 评论 0原文

我使用 openssl 生成了 RSA 私钥。

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

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

我想我应该丢弃标题?或者用户可以读取按键而不是自己操作?

我遇到了 PEM_read_PrivateKey() 但它创建了一个 EVP_PKEY 结构,该结构无法直接由 HMAC*() 函数使用。

有什么提示吗? 谢谢 !

I generated an RSA private key using openssl.

I need to use the HMAC_*() functions of the OpenSSL library in plain C to hash/sign data, but I'm unsure on how to correctly extract the private key data from that file.

From what I know, that file is B64 encoded, so I uncoded it and stored it in a buffer. However, it seems to me that the HMAC_*() functions, although hashing and signing do not use the actual key since the result is not what I expect.

I assume I should discard the header ? Or user functions to read the keys instead of doing it by myself ?

I came accross PEM_read_PrivateKey() but that one creates an EVP_PKEY struct which is unusable directly by HMAC*() functions.

Any hint ?
Thanks !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

下雨或天晴 2024-08-24 12:50:30

你误解了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_SignFinal() 所需的 EVP_PKEY *,您需要通过 RSA 密钥对其进行初始化:

EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);

openssl 创建的 Base64 编码的 RSA 密钥code> 命令行实用程序采用 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文