如何用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_PUBKEYstructure 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_INFOstructure and encode it directly to DER. - In-Memory Public Key: We'll use OpenSSL's
i2d_X509_PUBKEYfunction 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_membuffer 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
相关产品推荐
相关产品推荐

