私はsha1WithRSAEncryptionを使用しています(つまり、iOS 5でSecTrustEvaluateがkSecTrustResultRecoverableTrustFailureを返すようにMD5ではありません)単純なca-> subca-> server系列で生成されたサーバー証明書。
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) を返します。
さまざまな提案を試しました。日付のシフト、md5 ではなく sha1 であることの確認など。
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 証明書は、openssl s_client によって表示されるものと 1:1 で一致します。CA証明書は実際に提供されたDERファイルです(サーバーでフラッシュされたCA証明書002と同一です)。また、CA とクライアントで SubjectAltNames を設定しようとしました。違いが生じることはわかりませんでした(SecTrustEvaluateで示唆されているように、常にkSecTrustResultRecoverableTrustFailureをSecPolicyCreateSSLで返します)キーチェーン/プロファイルに手動でインポートすると、まったく同じ証明書がデフォルトのキーチェーンオブジェクトとして完全に正常に機能することがわかっているため、これは理にかなっています。
あらゆる提案を歓迎します。NSURLConnectionDelegate で、キーチェーンを受け入れる、「何でも」受け入れる、または特定のものを受け入れるという明確な方法を探しています。
ありがとう、
Dw。