d2i_RSA_PUBKEY、d2i_RSAPrivateKey 和 d2i_RSAPublicKey returns 空
d2i_RSA_PUBKEY, d2i_RSAPrivateKey and d2i_RSAPublicKey returns NULL
我使用以下命令创建了一个 RSA 私钥:
openssl genrsa -out keypair.pem 2048
我必须为这个项目使用 DER 编码的密钥 (PKCS#1),所以我从这个 PEM 编码的私钥文件生成了两个 DER 文件——一个带有私钥,另一个带有 public键。
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* 变量中。
None 以下各项按预期工作:
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);
我知道,因为他们所有人 return 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);
所有 return 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_PUBKEY
和 d2i_RSAPrivateKey
应该工作,并且在 Unix 上为我做。
你说你想要'DER-encoded keys (PKCS#1)'。
对于公钥,OpenSSL 通常使用 X.509 中定义的格式 SubjectPublicKeyInfo
,其中包含 AlgorithmIdentifier
plus(已编辑)BIT STRING
包含结构中的公钥值,该结构因算法而异。对于 RSA,algid 包含一个标识 RSA 的 OID,没有参数;依赖于算法的结构是 PKCS#1。
相比之下,OpenSSL 支持两种类型的私钥格式:每种算法(DH 除外)都有一种 'legacy' 格式,RSA 为 PKCS#1;和由 PKCS#8 定义的通用格式,它像 SPKI 一样由 AlgorithmIdentifier
加上一个算法相关的私钥值组成,这次在 OCTET STRING
中。 PKCS#8 也有一个加密密钥的选项,这是 SPKI 没有或不需要的。
OpenSSL 的旧部分,包括 genrsa
和 rsa
命令行实用程序,使用旧的私钥格式,但 OpenSSL 命名为 PUBKEY 的 SPKI 公钥格式。因此,您的 rsa
命令创建了一个 d2i_RSA_PUBKEY
可读但 d2i_RSAPublicKey
不可读的公钥文件(这只是 PKCS#1 部分)和一个 d2i_RSAPrivateKey
可读的私钥文件。
如果您确实需要 'bare' PKCS#1 格式的公钥,rsa
实用程序从 1.0 开始就有选项 -RSAPublicKey_in
和 -RSAPublicKey_out
来读写这种格式。 0,虽然最近才记录但仍未出现在帮助消息中。 d2i_RSAPublicKey
但 d2i_RSA_PUBKEY
无法读取该文件。
一种可能:你没有提到操作系统。 DER 文件是二进制文件,在 C 中要正确处理 Windows 上的 二进制文件,您必须 fopen
加上 b
修饰符,在这里您需要 "rb"
用于读取二进制文件。如果我 运行 你的代码在 Unix 上它可以工作,但要在 Windows 上获得正确的结果我必须添加 b
.
还有一个小问题:你说的'loading contents ... in char* variables'。实际上,您将文件内容加载到内存中并使用 char *
变量指向它们。严格来说,OpenSSL d2i
例程需要 const unsigned char *
变量的地址——如果您在符合标准的模式下 运行 至少,您的编译器应该警告您这种不匹配。但是 C 需要指向所有 char
风格(signed
unsigned
和 'plain')的指针,无论是否有限定,都具有相同的表示和对齐要求,即使它们不是t 与标准中定义的兼容,因此在预期 const unsigned char **
的地方传递 char **
确实有效。
我使用以下命令创建了一个 RSA 私钥:
openssl genrsa -out keypair.pem 2048
我必须为这个项目使用 DER 编码的密钥 (PKCS#1),所以我从这个 PEM 编码的私钥文件生成了两个 DER 文件——一个带有私钥,另一个带有 public键。
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* 变量中。
None 以下各项按预期工作:
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);
我知道,因为他们所有人 return 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);
所有 return 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_PUBKEY
和 d2i_RSAPrivateKey
应该工作,并且在 Unix 上为我做。
你说你想要'DER-encoded keys (PKCS#1)'。
对于公钥,OpenSSL 通常使用 X.509 中定义的格式 SubjectPublicKeyInfo
,其中包含 AlgorithmIdentifier
plus(已编辑)BIT STRING
包含结构中的公钥值,该结构因算法而异。对于 RSA,algid 包含一个标识 RSA 的 OID,没有参数;依赖于算法的结构是 PKCS#1。
相比之下,OpenSSL 支持两种类型的私钥格式:每种算法(DH 除外)都有一种 'legacy' 格式,RSA 为 PKCS#1;和由 PKCS#8 定义的通用格式,它像 SPKI 一样由 AlgorithmIdentifier
加上一个算法相关的私钥值组成,这次在 OCTET STRING
中。 PKCS#8 也有一个加密密钥的选项,这是 SPKI 没有或不需要的。
OpenSSL 的旧部分,包括 genrsa
和 rsa
命令行实用程序,使用旧的私钥格式,但 OpenSSL 命名为 PUBKEY 的 SPKI 公钥格式。因此,您的 rsa
命令创建了一个 d2i_RSA_PUBKEY
可读但 d2i_RSAPublicKey
不可读的公钥文件(这只是 PKCS#1 部分)和一个 d2i_RSAPrivateKey
可读的私钥文件。
如果您确实需要 'bare' PKCS#1 格式的公钥,rsa
实用程序从 1.0 开始就有选项 -RSAPublicKey_in
和 -RSAPublicKey_out
来读写这种格式。 0,虽然最近才记录但仍未出现在帮助消息中。 d2i_RSAPublicKey
但 d2i_RSA_PUBKEY
无法读取该文件。
一种可能:你没有提到操作系统。 DER 文件是二进制文件,在 C 中要正确处理 Windows 上的 二进制文件,您必须 fopen
加上 b
修饰符,在这里您需要 "rb"
用于读取二进制文件。如果我 运行 你的代码在 Unix 上它可以工作,但要在 Windows 上获得正确的结果我必须添加 b
.
还有一个小问题:你说的'loading contents ... in char* variables'。实际上,您将文件内容加载到内存中并使用 char *
变量指向它们。严格来说,OpenSSL d2i
例程需要 const unsigned char *
变量的地址——如果您在符合标准的模式下 运行 至少,您的编译器应该警告您这种不匹配。但是 C 需要指向所有 char
风格(signed
unsigned
和 'plain')的指针,无论是否有限定,都具有相同的表示和对齐要求,即使它们不是t 与标准中定义的兼容,因此在预期 const unsigned char **
的地方传递 char **
确实有效。