ios认证书_ios 证书信任设置

ios认证书_ios 证书信任设置调用NSURLConnection实现HTTPS访问时,如果服务器证书是由CA机构颁发的(全球可信的机构,如verisign),连接方式和HTTP并没有区别。但是如果证书不是合法机构颁发的就需要定制证书验证过程。本文从记录了部分对于该过程的研究。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

0x00 问题引出


   调用NSURLConnection实现HTTPS访问时,如果服务器证书是由CA机构颁发的(全球可信的机构,如verisign),连接方式和HTTP并没有区别。代码如下:

 

      
NSString *urlStr = @"https://yourURL";
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    系统会帮你建立TLS连接,验证服务器证书(包含是否过期,证书和访问域名是否一致,证书是否为合法机构颁发等),交换对称加密密钥等,几乎不用自己写任何代码。

 

 

0x01 ATS

    但是iOS9有一个新特性ATS(App Transport Security),需要我们注意一下,在测试访问百度时发现报错:

    NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)


    错误代码定义详解见文件<Security/SecureTranspot.h>,所有相关的错误代码都定义在这个头文件里面。查阅后发现-9802描述为Fatal alert。常见的还有:-9843(域名和证书不符),-9814(证书链中有过期证书)等。

 

    同样的代码在iOS9以前的系统上就不存在问题,这是因为在iOS9之后,ATS默认打开,然后它要求所有网络请求都为HTTPS,且支持TLS V1.2,对加密方式和证书的签名算法强度均有要求(详情见,iOS  App Transport Security研究)。官方文档是这样描述的:

Certificates must be signed with one of the following types of keys:

  • Secure Hash Algorithm 2 (SHA-2) key with a digest length of at least 256 (that is, SHA-256 or greater)
  • Elliptic-Curve Cryptography (ECC) key with a size of at least 256 bits
  • Rivest-Shamir-Adleman (RSA) key with a length of at least 2048 bits
    An invalid certificate results in a hard failure and no connection.

 

    也就是说不满足条件的证书,ATS都会拒绝连接,百度证书如下图。由于它采用的sha1,不满足要求,因此会报错。

计算机生成了可选文字:40 a6 35 7e 83 67 do Ib sha1RSA shal VeriSign 3 Secure 2015F5Ê27E 2015*12Ê29E •.baidu.com. service oper.„

 ios认证书_ios 证书信任设置


    在info.plist文件中加入以下代码,可以关闭ATS,就不会报错了。

 

      
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
 

ios认证书_ios 证书信任设置


    需要注意的是加入以上代码之后会完全关闭ATS,也就是说iOS系统不再检查你的TLS连接的安全性。如果还是需要保留此特性,可以设置NSExceptionDomains属性,指定某个域名,ATS不进行安全检查。按照如下配置也可以通过,可以更加细粒度的管理(详情见,iOS  App Transport Security研究)。

计算机生成了可选文字:App Transport Security Settings 'Exception Domains baidu.com NS ExceptionRequiresForwardSecrecy NS ExceptionAIIowsIn secureHTTPLoads NS IncludesSubdomains Dictionary Dictionary Dictionary Boolean Boolean Boolean (1 item) (1 item) (3 items) YES

 ios认证书_ios 证书信任设置


0x02 自定义证书验证


    为了更深入的了解证书验证过程,动手自定义证书验证过程,如果证书不是向可信CA机构购买的,而是自己做的证书(比如12306,顺便吐槽一下,最近帮同事买票,验证码真心醉了。。。言归正传,正如12306官网所说,为保障您顺畅购票,请下载安装根证书),就必须订制证书验证过程。订制证书验证过程需要实现协议NSURLConnectionDelegate,并实现其中的方法willSendRequestForAuthenticationChallenge,与之相关的还有canAuthenticateAgainstProtectionSpacedidReceiveAuthenticationChallenge,但是如果实现了willSendRequestForAuthenticationChallenge系统就不会调用后两个方法了,本例调用的前者。上代码:

 

      
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
// 1.判断本次鉴别挑战的类型,NSURLAuthenticationMethodServerTrust是验证服务器身份
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// 判断如果失败次数大于5次,则不再验证。直接返回失败。
if(challenge.previousFailureCount < 5) {
// 获取信任管理对象,里面包含了待验证的证书,和自定义的策略
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
// 2.保存验证结果
SecTrustResultType result;
// 注意:该方法是验证证书的关键方法,该方法可能会从网络获取证书,因此不能放在主线程。
// 也可以调用它的异步方法SecTrustEvaluateAsync
SecTrustEvaluate(self.serverTrust, &result);
 
if(result == kSecTrustResultProceed ||
result == kSecTrustResultUnspecified
) {
// 3.以下两种方法调用两个都可以,调用一个就可以了
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
// [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
} else if (result == kSecTrustResultRecoverableTrustFailure) {
// 域名和证书中的不匹配,或者证书过期等
// 中断本次连接
[challenge.sender cancelAuthenticationChallenge:challenge];
[connection cancel];
}
else {
// 域名和证书中的不匹配,或者证书过期等
// 中断本次连接
[challenge.sender cancelAuthenticationChallenge:challenge];
[connection cancel];
}
}
}
}

接下来深入介绍一下整个过程:

 

1.NSURLAuthenticationChallenge


    NSURLAuthenticationChallenge是一个认证挑战类,服务器向客户端发起挑战,要求客户端提供一个挑战凭证NSURLCredential(用户名密码、客户端证书等信息)来接受挑战。如函数:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]就是用SecTrustRef类创建一个挑战凭证。NSURLAuthenticationChallenge中的protectionSpace中保存了挑战相关的信息(如服务器提供的证书,主机名,端口号,协议等),由于willSendRequestForAuthenticationChallenge回调时不止HTTPS服务器身份鉴别,如BasicDigestHTML Form等方式的身份鉴别也会调用该方法,我们关注的是HTTPS证书验证,因此首先判断一下身份鉴别的类型。通过challenge.protectionSpace.authenticationMethod可以获取,可能获取到以下值:

NSURLAuthenticationMethodDefault // 使用默认的身份鉴别方法,默认为Basic方式
NSURLAuthenticationMethodHTTPBasic // 同上
NSURLAuthenticationMethodHTTPDigest // 使用Digest鉴别方式
NSURLAuthenticationMethodHTMLForm // HTML表单方式
NSURLAuthenticationMethodNegotiate
NSURLAuthenticationMethodNTLM
NSURLAuthenticationMethodClientCertificate // 用客户端提供的证书来完成身份鉴别
NSURLAuthenticationMethodServerTrust // 验证服务器证书,该方法主要用于SLLTLS连接的建立。


2.SecTrustEvaluate

函数定义:
OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType * __nullable result)
 
返回值:
OSStatus     定义在SecBase.h0是无错误。


参数:
Trust           信任管理对象,里面包含了待验证的证书,和自定义的策略。
Result          验证结果,有以下情况:

  • kSecTrustResultUnspecified 证书验证成功,但是用户没有明确指出信任此证书。这是最常见的返回值。
  • kSecTrustResultProceed 用户选择信任此证书。
  • kSecTrustResultDeny 用户选择不信任次证书。
  • kSecTrustResultRecoverableTrustFailure 证书不可信,但是经过较小的改动可以修复问题,例如忽略过期证书、增加信任链节点等。在iOS中通常会拒绝该证书,但是收到信息时证书未过期可以通过验证,因此可以验证证书在收到信息时是否过期。
  • kSecTrustResultConfirm 用户预先选择了证书链中得某一个证书在每次使用前询问允许。这个返回值已经不再使用,只在老版本的OS X中使用。

 
    该函数评估证书的有效性用于在数字签名、建立SSL连接等情况。在调用函数前,可以调用SecTrustSetVerifyDate来设置用于验证证书的时间,默认是当前的时间。如果证书是自定义的,则需要在调用SecTrustEvaluate之前,自己构造证书链等信息。
   
    如果信任管理对象(trust management object)中缺少验证页证书的上一级证书,它会在以下位置搜索证书:

    1.调用者自定义的证书链(SecTrustSetKeychains
    2.通过SecTrustSetAnchorCertificates设置的证书
    3.系统的证书链
    4.从网络获取

    注意:
该函数在调用时可能涉及到网络请求,因此不能在主线程调用,可以调用它的异步方法SecTrustEvaluateAsync

 


3.响应挑战


   
 证书验证完成后,会根据验证结果响应服务器挑战,响应挑战必须调用NSURLAuthenticationChallenge里的sender发送NSURLAuthenTicationChallengeSender定义了身份鉴别用的sender必须实现的协议,不同的方法提供不同的响应方式。注意,在调用其中一种响应方式后,之后再调用无效,同时,willSendRequestForAuthenticationChallenge
里必须调用一种响应挑战的方式。协议里定义的方法如下:

 

    
    
    
// 取消挑战。如果证书验证不通过,调用该方法终止本次认证。
- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
// 响应挑战。如果是服务器和客户端的单向验证,服务器不需要验证客户端的证书,因此调用该方法即可。
-(void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *) challenge
// 用凭证响应挑战。如果是双向验证,不仅客户端要验证服务器身份,服务器也需要客户端提供证书,因此需要提供凭证
-(void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

0x03 总结:


   由于公司云端使用的HTTPS,与之通信时要使用HTTPS协议,于是开始研究相关的内容,发现网上相关的资料太少,自己动手做了很多实验,查阅了很多文档终于把问题梳理清楚,还有很多疏漏或者错误的地方,欢迎大家指正。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189184.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python和java哪个更值得学_java和python「建议收藏」

    python和java哪个更值得学_java和python「建议收藏」从去年到现在IA人工智能热度一直都是上升,而且很多有经验的程序员也打出“2018年不学习Python还能学习哪种编程语言“的口号,可对于初学者来说,Python相对比较简单。Python的语法类似于伪

    2022年7月5日
    23
  • freeswitch呼叫中心开发

    freeswitch呼叫中心开发开发freeswitch呼叫中心1、配置ivr2、启用mod_callcenter3、开发websocker接口,通过esl接口,发送callcenter_config命令给fs4、开发客户端页面,注册,注销,就绪,置忙等接口5、开发来电弹屏,通过客户端读取redis参数实现freeswitch的呼叫中心模块很方便的就可以让用户体验这种呼叫中心模式,包含了很多功能,具体参数的配置在使用中自行摸索。编译安装freeswitch时需要开启mod_callcenter、mod_fifo的编译,之

    2022年7月12日
    14
  • MySQL数据库:锁机制

    MySQL数据库:锁机制

    2021年4月9日
    103
  • 有刷/无刷动力电调与马达知识

    有刷/无刷动力电调与马达知识模型车需要行驶,就跟真车一样,需要一套动力单元,也有分电动和油动,至于混合动力这个估计就不需要奢望了,对于车模这么小的空间来说是不现实的,而且模型车也不需要考虑燃油经济性的问题。本文则重点介绍电动模型的动力单元。电动模型的动力,主要是指2个元件:第一就是带动车架行驶的电机(Motor),也称马达/摩打等。第二就是控制电机转速的调速器(SpeedController),很久之前早期的调速器…

    2022年5月27日
    592
  • oracle查看表字段类型_oracle更改表字段类型

    oracle查看表字段类型_oracle更改表字段类型查看oracle中的表的字段类型的sql:selectCOLUMN_NAME,DATE_TYPE,DATA_LENGTH,DATA_PRECISIONfromall_tab_columns

    2022年9月4日
    3
  • ue4在c盘的缓存_怎么清除ps在C盘的缓存

    ue4在c盘的缓存_怎么清除ps在C盘的缓存大家好,可能很多新手使用UE4的时候会发现C盘越来越小了,那是因为UE4引擎的缓存文件默认保存在C盘的缘故。下面来告诉大家怎么解决这个问题。概述一、出现的问题:UE4的缓存文件会导致C盘膨胀!二、解决的方式:请严格按照下列步骤来执行1.更改UE4的缓存路径2.删除UE4在C盘的缓存3.删除各个引擎版本SwarmAgent(联机构建)的缓存文件…

    2022年10月5日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号