在 x509 基本约束中检测 CA:TRUE
Posted
技术标签:
【中文标题】在 x509 基本约束中检测 CA:TRUE【英文标题】:Detecting CA:TRUE in x509 Basic Contraints 【发布时间】:2012-02-07 12:36:05 【问题描述】:检查证书基本约束的正确方法是什么?下面是我目前用来模仿钥匙串中显示的图标的代码(下面的原因是,虽然我们有一个
SFChooseIdentityPanel * identityPanel = [SFChooseIdentityPanel sharedChooseIdentityPanel];
不存在用于选择 CA 或主机/叶证书的等效项。这在设置/锁定 SSL 连接时很有用。
不幸的是 - 我无法在头文件中找到 OID 字符串以从证书中干净地提取 CA:TRUE 或 false(或以错误的方式使用 API)。
所以问题是
我如何干净利落地检查 CA:TRUE - 虽然下面的工作正常 - 我可以想象它会被格式错误的证书与正确位置的文本字符串挫败。
其次 - 我正在使用 Issuer==Subject 的启发式方法来检测自签名。有没有更清洁的方法来做到这一点?
最后 - 通过反复试验 - 下面似乎模仿了苹果在钥匙串中的选择 - 但文档相当难以理解。 kSecTrustResultProceed 是否真的意味着用户设置了覆盖和 kSecTrustResultUnspecified 实际上信任是由系统基本信任指定的?虽然它'工作' - 我不能完全理解文档的确切解释。
非常感谢。代码如下。
Dw.
@implementation NSImage (CertificateSelectionPanelExtensions)
+(NSImage *)iconForCertificate:(SecCertificateRef)certificateRef small:(BOOL)isSmall
BOOL isCA = FALSE, isInvalid = TRUE, isUserTrust = FALSE;
NSString * issuer = nil, * subject = nil;
const void *keys[] = kSecOIDX509V1SubjectName, kSecOIDX509V1IssuerName, kSecOIDExtendedKeyUsage, kSecOIDBasicConstraints ;
CFArrayRef keySelection = CFArrayCreate(NULL, keys , sizeof(keys)/sizeof(keys[0]), &kCFTypeArrayCallBacks);
CFDictionaryRef vals = SecCertificateCopyValues(certificateRef, keySelection, NULL);
CFArrayRef values;
CFDictionaryRef dict;
dict = CFDictionaryGetValue(vals, kSecOIDBasicConstraints );
values = dict ? CFDictionaryGetValue(dict, kSecPropertyKeyValue) : NULL;
if (values)
for(int i = 0; i < CFArrayGetCount(values); i++)
CFDictionaryRef subDict = CFArrayGetValueAtIndex(values, i);
// We cannot find OID defines for the CA - so rely on the lower libraries to give us a string
// of sorts. Not a good idea - as now this code can be foiled by a actual string.
//
NSString *k = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(subDict, kSecPropertyKeyLabel)];
NSString *v = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(subDict, kSecPropertyKeyValue)];
if ([@"Certificate Authority" isEqualToString:k] && [@"Yes" isEqualToString:v])
isCA = TRUE;
;
// Fall back on a simple self-sign check if there where no kSecOIDBasicConstraints.
// set on the cert. Note that it is a DN is equal check - in some cases
// doing a 509v3 Subject/Authority Key Identifier may be better ?? XXXX
//
if (!isCA && !values)
dict = CFDictionaryGetValue(vals, kSecOIDX509V1SubjectName);
values = dict ? CFDictionaryGetValue(dict, kSecPropertyKeyValue) : NULL;
subject = [NSString stringWithFormat:@"%@", values];
dict = CFDictionaryGetValue(vals, kSecOIDX509V1IssuerName);
values = dict ? CFDictionaryGetValue(dict, kSecPropertyKeyValue) : NULL;
issuer = [NSString stringWithFormat:@"%@", values];
// Crap way of secondgessing CA ness.
if ([issuer isEqualToString:subject])
isCA = TRUE;
;
SecPolicyRef policy = SecPolicyCreateBasicX509(); // SecPolicyCreateSSL(YES,nil);
CFArrayRef chain = CFArrayCreate(NULL, (const void**)(&certificateRef), 1, NULL);
SecTrustRef trustRef;
SecTrustCreateWithCertificates(chain, policy, &trustRef);
SecTrustResultType result;
SecTrustEvaluate (trustRef, &result);
if(result == kSecTrustResultProceed)
isUserTrust = TRUE;
isInvalid = FALSE;
else
if (result == kSecTrustResultUnspecified)
isInvalid = FALSE;
CFRelease(trustRef);
CFRelease(chain);
// Images as per /System/Library/Frameworks/SecurityInterface.framework/Versions/A/Resources
// Cert <Small | Large> <Personal | Root> [_Invalid | _UserTrust ]
//
return [NSImage imageNamed:[NSString stringWithFormat:@"Cert%@%@%@",
isSmall ? @"Small" : @"Large",
isCA ? @"Root" : @"Personal",
isInvalid ? @"_Invalid" : (isUserTrust ? @"_UserTrust" : @"")]];
@end
【问题讨论】:
【参考方案1】:basicConstraints 扩展在X.509 中定义如下:
basicConstraints EXTENSION ::=
SYNTAX BasicConstraintsSyntax
IDENTIFIED BY id-ce-basicConstraints
BasicConstraintsSyntax ::= SEQUENCE
cA BOOLEAN DEFAULT FALSE,
pathLenConstraint INTEGER (0..MAX) OPTIONAL
这反过来又根据可分辨编码规则 (X.690) 进行编码。 BasicConstraintsSyntax
序列的各个部分没有自己的 OID。
我不会声称自己是专家,但我认为您正在对 cA
标志进行的测试没有问题。请注意,我认为[NSString stringWithFormat:@"%@", ...]
部分是不必要的。
至于检查自签名证书,测试主题和颁发者名称似乎并非不合理;显然,这确实告诉您证书是否声称是自签名的,并且要实际测试它是否是您需要自己检查签名(无论这是否是您想要做的事情,我不知道)不知道)。仅供参考,关于密钥标识符的主题,根据RFC3280,在自签名证书的特定情况下,可以省略授权密钥标识符,因此没有授权密钥标识符的证书可能表明该证书是自签名的,但完全有可能有人故意颁发没有授权密钥标识符的格式错误的证书。
通过查看文档,最后一个问题似乎得到了解决,这表明这些值大致意味着您所说的。
另一件值得一提的是,有一些代码可以帮助解决这类事情;例如,Jens Alfke 的 MYCrypto 库
编辑(2012 年 2 月 8 日)
根据X.509 Style Guide,subject 名称可能为空,在这种情况下,您需要查看 subjectAltName 扩展名。这不太可能破坏依赖于比较主题和颁发者名称的自签名证书的测试 - 向自己颁发证书并为颁发者名称提供 DN 但然后将主题名称留空似乎是不合理的。但是,值得牢记。
【讨论】:
对 - 我通过查看 DER 字节确认确实如此。我更想要的是一种干净的方式来“询问”这个问题;使用 kSecPropertyKeyValue 或一些比较。以这种方式(或字符串比较)查看 DER 似乎有点作弊。而且我想避免编写适当的 DER 解码器。虽然看起来你建议的 MyCrypto 库 - 这正是可能需要的? 也许还值得一提的是,您上面显示的代码在 ios 上根本无法运行,因为它没有公开您正在使用的功能。我想如果 我 正在编写类似的代码,我会使用 MYCrypto。 谢谢!尝试使用 MYCrypto - 尽管它缺少 CA/主机对等锁定 - 所以看看我是否可以添加它。以上是关于在 x509 基本约束中检测 CA:TRUE的主要内容,如果未能解决你的问题,请参考以下文章