如何使用 Apple 安全框架从证书中检索主题或颁发者专有名称?
How do I retrieve Subject or Issuer Distinguished Name from a certificate with Apple Security framework?
我想使用 SecCertificateCopyValues
功能,但找不到正确的证书 OID。
https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/certificate_oids?language=objc
我应该使用其他功能吗?
是的,你应该使用 SecCertificateCopyValues
。在此返回的字典中,从您提到的 Apple 文档 link 中搜索 kSecOIDX509V1IssuerName
。在 SecCertificateCopyValues 的文档中提到,
Each entry in this dictionary is itself a dictionary with the keys described in 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
我想使用 SecCertificateCopyValues
功能,但找不到正确的证书 OID。
https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/certificate_oids?language=objc
我应该使用其他功能吗?
是的,你应该使用 SecCertificateCopyValues
。在此返回的字典中,从您提到的 Apple 文档 link 中搜索 kSecOIDX509V1IssuerName
。在 SecCertificateCopyValues 的文档中提到,
Each entry in this dictionary is itself a dictionary with the keys described in 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