目前我正在开发一个使用相互身份验证以便与 REST 接口通信的应用程序。因为我对这个话题很陌生,所以我研究了几个例子——现在我有一些问题。我希望我能够将所有知识片段拼凑在一起,以便更好地了解整个过程。
该过程应如下所示:
- 我得到了包含服务器公钥的导出服务器证书,并将其添加到应用程序包(稍后用于 SSL Pinning)。
- 第一个请求,代表 2 路身份验证的开始,是一个发布请求,它还包含一个证书签名请求以获取客户端证书(需要与 REST 接口的安全部分进行对话)。CSR 是通过 openSSL 库在代码中动态生成的。
- 服务器的响应返回用于客户端身份验证的签名证书。此证书采用 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
现在我的问题。我看到了几个使用 PKCS12 格式(需要私钥和证书颁发机构)而不是 DER 编码证书的示例,以针对服务器验证自我。但是,如何在 `didReceiveAuthenticationChallenge 中使用我的 DER 格式的签名证书来获取更多请求?还有一个 Android 应用程序使用相同的过程进行相互身份验证,并且不需要 PKCS12 证书。
会很高兴一些提示。谢谢。