OpenSSL:如何从RSA结构体将生成的密钥导出到C字符数组?
将RSA密钥对导出到C字符数组的实现方法
嗨,刚好碰到过类似的需求!你已经用RSA_generate_key_ex生成了RSA密钥对,确实PEM_write_RSAPublicKey这类函数只能写文件,但OpenSSL的内存BIO接口可以完美解决这个问题——我们可以把密钥先写入内存缓冲区,再把缓冲区里的数据复制到C字符数组里。
下面是整合到你现有代码里的完整实现,包含公钥和私钥的导出:
#include <openssl/rsa.h> #include <openssl/bn.h> #include <openssl/bio.h> #include <openssl/pem.h> #include <stdlib.h> #include <stdio.h> int main() { int ret = 0; RSA *r = NULL; BIGNUM *bne = NULL; char *pub_key = NULL; char *pri_key = NULL; BIO *pub_bio = NULL; BIO *pri_bio = NULL; bne = BN_new(); ret = BN_set_word(bne, RSA_F4); if(ret != 1) { BN_free(bne); return 0; } r = RSA_new(); ret = RSA_generate_key_ex(r, 2048, bne, NULL); if(ret != 1){ RSA_free(r); BN_free(bne); return 0; } // -------------------------- 导出公钥到C字符数组 -------------------------- pub_bio = BIO_new(BIO_s_mem()); if (!pub_bio) { goto cleanup; } // 将公钥写入内存BIO if (!PEM_write_bio_RSAPublicKey(pub_bio, r)) { goto cleanup; } // 获取内存中数据的长度 size_t pub_len = BIO_pending(pub_bio); // 分配字符数组(+1是为了存储字符串终止符) pub_key = malloc(pub_len + 1); if (!pub_key) { goto cleanup; } // 从BIO读取数据到数组 BIO_read(pub_bio, pub_key, pub_len); pub_key[pub_len] = '\0'; // 添加字符串终止符,方便作为C字符串使用 // -------------------------- 导出私钥到C字符数组 -------------------------- pri_bio = BIO_new(BIO_s_mem()); if (!pri_bio) { goto cleanup; } // 将私钥写入内存BIO(NULL表示不加密私钥,若需要加密可以传入密码相关参数) if (!PEM_write_bio_RSAPrivateKey(pri_bio, r, NULL, NULL, 0, NULL, NULL)) { goto cleanup; } size_t pri_len = BIO_pending(pri_bio); pri_key = malloc(pri_len + 1); if (!pri_key) { goto cleanup; } BIO_read(pri_bio, pri_key, pri_len); pri_key[pri_len] = '\0'; // 这里可以使用pub_key和pri_key,比如打印出来验证 printf("Public Key:\n%s\n", pub_key); printf("Private Key:\n%s\n", pri_key); cleanup: // 释放所有资源,避免内存泄漏 if (pub_key) free(pub_key); if (pri_key) free(pri_key); if (pub_bio) BIO_free(pub_bio); if (pri_bio) BIO_free(pri_bio); if (r) RSA_free(r); if (bne) BN_free(bne); return ret == 1 ? 1 : 0; }
关键知识点说明:
- 内存BIO:
BIO_s_mem()创建一个基于内存的BIO对象,相当于内存缓冲区,用来替代文件指针作为写入目标。 - PEM内存写入函数:
PEM_write_bio_RSAPublicKey和PEM_write_bio_RSAPrivateKey是对应文件版本的内存版API,专门用来将密钥写入内存BIO。 - 数据读取:
BIO_pending()可以获取BIO中已写入的数据长度,用这个长度来分配字符数组的大小,之后用BIO_read()把数据从BIO复制到数组里。 - 资源释放:所有分配的内存和OpenSSL对象都要记得释放,示例里用
goto cleanup统一处理释放逻辑,是C语言里常用的资源管理方式。
内容的提问来源于stack exchange,提问作者81Vm3
相关产品推荐
相关产品推荐

