gpt4 book ai didi

c - d2i_RSA_PUBKEY、d2i_RSAPrivateKey 和 d2i_RSAPublicKey 返回 NULL

转载 作者:太空宇宙 更新时间:2023-11-04 01:54:32 25 4
gpt4 key购买 nike

我使用以下命令创建了一个 RSA 私钥:

 openssl genrsa -out keypair.pem 2048

我必须为此项目使用 DER 编码的 key (PKCS#1),因此我从这个 PEM 编码的私钥文件生成了两个 DER 文件 - 一个带有私钥,另一个带有公钥。

openssl rsa -inform PEM -in keypair.pem -outform DER -pubout -out public.der

openssl rsa -inform PEM -in keypair.pem -outform DER -out private.der

在我的代码中,我将这两个文件的内容加载到 char* 变量中。

以下均未按预期工作:

d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length);

d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length);

d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length);

我知道,因为它们都返回 null。我还尝试了以下方法:

RSA * rsa = RSA_new();
d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length);

RSA * rsa = RSA_new();
d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length);

RSA * rsa = RSA_new();
d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length);

所有返回null

我的完整测试代码如下:

#include <stdio.h>
#include <stdlib.h>

#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>

typedef struct
{
int len;
char * bytes;
} FileData;

static FileData readFileBytes(const char * name, int zero_ended)
{
FILE * fl = fopen(name, "r");
if (fl == NULL) return (FileData) { .len = 0, .bytes = NULL };
fseek(fl, 0, SEEK_END);
long len = ftell(fl);
char * ret = malloc(len + (zero_ended ? 1 : 0));
fseek(fl, 0, SEEK_SET);
fread(ret, 1, len, fl);
if (zero_ended) ret[len] = 0;
fclose(fl);
return (FileData) { .len = len, .bytes = ret };
}

int main()
{
FileData private_key = readFileBytes("../private.der", 0);
FileData public_key = readFileBytes("../public.der", 0);

char* public_key_bytes = public_key.bytes;
int public_key_length = public_key.len;

char* private_key_bytes = private_key.bytes;
int private_key_length = private_key.len;

RSA * rsa;

public_key_bytes = public_key.bytes;
public_key_length = public_key.len;
rsa = d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length);
printf("d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

public_key_bytes = public_key.bytes;
public_key_length = public_key.len;
rsa = d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length);
printf("d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

private_key_bytes = private_key.bytes;
private_key_length = private_key.len;
rsa = d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length);
printf("d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

public_key_bytes = public_key.bytes;
public_key_length = public_key.len;
rsa = RSA_new();
rsa = d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length);
printf("d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

public_key_bytes = public_key.bytes;
public_key_length = public_key.len;
rsa = RSA_new();
rsa = d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length);
printf("d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

private_key_bytes = private_key.bytes;
private_key_length = private_key.len;
rsa = RSA_new();
rsa = d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length);
printf("d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false");

getchar();

return 0;
}

我做错了什么?

最佳答案

TLDR:d2i_RSA_PUBKEYd2i_RSAPrivateKey 应该可以工作,并且在 Unix 上为我做。

您说您想要“DER 编码 key (PKCS#1)”。

对于公钥,OpenSSL 通常使用 X.509 中定义的格式作为 SubjectPublicKeyInfo,其中包含一个 AlgorithmIdentifier plus(已编辑)BIT STRING 包含结构中的公钥值,该结构因算法而异。对于 RSA,algid 包含一个标识 RSA 的 OID,没有参数;依赖于算法的结构是 PKCS#1。

相比之下,OpenSSL 支持两种类型的私钥格式:每种算法(DH 除外)都有一种“传统”格式,对于 RSA 是 PKCS#1;和由 PKCS#8 定义的通用格式,它像 SPKI 一样由 AlgorithmIdentifier 加上一个算法相关的私钥值组成,这次在 OCTET STRING 中。 PKCS#8 还有一个加密 key 的选项,SPKI 没有也不需要。

OpenSSL 的旧部分,包括 genrsarsa 命令行实用程序,使用传统的私钥格式,但 OpenSSL 命名为 PUBKEY 的 SPKI 公钥格式。因此,您的 rsa 命令创建了一个 publickey 文件,可由 d2i_RSA_PUBKEY 读取,但 d2i_RSAPublicKey 不可读(这只是 PKCS#1 部分)和一个 privatekey 文件可由 d2i_RSAPrivateKey 读取。

如果您确实需要“裸”PKCS#1 格式的公钥,rsa 实用程序有选项 -RSAPublicKey_in-RSAPublicKey_out 来读取并从 1.0.0 开始编写这种格式,尽管最近才记录并且仍然不在帮助消息中。 d2i_RSAPublicKey 可读取该文件,但 d2i_RSA_PUBKEY 不可读取。

一种可能性:您没有提到操作系统。 DER 文件是二进制文件,在 C 中要正确处理 Windows 上的二进制文件,您必须使用 b 修饰符来 fopen,在这里您需要 "rb" 用于读取二进制文件。如果我在 Unix 上运行您的代码,它可以工作,但要在 Windows 上获得正确的结果,我必须添加 b

还有一个小问题:你谈到“加载内容......在 char* 变量中”。实际上,您将文件内容加载到内存中并使用 char * 变量指向它们。严格来说,OpenSSL d2i 例程需要 const unsigned char * 变量的地址——如果您在标准中运行它,您的编译器至少应该警告您这种不匹配-符合模式。但是 C 需要指向所有 char 风格(signed unsigned 和 'plain')的指针,无论是否有限定,都具有相同的表示和对齐方式要求,即使它们与标准中定义的不兼容,所以传递 char ** 是预期的 const unsigned char ** 确实有效。

关于c - d2i_RSA_PUBKEY、d2i_RSAPrivateKey 和 d2i_RSAPublicKey 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36801158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com