質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

IIS

IIS(Internet Information Services)はマイクロソフト社によって開発されたwebサーバーです。Windows上で動作します。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Q&A

解決済

1回答

8118閲覧

iOSアプリからのクライアント認証について

konryu304

総合スコア8

Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

IIS

IIS(Internet Information Services)はマイクロソフト社によって開発されたwebサーバーです。Windows上で動作します。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

0グッド

0クリップ

投稿2016/12/27 06:45

###前提・実現したいこと
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

些細なことでも良いので情報を頂けると助かります。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

参考にされているサイトが古すぎるように思われます。
iOSは9.0以降からATS(App Transport Security)が導入されています。
これはセキュアな通信を確保するための仕組みです。
デフォルトは有効で、無効にするにはinfo.plistで設定しないといけません。
詳しくは以下のサイトを参考にしてください。
http://www.lac.co.jp/blog/category/security/20161017.html

①オレオレサーバ証明書を使用した認証

ATSでもオレオレサーバ証明書を使用することも可能ですが、ATSの要件に含まれる暗号強度で証明書を作成し、
端末にルート証明書をインストールする必要があります。
また、サーバ側の暗号化スイートも楕円暗号に対応したものでなくてはいけません。
前述のURLをご覧ください。
ATSが導入されて何度か経験したのが、ロードバランサーのSSLアクセラレータが
楕円暗号に対応していないものがあったり、楕円暗号では速度が出ない場合があります。
注意してください。

②クライアント証明書を使用した認証

おそらくATSによって①がブロックされて②に進んでいないのだと思います。
ただし、NSURLConnectionではなくNSURLSessionを使用すべきです。
NSURLConnectionを使用したアプリは2016年6月1日以降はAppStoreの審査に通らなくなっています。
AppStoreに掲載しないにしても、deprecatedなので新規に作成するアプリで使用すべきではありません。
NSURLSessionでクライアント証明書を使用する方法には以下のteratailの過去の質問が参考になります。
https://teratail.com/questions/45840

③その他

認証のデリゲートメソッドで正しく認証された結果が返ればGET要求が継続されるはずです。

投稿2016/12/31 06:04

nakasho_dev

総合スコア2655

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問