我需要编写一个生成RSA密钥的C程序,并以DER格式保存X.509公钥,以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格式写入密钥。我还需要能够在代码中实际拥有内存中的数据,而不是直接将其写入文件,因为我需要对公钥执行其他一些操作。
感谢您的帮助
答案 0 :(得分:2)
我认为您需要使用EVP_PKEY_assign_RSA
将密钥转换为EVP_PKEY。然后,您可以使用i2d_PUBKEY_bio
写出生物。
以下修改代码对我有用:
<openssl/evp.h>
EVP_PKEY_new()
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
中找到公钥的DER。你应该能够为私人做同样的事情。
希望这有帮助。
答案 1 :(得分:1)
你的问题对于你真正的意思是“以DER格式保存X.509公钥”有点含糊不清。假设您实际上是指“将其保存为SubjectPublicKeyInfo结构”(这是保存公钥的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