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

如何在OpenSSL CMS签名中添加指定OID的signedAttr?

如何在OpenSSL CMS签名中添加OID 1.2.840.113635.100.9.1的Signed Attribute

这个OID对应的是Apple的apple-application-identifier属性,通常用于iOS/macOS生态的代码签名场景。常规的CMS_sign()高层API确实不会直接暴露添加自定义Signed Attribute的入口,你需要手动操作底层的CMS结构来实现。下面是具体的步骤和代码示例:

核心思路

OpenSSL的CMS签名结构中,每个CMS_SignerInfo包含一组Signed Attributes。要添加自定义属性,你需要:

  • 创建并初始化CMS签名的基础结构
  • 定位到目标CMS_SignerInfo对象
  • 构造指定OID的X509_ATTRIBUTE对象
  • 将该属性添加到Signed Attributes集合
  • 重新计算签名(因为Signed Attributes是签名覆盖的内容,修改后必须重新签名)

代码示例(C语言API)

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

int add_apple_app_id_attr(CMS_ContentInfo *cms, EVP_PKEY *pkey, const char *app_id) {
    // 获取第一个SignerInfo(如果有多个签名者,需要遍历处理)
    STACK_OF(CMS_SignerInfo) *si_stack = CMS_get0_signerInfos(cms);
    if (!si_stack || sk_CMS_SignerInfo_num(si_stack) == 0) {
        fprintf(stderr, "No signer info found in CMS structure\n");
        return 0;
    }
    CMS_SignerInfo *si = sk_CMS_SignerInfo_value(si_stack, 0);

    // 创建OID对象
    ASN1_OBJECT *oid = OBJ_txt2obj("1.2.840.113635.100.9.1", 1);
    if (!oid) {
        fprintf(stderr, "Failed to create OID\n");
        return 0;
    }

    // 创建属性值(UTF-8字符串类型)
    ASN1_UTF8STRING *attr_val = ASN1_UTF8STRING_new();
    if (!attr_val || !ASN1_STRING_set(attr_val, app_id, -1)) {
        fprintf(stderr, "Failed to set attribute value\n");
        ASN1_OBJECT_free(oid);
        ASN1_UTF8STRING_free(attr_val);
        return 0;
    }

    // 创建X509_ATTRIBUTE对象
    X509_ATTRIBUTE *attr = X509_ATTRIBUTE_create_by_OBJ(NULL, oid, V_ASN1_UTF8STRING, attr_val);
    if (!attr) {
        fprintf(stderr, "Failed to create X509 attribute\n");
        ASN1_OBJECT_free(oid);
        ASN1_UTF8STRING_free(attr_val);
        return 0;
    }

    // 获取或初始化Signed Attributes集合
    STACK_OF(X509_ATTRIBUTE) *signed_attrs = CMS_SignerInfo_get0_attrs(si);
    if (!signed_attrs) {
        signed_attrs = sk_X509_ATTRIBUTE_new_null();
        if (!signed_attrs || !CMS_SignerInfo_set_attrs(si, signed_attrs)) {
            fprintf(stderr, "Failed to initialize signed attributes\n");
            X509_ATTRIBUTE_free(attr);
            ASN1_OBJECT_free(oid);
            ASN1_UTF8STRING_free(attr_val);
            return 0;
        }
    }

    // 添加属性到集合
    if (!sk_X509_ATTRIBUTE_push(signed_attrs, attr)) {
        fprintf(stderr, "Failed to push attribute to signed attrs\n");
        X509_ATTRIBUTE_free(attr);
        ASN1_OBJECT_free(oid);
        ASN1_UTF8STRING_free(attr_val);
        return 0;
    }

    // 重新计算签名(因为Signed Attributes被修改,必须重新签名)
    if (!CMS_SignerInfo_sign(si, pkey, NULL, NULL, 0)) {
        fprintf(stderr, "Failed to re-sign CMS signer info\n");
        return 0;
    }

    // 释放临时对象(attr已经被栈接管,不需要手动释放)
    ASN1_OBJECT_free(oid);
    ASN1_UTF8STRING_free(attr_val);

    return 1;
}

// 使用示例
int main() {
    // 假设你已经有输入数据in、签名密钥pkey、证书cert
    BIO *in = BIO_new_file("data.txt", "r");
    EVP_PKEY *pkey = PEM_read_PrivateKey(BIO_new_file("private.key", "r"), NULL, NULL, NULL);
    X509 *cert = PEM_read_X509(BIO_new_file("cert.pem", "r"), NULL, NULL, NULL);

    // 创建基础CMS签名结构(DETACHED表示分离式签名,根据你的需求调整)
    CMS_ContentInfo *cms = CMS_sign(cert, pkey, NULL, in, CMS_DETACHED);

    // 添加apple-application-identifier属性
    if (!add_apple_app_id_attr(cms, pkey, "com.yourcompany.yourapp")) {
        fprintf(stderr, "Failed to add apple app id attribute\n");
        CMS_ContentInfo_free(cms);
        return 1;
    }

    // 输出CMS签名到文件
    BIO *out = BIO_new_file("signed.cms", "w");
    i2d_CMS_bio(out, cms);

    // 资源释放
    BIO_free(in);
    BIO_free(out);
    EVP_PKEY_free(pkey);
    X509_free(cert);
    CMS_ContentInfo_free(cms);

    return 0;
}

注意事项

  • 如果你有多个签名者,需要遍历STACK_OF(CMS_SignerInfo)中的每个CMS_SignerInfo对象,为每个签名者添加该属性。
  • 内存管理要注意:X509_ATTRIBUTE被添加到栈后,不需要手动释放,栈会在CMS结构释放时一起清理;但OID和属性值需要手动释放。
  • 确保使用的OpenSSL版本支持这些API(OpenSSL 1.1.0及以上版本都没问题)。
  • 验证属性是否添加成功,可以用openssl cms -verify -in signed.cms -inform DER -noverify命令查看CMS结构的详细内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:34:36