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

OpenSSL与C开发:生成CSR时如何正确加载配置文件

问题分析与解决

你遇到的核心问题是:仅将配置加载到OSSL_LIB_CTX并不会自动把req_attributes段的内容注入到X509_REQ对象中。命令行工具openssl req内部会自动处理配置中的属性段,但C API需要手动完成这一步。

具体解决步骤

1. 加载配置并获取req_attributes段

加载配置后,需要通过CONF对象提取req_attributes段的键值对:

#include <openssl/conf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>

// 初始化上下文并加载配置
OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new();
if (!ctx || !OSSL_LIB_CTX_load_config(ctx, "./client.config")) {
    // 错误处理,比如打印错误信息
    goto cleanup;
}

// 获取配置对象
CONF *conf = OSSL_LIB_CTX_get0_config(ctx);
if (!conf) {
    // 错误处理
    goto cleanup;
}

// 提取req_attributes段的配置项
STACK_OF(CONF_VALUE) *attrs = NCONF_get_section(conf, "req_attributes");
if (!attrs) {
    // 错误处理,比如段不存在
    goto cleanup;
}

2. 将属性添加到X509_REQ对象

遍历req_attributes段的每个配置项,转换为X.509标准属性并添加到CSR:

// 创建CSR对象
X509_REQ *p_x509_req = X509_REQ_new_ex(ctx, NULL);
if (!p_x509_req) {
    // 错误处理
    goto cleanup;
}

// 逐个添加属性
for (int i = 0; i < sk_CONF_VALUE_num(attrs); i++) {
    CONF_VALUE *val = sk_CONF_VALUE_value(attrs, i);
    // 根据属性名称获取对应的NID(比如challengePassword对应NID_pkcs9_challengePassword)
    int nid = OBJ_sn2nid(val->name);
    if (nid == NID_undef) {
        // 跳过未知属性,或做自定义处理
        continue;
    }
    // 将属性添加到CSR
    if (!X509_REQ_add1_attr_by_NID(p_x509_req, nid, MBSTRING_UTF8, (const unsigned char *)val->value, -1)) {
        // 错误处理
        goto cleanup;
    }
}

3. 加载私钥并签名CSR

命令行工具会自动完成私钥加载和CSR签名,C代码需要手动实现:

// 加载私钥(PEM格式示例)
EVP_PKEY *key = NULL;
FILE *key_file = fopen("./my-key.pem", "r");
if (!key_file || !(key = PEM_read_PrivateKey(key_file, NULL, NULL, NULL))) {
    // 错误处理
    goto cleanup;
}
fclose(key_file);

// 设置CSR公钥并签名
if (!X509_REQ_set_pubkey(p_x509_req, key) || !X509_REQ_sign(p_x509_req, key, EVP_sha256())) {
    // 错误处理
    goto cleanup;
}

// 保存CSR到文件
FILE *csr_file = fopen("./certreq.csr", "w");
if (csr_file) {
    PEM_write_X509_REQ(csr_file, p_x509_req);
    fclose(csr_file);
}

// 资源清理
cleanup:
X509_REQ_free(p_x509_req);
EVP_PKEY_free(key);
OSSL_LIB_CTX_free(ctx);

关键说明

  • OSSL_LIB_CTX仅提供配置和算法的上下文环境,不会自动将配置内容绑定到具体的X509_REQ对象,必须手动读取配置段并应用。
  • X509_REQ_add1_attr_by_NID是将配置属性转换为X.509标准属性的核心函数,需确保配置中的属性名称(如challengePassword)对应正确的NID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 21:23:14