現在、REST インターフェイスと通信するために相互認証を使用するアプリに取り組んでいます。私はこのトピックに非常に慣れていないため、いくつかの例を調べましたが、いくつか質問があります。プロセス全体をよりよく理解するために、すべての知識をまとめられることを願っています。
プロセスは次のようになります。
- サーバーの公開鍵を含むエクスポートされたサーバー証明書を取得し、それをアプリ バンドルに追加しました (これは後で SSL ピンニングに使用されます)。
- 双方向認証の開始を表す最初のリクエストは、クライアント証明書を取得するための証明書署名リクエストも含むポスト リクエストです (これは、REST インターフェースのセキュリティで保護された部分と通信するために必要です)。CSR は、openSSL lib を介してコードで動的に生成されます。
- サーバーの応答は、クライアント認証に使用される署名付き証明書を返します。この証明書は DER 形式であり、Base64 でエンコードされています。
最初のリクエストで SSL ピニングを実行するために使用するコードは次のようになり、SSL ピニングは期待どおりに機能します。
- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server-cert" ofType:@"cer"];
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSData *localCertificateData = [NSData dataWithContentsOfFile:cerPath];
if ([remoteCertificateData isEqualToData:localCertificateData]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:[challenge protectionSpace]];
NSLog(@"Certificate Pinning Succeeded");
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog(@"Certificate Pinning Failed");
}
}
しかし、サーバーから返された証明書をどのように処理すればよいでしょうか? 私が知る限り、次の NSURLConnection デリゲート メソッドを使用する必要があります。また、この証明書を何らかの方法でサーバーに提供する必要があります (さらなる要求のために)。
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace
{
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSLog(@"Wants to Authenticate Server Trust");
return YES;
}
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
NSLog(@"Wants to Authenticate Client Certificate");
return YES;
}
return NO;
}
と
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
今私の質問。サーバーに対して自己認証を行うために、DER でエンコードされた証明書の代わりに PKCS12 形式 (秘密鍵と認証局が必要) を使用する例をいくつか見ました。しかし、`didReceiveAuthenticationChallenge の DER 形式の署名付き証明書を今後の要求に使用するにはどうすればよいですか? 相互認証に同じプロセスを使用する Android アプリもあり、PKCS12 証明書は必要ありません。
何かのヒントになれば幸いです。どうも。