c - 以 DER 格式编写私钥/公钥

标签 c openssl rsa x509 pkcs#8

<分区>

我需要编写一个 C 程序来生成 RSA key ,并以 DER 格式保存 X.509 公钥和 DER 格式的 PKCS#8 私钥。我用过谷歌,但并没有真正找到太多。我到目前为止是这样的:

#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 格式编写 key 。我还需要能够在代码中将数据实际存储在内存中,而不仅仅是将其直接写入文件,因为我需要用公钥做一些其他事情。

谢谢你的帮助

最佳答案

您的问题在“以 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)将其写出。

我假设您不想做任何复杂的事情,比如先加密 key 。对于这个,您需要将其转换为 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

关于c - 以 DER 格式编写私钥/公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48324615/

相关文章:

c - 用C编写一个简单的时钟

c - 如何使用C代码从文本文件中读取时间戳数据?

c++ - 如何确定阻塞的 SSL BIO 连接是否已关闭?

c++ - 如何获取 OpenSSL BIO_do_connect() 失败原因?

ssl - ffmpeg 错误 SSL 例程 :ssl3_write_pending:bad write retry

swift - 如何快速处理长整数的答案

c - 带双引号的 sscanf

c - 打印正确数量的相同字符时出现问题。C 中的 RLE

C# 使用 RSA 签名和验证签名。编码问题

java - 在 Java 中使用 RSA 公钥加密数据并在 Crypto++ 中解密