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

Swift中如何提取OpenSSL stack_st_X509中的证书内容?

从OpenSSL CMS签名中提取签名证书(Swift实现)

很高兴你已经搞定了CMS签名验证的部分!接下来要从CMS_get0_signers返回的栈中提取X509证书,其实就是利用OpenSSL提供的STACK操作函数结合Swift的不安全指针来遍历处理,我给你详细拆解下步骤和代码:


核心思路

OpenSSL的STACK_OF(X509)在Swift中被映射为UnsafeMutablePointer<stack_st_X509>,要提取里面的证书,需要用OpenSSL专门为X509栈提供的操作函数:

  • sk_X509_num():获取栈中证书的数量
  • sk_X509_value():根据索引取出对应位置的X509证书指针

完整代码示例

首先确保你的项目已经正确桥接了OpenSSL的头文件(在桥接文件中添加#include <openssl/cms.h>和#include <openssl/x509.h>),然后可以用下面的代码处理:

// 假设你已经成功验证CMS签名,得到了cms指针:UnsafeMutablePointer<CMS_ContentInfo>
guard let signersStack = CMS_get0_signers(cms) else {
    print("未找到任何签名证书")
    return
}

// 获取栈中证书的总数
let signerCount = sk_X509_num(signersStack)
print("共找到 \(signerCount) 个签名证书")

// 遍历栈中的每个证书
for index in 0..<signerCount {
    // 取出对应索引的X509证书指针
    guard let x509Cert = sk_X509_value(signersStack, index) else {
        print("无法获取索引 \(index) 的签名证书")
        continue
    }
    
    // 示例:获取证书的主题名称并打印
    // 方式1:使用X509_NAME_oneline(注意:返回的是静态缓冲区,无需手动释放,但线程不安全)
    if let subjectCStr = X509_NAME_oneline(X509_get_subject_name(x509Cert), nil, 0) {
        let subject = String(cString: subjectCStr)
        print("签名证书 \(index+1) 主题:\(subject)")
    }
    
    // 方式2:使用BIO读取(线程安全,推荐)
    let bio = BIO_new(BIO_s_mem())
    defer { BIO_free(bio) } // 确保BIO资源被释放
    
    if X509_NAME_print_ex(bio, X509_get_subject_name(x509Cert), 0, XN_FLAG_ONELINE) > 0 {
        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 2048)
        defer { buffer.deallocate() }
        
        let readLength = BIO_read(bio, buffer, 2047)
        if readLength > 0 {
            buffer[readLength] = 0 // 手动添加字符串结束符
            let subjectStr = String(cString: buffer)
            print("签名证书 \(index+1) 主题(安全方式):\(subjectStr)")
        }
    }
    
    // 如果你需要保留证书的引用,记得调用X509_up_ref(x509Cert)增加引用计数
    // 后续不再使用时,调用X509_free(x509Cert)释放资源
}

关键注意事项

  1. 内存管理:
    • CMS_get0_signers返回的栈由CMS结构持有,不需要手动释放,当你调用CMS_ContentInfo_free(cms)时,栈会被自动清理。
    • sk_X509_value返回的X509指针是栈内的引用,默认不需要手动X509_free,除非你调用了X509_up_ref增加了引用计数。
  2. 函数可用性:
    确保你的OpenSSL版本支持这些函数,不同版本的函数名可能略有差异(比如旧版本可能需要用宏而不是直接函数调用,但现代版本都支持直接调用sk_X509_num和sk_X509_value)。
  3. 错误处理:
    记得在每次获取指针后做非空判断,避免野指针导致的崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:27:47