zoukankan      html  css  js  c++  java
  • https的证书认证 iOS版

    一、证书链

    SecTrustRef:

    SecTrustRef trust = challenge.protectionSpace.serverTrust;

    需要先拿出一个 SecTrustRef 对象,它是一种执行信任链验证的抽象实体,包含着验证策略(SecPolicyRef以及一系列受信任的锚点证书,而我们能做的也是修改这两样东西而已。

    SecTrustResultType trustResult = kSecTrustResultInvalid;

    // 函数的内部递归地从叶节点证书到根证书的验证

    OSStatus statue = SecTrustEvaluate(trust, &trustResult);

    二、系统验证策略及修改:

    SecTrustSetPolicies

    域名验证

    可以通过以下的代码获得当前的验证策略:

    CFArrayRef policiesRef;

    SecTrustCopyPolicies(trust, &policiesRef); 

    打印 policiesRef 后,你会发现默认的验证策略就包含了域名验证,即“服务器证书上的域名和请求域名是否匹配”。如果你的一个证书需要用来连接不同域名的主机,或者你直接用 IP 地址去连接,那么你可以重设验证策略以忽略域名验证:

    三、系统本地证书链的修改与维护

    下面是设置锚点证书的做法:

    copycode.gif

     1 NSMutableArray *certificates = [NSMutableArray array];

     2 

     3 NSDate *cerData = /* 在 App Bundle 中你用来做锚点的证书数据,证书是 CER 编码的,常见扩展名有:cer, crt...*/

     4 

     5 SecCertificateRef cerRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerData);

     6 

     7 [certificates addObject:(__bridge_transfer id)cerRef];

     8 

     9 // 设置锚点证书。

    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)certificates);

    copycode.gif

    只调用 SecTrustSetAnchorCertificates () 这个函数的话,那么就只有作为参数被传入的证书作为锚点证书,连系统本身信任的 CA 证书不能作为锚点验证证书链。要想恢复系统中 CA 证书作为锚点的功能,还要再调用下面这个函数:

    1 // true false CA SecTrustSetAnchorCertificatesOnly(trust, ); 

    这样,再调用 serverTrustIsVaild() 验证证书有效性就能成功了。

    四、AFNetwork对app内嵌证书的支持:

    会自动扫描bundle中.cer的文件,并引入

    解决方法:AFNetworking是允许内嵌证书的,通过内嵌证书,AFNetworking就通过比对服务器端证书、内嵌的证书、站点域名是否一致来验证连接的服务器是否正确。由于CA证书验证是通过站点域名进行验证的,如果你的服务器后端有绑定的域名,这是最方便的。将你的服务器端证书,如果是pem格式的,用下面的命令转成cer格式

    openssl x509 -in <你的服务器证书>.pem -outform der -out server.cer

    然后将生成的server.cer文件,如果有自建ca,再加上ca的cer格式证书,引入到app的bundle里,AFNetworking在

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModeCertificate];

    或者

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModePublicKey];

    情况下,会自动扫描bundle中.cer的文件,并引入,这样就可以通过自签证书来验证服务器唯一性了。

    五、AFNetwork的证书验证模式

    AFSecurityPolicy分三种验证模式:

    AFSSLPinningModeNone

    这个模式表示不做SSL pinning,

    只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书就不会通过。

    AFSSLPinningModeCertificate

    这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。

    AFSSLPinningModePublicKey

    这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,

    只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。

    六、整体验证过程:

    所以在 iOS 中,证书是否有效的标准是:

    信任链中如果只含有有效证书并且以可信锚点(trusted anchor)结尾,那么这个证书就被认为是有效的。

    其中可信锚点指的是系统隐式信任的证书,通常是包括在系统中的 CA 根证书。不过你也可以在验证证书链时,设置自定义的证书作为可信的锚点。

    具体到使用 NSURLSession 走 HTTPS 访问网站,-URLSession:didReceiveChallenge:completionHandler: 回调中会收到一个 challenge,也就是质询,需要你提供认证信息才能完成连接。这时候可以通过 challenge.protectionSpace.authenticationMethod 取得保护空间要求我们认证的方式,如果这个值是 NSURLAuthenticationMethodServerTrust 的话,我们就可以插手 TLS 握手中“验证数字证书有效性”这一步。

    如果我们要实现这个代理方法的话,需要提供 NSURLSessionAuthChallengeDisposition(处置方式)和 NSURLCredential(资格认证)这两个参数给 completionHandler 这个 block:

    七、系统默认实现

    系统的默认实现(也即代理不实现这个方法)是验证这个信任链,结果是有效的话则根据 serverTrust 创建 credential 用于同服务端确立 SSL 连接。否则会得到 “The certificate for this server is invalid...” 这样的错误而无法访问。

    八、双向认证:

    NSURLCredential

    NSURLCredential代表的是一个身份验证证书。URL Loading系统支持3种类型的证书:password-based user credentials, certificate-based user credentials, and certificate-based server credentials。

    参考文献:

    https://www.cnblogs.com/oc-bowen/p/5896041.html

  • 相关阅读:
    SpringMvc 框架
    面试:你最大的长处和弱点分别是什么?这些长处和弱点对你在企业的业绩会有什么样的影响?
    线程、并发、并行、进程是什么,以及如何开启新的线程?
    面向对象三大特性
    一台客户端有三百个客户与三百个客户端有三百个客户对服务器施压,有什么区别?
    JavaScript 引擎
    Spring Data JPA简介 Spring Data JPA特点
    博主博客
    微信相关
    关于正则表达式
  • 原文地址:https://www.cnblogs.com/feng9exe/p/10621654.html
Copyright © 2011-2022 走看看