###前提・実現したいこと
iOSアプリにてクライアント証明書を使用したシステムを作成しています。
言語はObjective-Cを使用。
実現したいことは以下の2つです。
①オレオレサーバ証明書を使用した認証
テスト用のサーバを立てているのでサーバ証明書の認証が必要になります。
正式なサーバ証明書がある場合、このステップはいらないかもしれません。
②クライアント証明書を使用した認証
独自のiOSアプリよりクライアント証明書の認証を行いたいです。
iOSアプリに事前にクライアント証明書を組み込んでおき、https通信の前に読み込む方式を考えています。
下記の記事を参考にしています。
http://cocoadays-info.blogspot.jp/2012/01/blog-post_21.html
https://gist.github.com/shunsuke0125/9181757
###発生している問題・エラーメッセージ
実現したいことについてそれぞれ問題が発生しています。
①オレオレサーバ証明書を使用した認証
下部に載せているコードを実行したところ、認証チャレンジにてkSecTrustResultRecoverableTrustFailureとなり認証失敗となります。
safariからの通信はできているため、サーバ証明書の内容は正しいと思われます。
下記のページを参考に実装しています。
http://miblog.guruguruheadslab.com/archives/46
SSL通信を行うためにxcode側で何か必要なのでしょうか・・・・
②クライアント証明書を使用した認証
認証が必要な時に呼ばれる下記のメソッドが呼ばれません。
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
①の認証が失敗しているためでしょうか。
③その他
下記に記載しているクライアント証明書の認証処理が仮に通った場合、GET要求が発行されることになるのでしょうか。
それとも、認証が成功し、コネクションが確立された後に再度発行する必要があるのでしょうか。
###該当のソースコード
Objective-C
//GET要求処理 ここから開始
- (void)testClientCertificate
{
NSString* url = @“GET要求先のURL”;
//リクエスト作成 NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; //コネクション作成 NSURLConnection *connection = [NSURLConnection connectionWithRequest:req delegate:self]; if (!connection) { NSLog(@"コネクションなし"); } else { NSLog(@"コネクションあり"); }
}
- (SecCertificateRef)sslCertificate
{
if (!sslCertificate )
{
NSString *path = [[NSBundle mainBundle] pathForResource:@“サーバ証明書のファイル名” ofType:@"cer"];
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
sslCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
}
return sslCertificate;
}
/*
- 認証が必要な場合に呼び出される
- (NSURLConnectionに対しある種類の認証手順を知っている旨を伝える)
- ※Deprecated in iOS5.0
*/
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust];
}
/*
- 認証が必要な場合に呼び出される
- for iOS5.0 and later
*/
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ( [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]
|| [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest] )
{
NSLog(@"Basic認証");
}
else if ( [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] )
{
NSLog(@"SSL認証");
NSURLProtectionSpace *protecitionSpace = [challenge protectionSpace]; SecTrustRef trust = [protecitionSpace serverTrust]; NSURLCredential *credential = [NSURLCredential credentialForTrust:trust]; NSArray *certs = [[NSArray alloc] initWithObjects:(id)[[self class] sslCertificate], nil]; OSStatus status = SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)certs); if ( status != errSecSuccess ) { NSLog(@"SecTrustSetAnchorCertificates err:%ld", status); [connection cancel]; return; } SecTrustResultType trustResult = kSecTrustResultInvalid; status = SecTrustEvaluate(trust, &trustResult); if ( status != errSecSuccess ) { NSLog(@"SecTrustEvaluate err:%ld", status); NSLog(@"trustResult:%ld", trustResult); [connection cancel]; return; } switch ( trustResult ) { case kSecTrustResultProceed: // valid and user has explicitly accepted it. case kSecTrustResultUnspecified: // valid and user has not explicitly accepted or reject it. generally you accept it in this case. { [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; return; } break; case kSecTrustResultRecoverableTrustFailure: // invalid, but in a way that may be acceptable, such as a name mismatch, expiration, or lack of trust (such as self-signed certificate) { [challenge.sender cancelAuthenticationChallenge:challenge]; [connection cancel]; } break; default: [challenge.sender cancelAuthenticationChallenge:challenge]; [connection cancel]; break; } } else if ( [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) { NSLog(@"クライアント認証"); OSStatus status; CFArrayRef importedItems = NULL; // パスワード設定 NSString *password = @“パスワード”; //クライアント証明書データ作成 NSString *pkcs12Path = [[NSBundle mainBundle] pathForResource:@“クライアント証明書の名前” ofType:@"pfx"]; //認証データP12のファイルを読み込み NSData *PKCS12Data = [NSData dataWithContentsOfFile:pkcs12Path]; status = SecPKCS12Import((__bridge CFDataRef)PKCS12Data, (__bridge CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:password, kSecImportExportPassphrase, nil], &importedItems); if (status == errSecSuccess) { NSArray* items = (__bridge NSArray*)importedItems; NSLog(@"%@", items); SecIdentityRef identityRef = (__bridge SecIdentityRef)[[items objectAtIndex:0] objectForKey:(__bridge id)kSecImportItemIdentity]; NSLog(@"%@", identityRef); NSURLCredential* credential = [NSURLCredential credentialWithIdentity:identityRef certificates:nil persistence:NSURLCredentialPersistenceNone]; NSLog(@"%@", credential); //認証送信(?) [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; if (importedItems != NULL) CFRelease(importedItems); } }
}
###補足情報(言語/FW/ツール等のバージョンなど)
●言語
Objective-C
●開発環境
Xcode8.2.1
●iOS
iOS10.2
些細なことでも良いので情報を頂けると助かります。
よろしくお願いいたします。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。