我正在创建一个使用TLS与Web服务器通信的iOS应用程序。当我访问Web服务器时,它会向我的设备提供证书,我想验证我可以信任它。
我将xcode项目中嵌入的根证书作为der文件。到目前为止,我所拥有的代码在NSURLConnection的委托函数中获取了两个证书的NSString版本,用于身份验证挑战。
有关如何手动验证的任何想法?
这是我目前的代码:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"Certificate challenge");
if (self.stageNum==0) {
id <NSURLAuthenticationChallengeSender> sender=challenge.sender;
NSURLProtectionSpace *protectionSpace=challenge.protectionSpace;
SecTrustRef trust=[protectionSpace serverTrust];
//Get server certificate
SecCertificateRef certificate=SecTrustGetCertificateAtIndex(trust, 0);
NSData *serverCertificateData=(__bridge NSData *)SecCertificateCopyData(certificate);
NSString *serverBase64Certificate=[serverCertificateData base64EncodedStringWithOptions:0];
//Get our certificate
NSData *certData1 = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"SUMOSRoot" ofType:@"der"]];
NSString *certBase64=[certData1 base64EncodedStringWithOptions:0];
//Heres where I need to compare the certificates
//
//
[sender useCredential:[NSURLCredential credentialForTrust:protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
}
答案 0 :(得分:1)
我认为这篇文章解决了你的目的。精美的书面/解释。
懒得打开链接的人,我会在帖子中添加一些描述。
答案 1 :(得分:1)
我不确定你为什么要获得NSString
代表。获得SecTrustRef
后,可以调用SecTrustCopyPublicKey
将公钥复制到SecKeyRef,然后将其与原始密钥数据(原始字节)进行比较。如果公钥匹配,则应接受证书。
这种技术称为&#34;证书固定&#34;,我确定Stack Overflow上可能有很多答案可以提供完整的代码示例,如果你搜索该术语。
表面上你也可以比较证书,但这可能不是你想要做的,因为证书会定期到期并且必须更新。如果您比较密钥,那么即使它们重新生成证书,它也将继续工作(假设它们使用相同的私钥/公钥对重新生成)。
或者如果您愿意将其绑定到特定的长期私有根证书,您可以将其添加到可信锚点列表并重新评估信任对象,但需要注意的是,当私有根证书出现时,这将会中断到期。另一方面,如果您固定密钥,如果您因某种原因需要更改私钥,它将会中断...所以这是一个权衡。
当然,一般来说,如果可能的话,最好的选择是获得真正的CA证书并且不要乱用任何链验证,但我认为这不是&#39 ; t可能(例如,因为服务器位于.local域中,在物理设备上生成自己的证书而没有Internet访问,或者其他类似的原因)。因此,对于与本地网络上的任意硬件进行安全通信之类的事情,密钥锁定是最佳方法。如果密钥不匹配,则要求用户将其添加为新设备或其他任何内容。