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

如何从BIO加载含1至N个证书的PEM到STACK_OF(X509*)?

你说得没错,OpenSSL确实没有提供一个像PEM_read_bio_X509那样直接从BIO读取并返回STACK_OF(X509*)的函数。不过别担心,有两种常用的方法可以实现这个需求,我给你详细说说:

方法一:手动循环读取单个证书并构建栈

这是最直接也最常用的方式——循环调用PEM_read_bio_X509读取每个证书,直到遇到EOF,然后把每个读取到的X509对象推入栈中。需要注意处理内存分配错误和读取过程中的异常情况:

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

STACK_OF(X509)* load_certs_from_bio(BIO *bio) {
    // 创建空的X509栈
    STACK_OF(X509)* cert_stack = sk_X509_new_null();
    if (!cert_stack) {
        fprintf(stderr, "Failed to create X509 stack\n");
        return NULL;
    }

    X509* cert = NULL;
    // 循环读取每个PEM证书
    while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
        // 将证书推入栈中
        if (!sk_X509_push(cert_stack, cert)) {
            fprintf(stderr, "Failed to push certificate to stack\n");
            // 清理已获取的证书和栈
            X509_free(cert);
            sk_X509_pop_free(cert_stack, X509_free);
            return NULL;
        }
    }

    // 检查循环终止的原因:是正常EOF还是读取错误
    unsigned long err = ERR_get_error();
    if (ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
        fprintf(stderr, "Error reading certificates: %s\n", ERR_error_string(err, NULL));
        sk_X509_pop_free(cert_stack, X509_free);
        return NULL;
    }

    // 成功读取所有证书,返回栈
    return cert_stack;
}

使用完栈之后,记得用sk_X509_pop_free(cert_stack, X509_free)来释放栈和所有证书对象,避免内存泄漏。

方法二:利用X509_STORE间接加载(适合需要验证场景)

如果你最终需要把这些证书用于证书验证,可以借助X509_STORE来间接加载:

#include <openssl/x509_vfy.h>

X509_STORE* load_certs_to_store_from_bio(BIO *bio) {
    X509_STORE* store = X509_STORE_new();
    if (!store) {
        fprintf(stderr, "Failed to create X509 store\n");
        return NULL;
    }

    X509* cert = NULL;
    while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
        if (!X509_STORE_add_cert(store, cert)) {
            fprintf(stderr, "Failed to add certificate to store\n");
            X509_free(cert);
            X509_STORE_free(store);
            return NULL;
        }
        // X509_STORE_add_cert会接管证书的内存,不需要手动free
        cert = NULL;
    }

    unsigned long err = ERR_get_error();
    if (ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
        fprintf(stderr, "Error reading certificates: %s\n", ERR_error_string(err, NULL));
        X509_STORE_free(store);
        return NULL;
    }

    return store;
}

这种方法的好处是X509_STORE会自动管理证书的内存,不需要你手动维护栈的释放逻辑,适合后续要做证书链验证的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:01:18