我正在使用sha1WithRSAEncryption(即不是根据SecTrustEvaluate returns kSecTrustResultRecoverableTrustFailure on iOS 5的MD5)服务器证书,使用简单的ca-> subca->服务器沿袭生成。
openssl req -new -x509 -subj /CN=ca/O=1002 -nodes -keyout /dev/stdout -set_serial 4 -days 3650 > ca-1002.pem
openssl req -new -subj /CN=sub-ca/O=1002 -nodes -keyout subca-1002.pem -set_serial 5 -days 3650 | openssl x509 -CA ca-1002.pem -req -set_serial 1 >> subca-1002.pem
openssl req -new -subj /CN=localhost:2002/O=1002 -nodes -keyout cert-1002.pem -set_serial 6 -days 3650 | openssl x509 -CA subca-1002.pem -req -set_serial 1 >> cert-1002.pem
用于服务器;带有服务器链SSLCACertificateFile和稍后由iPhone / iPad应用程序读取的DER文件。
cat ca-1002.pem subca-1002.pem > chain-1002.pem
openssl x509 -in ca-1002.pem -outform DER -out ca-1002.der
我确保在评估中得到一个发言权:
-(BOOL)connection:(NSURLConnection *)aConnection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space
{
DLog(@" authenticationMethod: %@",[space authenticationMethod]);
// nil/not set - rely on the keychain, set to an empty array indicates
// we know what we're doing -and accept anything - otherwise a list
// of certs gotten from reading in DER files.
//
NSArray *acceptableCAs = [delegate sslAcceptableServerCACertificates];
if ([[space authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
NSArray *acceptableCAs = [delegate sslAcceptableServerCACertificates];
return acceptableCAs != nil ? YES : NO;
}
// Client cert stuff snipped.
// the keychain is used.
return NO;
}
到目前为止一切顺利。
-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSURLProtectionSpace * space = [challenge protectionSpace];
if ([space.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSArray *acceptableCAs = [delegate sslAcceptableServerCACertificates];
NSURLCredential *newCredential;
if (acceptableCAs == nil) { ... }
// We'll leave this to the keychain by doing nothing. (works splendidly)
else if ([acceptableCAs count] == 0) { }
// We'll accept 'anything' - or in this case - exactly this server.
// (this works just fine).
有效 - 但是当我特定1个或多个证书明确时 - 事情就失败了:
else {
SecTrustRef secTrustRef = challenge.protectionSpace.serverTrust;
SecTrustResultType result;
NSMutableArray * serverChain = [[NSMutableArray alloc] init];
for(long i = 0; i < SecTrustGetCertificateCount(secTrustRef); i++) {
SecCertificateRef cr = SecTrustGetCertificateAtIndex(secTrustRef, i);
DLog(@"Server cert %04ld: %@", i, cr);
DLog(@" %@", [SimpleCertificate sha1fingerprint:cr]);
[serverChain addObject:(__bridge id)(cr)];
}
for(NSUInteger i = 0; i < [acceptableCAs count]; i++) { .. dump these too }
SecTrustSetAnchorCertificatesOnly(secTrustRef, YES);
SecTrustSetAnchorCertificates(secTrustRef, (__bridge CFArrayRef)acceptableCAs);
// SecTrustSetAnchorCertificatesOnly(secTrustRef, NO);
// assert(SecTrustCreateWithCertificates((__bridge CFTypeRef)(serverChain), SecPolicyCreateSSL(YES, nil), &secTrustRef) == noErr);
// assert(SecTrustCreateWithCertificates((__bridge CFTypeRef)(serverChain), SecPolicyCreateSSL(NO, nil), &secTrustRef) == noErr);
// assert(SecTrustCreateWithCertificates((__bridge CFTypeRef)(serverChain), SecPolicyCreateBasicX509(), &secTrustRef) == noErr);
// assert(SecTrustSetVerifyDate(secTrustRef, ...);
assert(SecTrustEvaluate(secTrustRef, &result) == noErr);
DLog(@"SecTrustEvaluate gives us: %lu", result);
....
我收到以下错误。 SecTrustEvaluate总是给我一个5(有时是4)。
尝试过各种建议;如日期转换,验证它是sha1而不是md5等。
athAgstPrSp:] [Line 68] authenticationMethod: NSURLAuthenticationMethodServerTrust
didRecAChlg:] [Line 98] authenticationMethod: NSURLAuthenticationMethodServerTrust
didRecAChlg:] [Line 143] Server cert 0000: <cert(0xd637ce0) s: localhost:2002 i: sub-ca>
didRecAChlg:] [Line 144] 8D:21:95:20:11:D0:9C:27:86:56:B3:0B:A6:F7:A2:CF:4C:F6:67:64
didRecAChlg:] [Line 143] Server cert 0001: <cert(0xd638710) s: sub-ca i: ca>
didRecAChlg:] [Line 144] 30:58:8E:F9:B8:29:5E:84:46:E3:0B:98:0D:B0:28:23:3D:7E:86:A3
didRecAChlg:] [Line 143] Server cert 0002: <cert(0xd638af0) s: ca i: ca>
didRecAChlg:] [Line 144] 8E:A2:D9:13:AF:8B:AE:82:1C:39:E9:79:72:98:2A:B4:C0:17:0D:F0
didRecAChlg:] [Line 150] CA cert 0000: <cert(0xf0397f0) s: ca i: ca>
didRecAChlg:] [Line 151] 8E:A2:D9:13:AF:8B:AE:82:1C:39:E9:79:72:98:2A:B4:C0:17:0D:F0
didRecAChlg:] [Line 159] SecTrustEvaluate gives us: 5
注意 - 我试图避免手动与主要答案的SHA1进行比较: Does SecTrustEvaluate() look for root certificates in the application keychain?尽可能干净地依赖钥匙链而不是。我还有其他一些使用芯片卡和钥匙串的用例。上面示例中的主机名匹配。在上面 - 服务器001..003证书匹配1:1 openssl s_client看到的内容;并且CA证书确实是提供的DER文件(并且与服务器闪存CA证书002相同)。我们还尝试在CA和客户端上设置SubjectAltNames;并且没有看到有所作为(正如SecTrustEvaluate always returns kSecTrustResultRecoverableTrustFailure with SecPolicyCreateSSL所建议的那样)是有道理的,因为我们知道在钥匙串/配置文件中手动导入它们使得完全相同的证书与默认的钥匙串对象一样完美。
欢迎任何和所有建议。寻找一种干净的方式在NSURLConnectionDelegate中说要么接受钥匙串,接受'任何'或接受特定的东西。
谢谢,
DW传递。