【问题标题】:How do I retrieve Subject or Issuer Distinguished Name from a certificate with Apple Security framework?如何使用 Apple 安全框架从证书中检索主题或颁发者可分辨名称?
【发布时间】:2021-06-05 12:19:45
【问题描述】:

我想使用SecCertificateCopyValues 函数但找不到正确的证书OID。 https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/certificate_oids?language=objc

我应该使用其他功能吗?

【问题讨论】:

    标签: c objective-c macos security certificate


    【解决方案1】:

    是的,您应该使用SecCertificateCopyValues。在这个返回的字典中,从您提到的 Apple 文档链接中搜索 kSecOIDX509V1IssuerName。在SecCertificateCopyValues 的文档中提到,

    此字典中的每个条目本身就是一个字典,其键值在Certificate Property Keys 中描述。

    因此,例如,要获取发行人的通用名称,您可以:

    • 检索密钥 kSecOIDX509V1IssuerName 的字典
    • 从那里得到键为 kSecPropertyKeyValue 的值数组
    • 每个数组元素本身就是一个字典
    • 例如对于您要使用密钥 kSecOIDCommonName 的通用名称

    要创建专有名称,您可以检查不同的键。

    如果你有OID,可以查看苹果开源certificate values中对应的常量,添加到代码中获取你感兴趣的值:

    在代码中,这可能如下所示:

    static CFStringRef createDistinguishedName(CFDictionaryRef certValues, CFStringRef key) {
        CFDictionaryRef dict = CFDictionaryGetValue(certValues, key);
        CFArrayRef values = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
        
        CFMutableStringRef dn = CFStringCreateMutableCopy(NULL, 0, CFSTR(""));
        
        CFStringRef keys[] = { kSecOIDCommonName, kSecOIDOrganizationName, kSecOIDOrganizationalUnitName, kSecOIDLocalityName, kSecOIDStateProvinceName, kSecOIDCountryName, kSecOIDSerialNumber, kSecOIDEmailAddress};
        CFStringRef txt[] = { CFSTR("CN"), CFSTR("O"), CFSTR("OU"), CFSTR("L"), CFSTR("S"), CFSTR("C"), CFSTR("SERIALNUMBER"), CFSTR("MAIL")};
        
        bool appendComa = false;
        for(int i = 0; i < CFArrayGetCount(values); i++) {
            CFDictionaryRef subDict = CFArrayGetValueAtIndex(values, i);
            CFStringRef labelVal = CFDictionaryGetValue(subDict, kSecPropertyKeyLabel);
            
            for(int k = 0; k < sizeof(keys)/sizeof(keys[0]); k++) {
                if (kCFCompareEqualTo == CFStringCompare(labelVal, keys[k], 0)) {
                    if (appendComa)
                        CFStringAppend(dn, CFSTR(", "));
                    CFStringAppend(dn, txt[k]);
                    CFStringAppend(dn, CFSTR("="));
                    CFStringAppend(dn, CFDictionaryGetValue(subDict, kSecPropertyKeyValue));
                    appendComa = true;
                }
            }
        }
        return dn;
    }
    

    可以这样调用:

    void printDN(CFDataRef certData) {
        SecCertificateRef certRef = SecCertificateCreateWithData(NULL, certData);
        CFDictionaryRef certValues = SecCertificateCopyValues(certRef, nil, nil);
        CFStringRef dn = createDistinguishedName(certValues, kSecOIDX509V1IssuerName);
        CFShow(dn);
        CFRelease(dn);
        CFRelease(certValues);
        CFRelease(certRef);
    }
    

    来自here 的示例证书将产生以下字符串:

    C=JP, S=Tokyo, L=Chuo-ku, O=Frank4DD, OU=WebCert Support, CN=Frank4DD Web CA, MAIL=support@frank4dd.com
    

    【讨论】:

    • 很好的答案!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2021-04-22
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    相关资源
    最近更新 更多