You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C语言生成RSA密钥并输出DER格式的X.509公钥与PKCS#8私钥

Solution for Generating RSA Keys in X.509 DER (Public) and PKCS#8 DER (Private) with In-Memory Public Key Storage

Got it, let's tackle your requirements step by step. Here's how to modify your existing OpenSSL code to meet all your needs:

Key Changes Explained

  • X.509 DER Public Key: The original code writes a PKCS#1 format public key in PEM. To get an X.509 DER public key, we need to convert the RSA key to an X509_PUBKEY structure first, then use DER encoding functions instead of PEM.
  • PKCS#8 DER Private Key: PKCS#8 is a standard, portable format for private keys. We'll wrap the RSA private key into a PKCS8_PRIV_KEY_INFO structure and encode it directly to DER.
  • In-Memory Public Key: We'll use OpenSSL's i2d_X509_PUBKEY function twice—once to calculate the exact memory size needed, then again to write the DER-encoded data into an allocated buffer for later use.

Modified Complete Code

#include <stdio.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/pkcs8.h>

int main() {
    int ret = 0;
    RSA *r = NULL;
    BIGNUM *bne = NULL;
    BIO *bp_public_der = NULL, *bp_private_der = NULL;
    X509_PUBKEY *pubkey = NULL;
    PKCS8_PRIV_KEY_INFO *p8info = NULL;
    unsigned char *pubkey_mem = NULL;
    int pubkey_mem_len = 0;
    int bits = 2048;
    unsigned long e = RSA_F4;

    // Generate the RSA key pair
    printf("Generating RSA key...\n");
    bne = BN_new();
    if (!bne) {
        fprintf(stderr, "Failed to create BIGNUM\n");
        goto free_all;
    }
    ret = BN_set_word(bne, e);
    if (ret != 1) {
        fprintf(stderr, "Failed to set public exponent\n");
        goto free_all;
    }
    r = RSA_new();
    if (!r) {
        fprintf(stderr, "Failed to create RSA structure\n");
        goto free_all;
    }
    ret = RSA_generate_key_ex(r, bits, bne, NULL);
    if (ret != 1) {
        fprintf(stderr, "Failed to generate RSA key\n");
        goto free_all;
    }

    // Convert RSA public key to X.509 standard format
    pubkey = X509_PUBKEY_new();
    if (!pubkey) {
        fprintf(stderr, "Failed to create X509_PUBKEY structure\n");
        goto free_all;
    }
    ret = X509_PUBKEY_set0_RSA(pubkey, r);
    if (ret != 1) {
        fprintf(stderr, "Failed to wrap RSA key into X509_PUBKEY\n");
        goto free_all;
    }

    // Save X.509 public key as DER file
    printf("Writing X.509 DER public key to file...\n");
    bp_public_der = BIO_new_file("public.der", "wb");
    if (!bp_public_der) {
        fprintf(stderr, "Failed to open public.der for writing\n");
        goto free_all;
    }
    ret = i2d_X509_PUBKEY_bio(bp_public_der, pubkey);
    if (ret != 1) {
        fprintf(stderr, "Failed to write X509 DER public key\n");
        goto free_all;
    }

    // Store X.509 public key in memory for later operations
    printf("Storing public key in memory...\n");
    // First call to get required buffer length
    pubkey_mem_len = i2d_X509_PUBKEY(pubkey, NULL);
    if (pubkey_mem_len <= 0) {
        fprintf(stderr, "Failed to calculate public key memory size\n");
        goto free_all;
    }
    pubkey_mem = malloc(pubkey_mem_len);
    if (!pubkey_mem) {
        fprintf(stderr, "Failed to allocate memory for public key\n");
        goto free_all;
    }
    // Second call to write DER data into buffer
    unsigned char *ptr = pubkey_mem;
    i2d_X509_PUBKEY(pubkey, &ptr);
    printf("Public key stored in memory: %d bytes available for use\n", pubkey_mem_len);

    // Convert RSA private key to PKCS#8 format and save as DER
    printf("Writing PKCS#8 DER private key to file...\n");
    p8info = PKCS8_PRIV_KEY_INFO_create(RSA_PKCS8_VERSION, EVP_PKEY_new(), r, NULL);
    if (!p8info) {
        fprintf(stderr, "Failed to wrap RSA key into PKCS#8 structure\n");
        goto free_all;
    }
    bp_private_der = BIO_new_file("private.der", "wb");
    if (!bp_private_der) {
        fprintf(stderr, "Failed to open private.der for writing\n");
        goto free_all;
    }
    ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp_private_der, p8info);
    if (ret != 1) {
        fprintf(stderr, "Failed to write PKCS#8 DER private key\n");
        goto free_all;
    }

    printf("All operations completed successfully!\n");

free_all:
    // Clean up all allocated resources
    BIO_free_all(bp_public_der);
    BIO_free_all(bp_private_der);
    X509_PUBKEY_free(pubkey);
    PKCS8_PRIV_KEY_INFO_free(p8info);
    RSA_free(r);
    BN_free(bne);
    free(pubkey_mem); // Don't forget to free the in-memory buffer when done
    return ret == 1 ? 0 : 1;
}

Usage Notes

  • Compile with OpenSSL libraries: gcc rsa_keygen.c -o rsa_keygen -lcrypto
  • The pubkey_mem buffer contains raw DER-encoded X.509 public key data—you can use this directly for tasks like network transmission or embedding in other cryptographic structures.
  • Added detailed error checking to simplify debugging if something goes wrong.

内容的提问来源于stack exchange,提问作者atoms118

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:39:22