以 DER 格式写入 private/public 键
Write private/public keys in DER format
我需要编写一个生成 RSA 密钥的 C 程序,并以 DER 格式保存 X.509 public 密钥和 DER 格式的 PKCS#8 私钥。我用过 Google,但并没有真正找到多少。我到目前为止是这样的:
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
void main() {
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
BIO *bp_public = NULL, *bp_private = NULL;
int bits = 2048;
unsigned long e = RSA_F4;
// Generate the RSA key
printf("Generating RSA key...\n");
bne = BN_new();
ret = BN_set_word(bne, e);
if(ret != 1) {
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if(ret != 1) {
goto free_all;
}
// Save the public key in PEM format
printf("Writing key files...\n");
bp_public = BIO_new_file("public.pem", "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if(ret != 1) {
goto free_all;
}
// Save the private key in PEM format
bp_private = BIO_new_file("private.pem", "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
// Free everything
free_all:
BIO_free_all(bp_public);
BIO_free_all(bp_private);
RSA_free(r);
BN_free(bne);
printf("Done!\n");
}
这显然是以PEM 格式编写密钥。我还需要能够在代码中将数据实际存储在内存中,而不仅仅是将其直接写入文件,因为我还需要用 public 键做一些其他事情。
感谢您的帮助
我认为您需要使用 EVP_PKEY_assign_RSA
将密钥转换为 EVP_PKEY。然后你可以使用 i2d_PUBKEY_bio
写出一个生物。
对我的代码进行以下修改:
- 包含头文件
<openssl/evp.h>
- 声明 BIO 以写出 public_der
- 用
EVP_PKEY_new()
创建 EVP_PKEY 结构
- 使用
EVP_PKEY_assign_RSA
进行转换
- 用
i2d_PUBKEY_bio
写简历
在上下文中:
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
void main() {
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
BIO *bp_public = NULL, *bp_private = NULL, *bp_public_der = NULL;
int bits = 2048;
unsigned long e = RSA_F4;
// Generate the RSA key
printf("Generating RSA key...\n");
bne = BN_new();
ret = BN_set_word(bne, e);
if(ret != 1) {
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if(ret != 1) {
goto free_all;
}
// Save the public key in PEM format
printf("Writing key files...\n");
bp_public = BIO_new_file("public.pem", "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if(ret != 1) {
goto free_all;
}
// Save the private key in PEM format
bp_private = BIO_new_file("private.pem", "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
// Save in DER
EVP_PKEY *evp = EVP_PKEY_new();
ret = EVP_PKEY_assign_RSA(evp, r);
if(ret != 1){
printf("failure %i\n", ret);
}
bp_public_der = BIO_new_file("public.key", "w+");
ret = i2d_PUBKEY_bio(bp_public_der, evp);
// Free everything
free_all:
BIO_free_all(bp_public);
BIO_free_all(bp_public_der);
BIO_free_all(bp_private);
RSA_free(r);
BN_free(bne);
printf("Done!\n");
}
您现在可以在 public.key
中找到 public 键的 DER。你应该能够为私人做同样的事情。
希望对您有所帮助。
您的问题 "saves an X.509 public key in DER format" 的实际含义有点含糊。假设您实际上是指 "save it as a SubjectPublicKeyInfo structure" (这是持有 public 密钥的 X.509 证书的一部分),那么您应该使用 i2d_RSA_PUBKEY (或 i2d_RSA_PUBKEY_fp 或 i2d_RSA_PUBKEY_bio) 将其写出(无需先将其转换为 EVP_PKEY)。
对于 DER 格式的 PKCS#8 私钥,您当前的方法对于 PEM 格式不正确。 PEM_write_bio_RSAPrivateKey() 函数将以传统格式(不是 PKCS#8)写出来。
我假设您不想做任何复杂的事情,比如先加密密钥。对于这个,您需要将其转换为 EVP_PKEY(使用 @JawguyChooser 提到的 EVP_PKEY_assign_RSA())。接下来,您使用(遗憾的是未记录)函数 EVP_PKEY2PKCS8.
获得一个 PKCS8_PRIV_KEY_INFO 结构
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
使用完 PKCS8_PRIV_KEY_INFO_free() 后,您需要释放此结构。接下来使用 i2d_PKCS8_PRIV_KEY_INFO()(或 i2d_PKCS8_PRIV_KEY_INFO_fp() 或 i2d_PKCS8_PRIV_KEY_INFO_bio)写出 PKCS8 DER。
有关这些函数的各种信息,请参阅手册页:
https://www.openssl.org/docs/man1.1.0/crypto/i2d_RSAPublicKey.html
我需要编写一个生成 RSA 密钥的 C 程序,并以 DER 格式保存 X.509 public 密钥和 DER 格式的 PKCS#8 私钥。我用过 Google,但并没有真正找到多少。我到目前为止是这样的:
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
void main() {
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
BIO *bp_public = NULL, *bp_private = NULL;
int bits = 2048;
unsigned long e = RSA_F4;
// Generate the RSA key
printf("Generating RSA key...\n");
bne = BN_new();
ret = BN_set_word(bne, e);
if(ret != 1) {
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if(ret != 1) {
goto free_all;
}
// Save the public key in PEM format
printf("Writing key files...\n");
bp_public = BIO_new_file("public.pem", "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if(ret != 1) {
goto free_all;
}
// Save the private key in PEM format
bp_private = BIO_new_file("private.pem", "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
// Free everything
free_all:
BIO_free_all(bp_public);
BIO_free_all(bp_private);
RSA_free(r);
BN_free(bne);
printf("Done!\n");
}
这显然是以PEM 格式编写密钥。我还需要能够在代码中将数据实际存储在内存中,而不仅仅是将其直接写入文件,因为我还需要用 public 键做一些其他事情。
感谢您的帮助
我认为您需要使用 EVP_PKEY_assign_RSA
将密钥转换为 EVP_PKEY。然后你可以使用 i2d_PUBKEY_bio
写出一个生物。
对我的代码进行以下修改:
- 包含头文件
<openssl/evp.h>
- 声明 BIO 以写出 public_der
- 用
EVP_PKEY_new()
创建 EVP_PKEY 结构
- 使用
EVP_PKEY_assign_RSA
进行转换
- 用
i2d_PUBKEY_bio
写简历
在上下文中:
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
void main() {
int ret = 0;
RSA *r = NULL;
BIGNUM *bne = NULL;
BIO *bp_public = NULL, *bp_private = NULL, *bp_public_der = NULL;
int bits = 2048;
unsigned long e = RSA_F4;
// Generate the RSA key
printf("Generating RSA key...\n");
bne = BN_new();
ret = BN_set_word(bne, e);
if(ret != 1) {
goto free_all;
}
r = RSA_new();
ret = RSA_generate_key_ex(r, bits, bne, NULL);
if(ret != 1) {
goto free_all;
}
// Save the public key in PEM format
printf("Writing key files...\n");
bp_public = BIO_new_file("public.pem", "w+");
ret = PEM_write_bio_RSAPublicKey(bp_public, r);
if(ret != 1) {
goto free_all;
}
// Save the private key in PEM format
bp_private = BIO_new_file("private.pem", "w+");
ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL);
// Save in DER
EVP_PKEY *evp = EVP_PKEY_new();
ret = EVP_PKEY_assign_RSA(evp, r);
if(ret != 1){
printf("failure %i\n", ret);
}
bp_public_der = BIO_new_file("public.key", "w+");
ret = i2d_PUBKEY_bio(bp_public_der, evp);
// Free everything
free_all:
BIO_free_all(bp_public);
BIO_free_all(bp_public_der);
BIO_free_all(bp_private);
RSA_free(r);
BN_free(bne);
printf("Done!\n");
}
您现在可以在 public.key
中找到 public 键的 DER。你应该能够为私人做同样的事情。
希望对您有所帮助。
您的问题 "saves an X.509 public key in DER format" 的实际含义有点含糊。假设您实际上是指 "save it as a SubjectPublicKeyInfo structure" (这是持有 public 密钥的 X.509 证书的一部分),那么您应该使用 i2d_RSA_PUBKEY (或 i2d_RSA_PUBKEY_fp 或 i2d_RSA_PUBKEY_bio) 将其写出(无需先将其转换为 EVP_PKEY)。
对于 DER 格式的 PKCS#8 私钥,您当前的方法对于 PEM 格式不正确。 PEM_write_bio_RSAPrivateKey() 函数将以传统格式(不是 PKCS#8)写出来。
我假设您不想做任何复杂的事情,比如先加密密钥。对于这个,您需要将其转换为 EVP_PKEY(使用 @JawguyChooser 提到的 EVP_PKEY_assign_RSA())。接下来,您使用(遗憾的是未记录)函数 EVP_PKEY2PKCS8.
获得一个 PKCS8_PRIV_KEY_INFO 结构PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
使用完 PKCS8_PRIV_KEY_INFO_free() 后,您需要释放此结构。接下来使用 i2d_PKCS8_PRIV_KEY_INFO()(或 i2d_PKCS8_PRIV_KEY_INFO_fp() 或 i2d_PKCS8_PRIV_KEY_INFO_bio)写出 PKCS8 DER。
有关这些函数的各种信息,请参阅手册页:
https://www.openssl.org/docs/man1.1.0/crypto/i2d_RSAPublicKey.html