欢迎来真孝善网,为您提供真孝善正能量书籍故事!

深入解析iOS平台HTTPS证书链验证机制

时间:11-20 名人轶事 提交错误

大家好,今天小编来为大家解答深入解析iOS平台HTTPS证书链验证机制这个问题,很多人还不知道,现在让我们一起来看看吧!

对称加密只有一把密钥,既用于加密又用于解密;

非对称加密有公钥和私钥。只有公钥才能解密私钥加密的内容。只有私钥才能解密公钥加密的内容。

为了提高安全性,我们常用的做法是使用对称加密来加密数据。但是,如果仅使用对称加密,则在双方通信开始时密钥将始终以明文形式传输。所以密钥从一开始就已经泄露了,根本没有安全可言。因此,TLS/SSL在握手阶段结合了非对称加密,保证只有通信双方知道对称加密密钥。大致流程如下:

TSL:SSL_handshake.png

因此,HTTPS传输安全的关键是保证在TLS/SSL握手阶段只有通信双方才能得到Session Key!

数字证书的内容

X.509应该是目前比较流行的SSL数字证书标准,包括(但不限于)以下字段:

字段值说明

主题名称:用于识别数字证书的信息

Common Name:对于客户端证书,通常是对应的域名

证书颁发者(颁发者名称) 有关颁发和签署证书的实体的信息

签名算法用于签名的算法

序列号(Serial Number) 由数字证书颁发机构(CA) 赋予证书的唯一整数。数字证书有一个序列号。

之前无效(´)

(口)(—之后无效

公钥公钥

签名是通过签名算法计算出证书内容后得到的数据,用于验证证书是否被篡改。

除了上面列出的字段外,还有很多扩展字段,这里不再详述。

下图是维基百科的公钥证书:

wikipedia_cer.png

数字证书的生成和验证

数字证书的生成是分层的,下层证书需要上层证书的私钥签名。

因此,后者是前者的证书颁发者,也就是说,上级证书的Subject Name 就是其下级证书的Issuer Name。

证书颁发者从证书申请者那里获得一些必要的信息(对象名称、公钥和私钥)后,通过SHA-256哈希得到证书内容的摘要,然后用自己的私钥对摘要进行加密,得到数字证书。签名。根据现有信息,生成包含公钥和私钥的两个证书。

此时,有几个问题:

问:如果颁发数字证书必须用上级证书的私钥加密,那么顶级证书——根证书来自哪里?

根证书是自签名的,即用自己的私钥进行签名,不需要另一个证书的私钥来生成签名。

问:如何验证证书是否被篡改?

当客户端通过HTTPS访问站点时,服务器返回整个证书链。下图的证书链就是一个例子:

chain_hierarchy.png

为了验证*.wikipedia.org证书没有被篡改,我们需要使用GlobalSign组织验证CA提供的公钥-SHA256-G2解密前者的签名并获得摘要Digest1。我们的客户还计算了前一个证书的内容并获得摘要。摘要2.比较两个摘要就可以知道前者是否被篡改。后者是一样的,使用GlobalSign Root CA提供的公钥验证。当验证受信任的根证书时,可以确定证书*.wikipedia.org 是受信任的。

问:为什么上述根证书GlobalSign Root CA 受信任?

由数字证书颁发机构(Certificate Authority,CA)签名和管理的CA根证书将被包含在您的浏览器和操作系统的可信证书列表中,并且该列表将用于确定根证书是否可信。所以不要随便将奇怪的根证书导入到你的操作系统中。

问:生成的数字证书(例如*.wikipedia.org)可以用来签署新证书吗?

不确定。如下图,扩展字段中有一个名为Basic Constraints的数据结构。有一个字段叫做Path Length Constraint,它表示证书可以继续签署CA子证书的深度。这里是0,表示这个GlobalSign组织验证CA-SHA256-G2只能签署客户端证书,并且客户端证书不能用于签署新证书,只有CA子证书可以这样做。

路径长度约束.png

iOS 上的证书链验证

正确覆盖TLS 链验证中提到:

验证TLS 证书后,操作系统会验证其信任链。如果该信任链仅包含有效证书并以已知(受信任)锚证书结束,则该证书被视为有效。

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

如果信任链仅包含有效证书并以可信锚结尾,则证书被视为有效。

可信锚点是指系统隐式信任的证书,通常是系统包含的CA根证书。但是,您也可以在验证证书链时将自定义证书设置为可信锚点。

NSURLSession 实现HTTPS

具体来说,当使用NSURLSession 通过HTTPS 访问网站时,-URLSession:didReceiveChallenge:completionHandler: 回调中会收到一个质询,需要您提供身份验证信息才能完成连接。这时,我们可以使用challenge.protectionSpace.authenticationMethod来获取保护空间需要我们认证的方法。如果这个值为NSURLAuthenticationMethodServerTrust,我们就可以干预TLS握手中的“验证数字证书的有效性”步骤。

默认实现

系统默认的实现(即代理不实现该方法)就是验证这条信任链。如果结果有效,将基于serverTrust 创建凭证,以与服务器建立SSL 连接。否则,您将收到类似“该服务器的证书无效.”的错误,并且无法访问它。

比如访问https://www.google.com时,我们不实现这个方法仍然可以访问成功。系统验证Google服务器返回的从叶节点证书到根证书的证书链(有效期、签名等)。当遇到根证书时,发现它作为可信锚点存在于可信证书列表中。然后验证通过并允许建立与服务器的连接。

谷歌.png

当我们访问https://www.12306.cn时,“该服务器的证书无效”。您可能正在连接到冒充“www.12306.cn”的服务器,这可能会使您的机密信息面临风险。错误。原因是系统验证根证书时发现它是自签名且不可信的。

12306.png

定制实施

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

复制代码

1 -(void)URLSession:(NSURLSession *)会话

2 didReceiveChallenge:(NSURLAuthenticationChallenge *)挑战

3 完成处理程序:(无效(^)(NSURLSessionAuthChallengeDisposition,

4 NSURLCredential * _Nullable))completionHandler {

5

6 //如果使用默认的处理方法,凭证将被忽略

7 NSURLSessionAuthChallengeDisposition 配置=NSURLSessionAuthChallengePerformDefaultHandling;

8 NSURLCredential凭证=nil;

9

10 if ([challenge.protectionSpace.authenticationMethod]

11 等于字符串:

12 NSURLAuthenticationMethodServerTrust]){

13

14/调用自定义验证流程/

15 if ([self myCustomValidation:challenge]) {

16 凭证=[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

17 if(凭证){

18 处置=NSURLSessionAuthChallengeUseCredential;

19}

20 } 其他{

21/如果无效,则取消*/

22 处置=NSURLSessionAuthChallengeCancelAuthenticationChallenge

23 }

24 }

25 if (completionHandler) {

26 完成处理程序(处置,凭证);

27}

28}

复制代码

在[self myCustomValidation:challenge]中调用自定义验证流程。如果结果有效,将创建凭据以建立连接。

要自定义验证流程,首先需要取出一个SecTrustRef对象,它是一个执行信任链验证的抽象实体。它包含验证策略(SecPolicyRef)和一系列可信锚证书。我们能做的就是修改它。就这两件事。

1 SecTrustRef trust=challenge.protectionSpace.serverTrust;

获得信任对象后,可以使用以下函数进行验证。

复制代码

1 静态BOOL serverTrustIsVaild(SecTrustRef trust) {

2 BOOL 允许连接=NO;

3

4 //假设验证结果无效

5 SecTrustResultType trustResult=kSecTrustResultInvalid;

6

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

8 OSStatus 状态=SecTrustEvaluate(trust, trustResult);

9

10 if (雕像==noErr) {

11 //kSecTrustResultUnspecified: 系统隐式信任此证书

12 //kSecTrustResultProceed: 用户添加自己的信任锚点并明确告诉系统该证书是值得信任的。

13

14 允许连接=(trustResult==kSecTrustResultProceed

15 || trustResult==kSecTrustResultUnspecified);

16}

17返回allowConnection;

18}

复制代码

什么时候调用这个函数完全取决于你的需要。如果你不想修改验证策略直接调用,那你还在这里! ()︵

域名验证

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

1 CFArrayRef 政策参考;

2 SecTrustCopyPolicies(trust,policiesRef);

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

复制代码

1 NSMutableArray *策略=[NSMutableArray 数组];

2

3 //BasicX509不验证域名是否相同

4 SecPolicyRef 策略=SecPolicyCreateBasicX509();

5 [策略addObject:(__bridge_transfer id)策略];

6 SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);

7

8

复制代码

然后调用serverTrustIsVaild()进行验证。

但如果域名没有经过验证,安全性就会大大降低。拿一个浏览器:

想象一下,您想向https://www.real-website.com发送消息,但由于域名劫持,您被带到了https://www.real-website.cn网站。大概有以下两种结果:

如果这个假网站的证书是非CA颁发的假证书,那么浏览器会提醒你这个证书不可信;

该假冒网站还使用CA 颁发的证书。由于我们不验证域名,因此您的浏览器不会给出任何警告。

你可能会问:公钥证书是所有人都可以使用的。钓鱼网站能否将真实的公钥证书返回给我们?

我觉得可以,但是没啥用。没有私钥的网络钓鱼服务器无法获得第三个随机数,无法生成会话密钥,也无法解密我们传递给它的数据。

自签名证书链验证

为了防止App中出现上述的中间人攻击,更好的做法是将公钥证书封装到App中,然后在接收服务器证书链时,可以有效验证服务器是否是值得信赖。这对于验证自签名证书链也是必要的。

假设您的服务器返回:[您的自签名根证书] -- [您的辅助证书] -- [您的客户端证书]。系统不信任这三个证书。

所以验证时需要设置这三者之一作为锚点证书。当然,多份证书也是可以的。

例如,使用[您的辅助证书]作为锚点后,SecTrustEvaluate()函数只需验证[您的客户端证书]确实是由[您的辅助证书]签名的,则验证结果为kSecTrustResultUnspecified,表示[您的客户端]证书] 是可信的。设置锚点证书的方法如下:

复制代码

1 NSMutableArraycertificates=[NSMutableArray 数组];

2

3 NSDatecerData=/您在App Bundle 中用作锚点的证书数据。该证书采用CER 编码。常见的扩展名有:cer、crt./

4

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

6

7 [证书addObject:(__bridge_transfer id)cerRef];

8

9 //设置锚点证书。

10 SecTrustSetAnchorCertificates(信任,(__bridge CFArrayRef)证书);

复制代码

如果只调用SecTrustSetAnchorCertificates()函数,那么只有作为参数传入的证书才会被用作锚点证书,甚至系统本身信任的CA证书也无法作为锚点来验证证书链。要恢复CA证书作为系统中锚点的功能,必须再次调用以下函数:

1 //true 表示仅传入的证书用作锚点, false 允许系统CA 证书也用作锚点

2 SecTrustSetAnchorCertificatesOnly(信任,假);

这样调用serverTrustIsVaild()验证证书有效性就会成功。

CA证书链验证

上面说的是对没有经过CA认证的自签名证书的验证,CA的证书链的验证方法是一样的。不同的是,不可信锚点的证书类型不同:前者的锚点是自签名的,需要验证。打包到App中进行验证,后者的锚点可能已经存在于系统中。但我发现了这个陷阱:

如果我们使用一个CA根证书签名的数字证书,并且只用这个CA根证书作为锚点,而不验证域名,那么在握手阶段我们会信任同一个CA根证书签名的伪造证书吗?呢绒?

参考阅读

iOS安全系列一:HTTPS

iOS 安全系列2:HTTPS 高级

正确覆盖TLS 链验证

HTTPS服务器信任评估

如果有什么我理解不正确或者表达不准确的地方,请告诉我。

文/StanOz(简书作者)

原文链接:http://www.jianshu.com/p/31bcddf44b8d

版权归作者所有。转载请联系作者授权并注明“简书作者”。

其他:

公司的接口一般采用两种协议,一种是HTTP,一种是HTTPS。只要HTTP请求,服务器就会响应。如果我们不对请求和响应进行加密,所有信息都将被检测到并被劫持。这是非常不安全的。可以使用我的一套工具来处理客户端加密:文章地址

但任何时候,服务都应该放在HTTPS上,因为它可以避免中间人攻击的问题,而且还带有基于非对称密钥的加密通道!现实情况是,近年来涌现了大量即时移动开发者。这些人往往基础很差,对加密解密毫无了解。使用HTTPS后,你可以省去他们对他们进行各种加密和解密技术的教育,他们的生活会轻松很多。

介绍HTTPS交互原理

简而言之,HTTPS 是HTTP 协议加上SSL 协议的一层加密。 SSL证书符合SSL协议,由受信任的数字证书颁发机构CA(如GlobalSign、wosign)验证服务器身份后颁发。这是要花钱的。颁发的证书一般放在服务器根目录下作为公钥,方便客户端请求返回给客户端。私钥存储在服务器内部中心,用于解密公钥。

HTTPS客户端与服务器交互流程:

1、客户端发送请求,服务器返回公钥给客户端;

2、客户端生成对称加密密钥,用公钥加密,返回给服务器;

3、服务器收到后,使用私钥解锁对称加密密钥并保存;

4、后续所有交互都将使用对称加密数据。

我们来谈谈证书

简单来说,证书有两种,一种是严肃的:

CA颁发的证书

一种是不合时宜的:

自行生成并颁发证书

介绍一下我们需要做什么

如果遇到严重的证书,我们可以直接使用AFNetworking来请求。 AFNetworking帮助我们内部封装了HTTPS请求方法,但是大多数公司接口都不是正经的证书。在这种情况下,我们需要执行以下步骤:

1.将服务器的公钥证书拖入Xcode中

2.修改验证方式

manager.securityPolicy=[AFSecurityPolicy策略WithPinningMode:AFSSLPinningModePublicKey];

原则:

简单来说,您可以修改AFN 设置以允许客户端从服务器接收任何证书。但是这样做有一个问题,就是无法验证该证书是否是你服务器后端的证书,从而允许中间人攻击,即通过重路由的方式。定向路由为在服务器端分析伪造品打开了大门。

AFSecurityPolicy *securityPolicy=[AFSecurityPolicy defaultPolicy];

securityPolicy.allowInvalidCertificates=是;

解决方案:AFNetworking 允许嵌入证书。通过嵌入证书,AFNetworking通过比较服务器端证书、嵌入证书和站点域名来验证连接的服务器是否正确。由于CA证书验证是通过站点域名来验证的,所以如果你的服务器后端有绑定域名的话是最方便的。如果您的服务器端证书是pem格式,请使用以下命令将其转换为cer格式。

openssl x509 -在您的服务器证书.pem -outform der -out server.cer

然后将生成的server.cer文件引入,如果你有自建的ca,加上ca的cer格式证书,放入app的bundle中。 AF网络

AFSecurityPolicy *securityPolicy=[AFSecurityPolicy AFSSLPinningModeCertificate];

或者

AFSecurityPolicy *securityPolicy=[AFSecurityPolicy AFSSLPinningModePublicKey];

在这种情况下,将自动扫描并导入捆绑包中的.cer文件,以便可以通过自签名证书来验证服务器的唯一性。

AFSecurityPolicy具有三种验证模式:

AFSSLPinningMode无

此模式意味着不执行SSL 固定。

就像浏览器一样,它会在系统的受信任权限列表中验证服务器返回的证书。如果证书是由信任机构颁发的,它将通过。如果证书是自己的服务器生成的,就不会通过。

AFSSLPinningMode证书

该模式是指使用证书绑定来验证证书。客户端需要保存服务器证书的副本。这里的验证分为两步。第一步,验证证书的域名有效期等信息。第二步是将服务器返回的证书与客户端进行比较。终端返回的结果是否一致。

好了,文章到此结束,希望可以帮助到大家。

用户评论

别留遗憾

苹果官方一直很重视用户隐私和安全,这篇文章应该介绍了 iOS 如何确保我们访问网站时数据加密安全

    有8位网友表示赞同!

开心的笨小孩

终于可以了解一下手机端HTTPS证书是怎么运作的了,太难懂了...

    有12位网友表示赞同!

清羽墨安

我最近在学习网络安全,看到这个标题就迫不及待想看

    有16位网友表示赞同!

花海

不知道iOS的证书链验证和安卓有什么区别

    有7位网友表示赞同!

颓废i

希望这篇文章能解释清楚HTTPS协议,我一直不太明白它是怎么工作的

    有15位网友表示赞同!

丢了爱情i

如果攻击者绕过证书链认证怎么办?这篇文章会提到吗?

    有20位网友表示赞同!

怀念·最初

我很好奇 iOS 使用哪些特定的算法来验证证书

    有5位网友表示赞同!

爱到伤肺i

最近听说了一些关于网站被盗用、数据泄露的信息,了解安全知识很重要哦!

    有9位网友表示赞同!

有些人,只适合好奇~

这个话题看起来很专业,但应该很有趣

    有16位网友表示赞同!

ok绷遮不住我颓废的伤あ

看来苹果又升级了新的安全措施

    有20位网友表示赞同!

抚涟i

想了解一下如何自己手动查看 iPhone 的证书链验证过程

    有10位网友表示赞同!

葵雨

学习一下这些知识可以保护我们的手机安全

    有12位网友表示赞同!

反正是我

这篇文章能让我更好地理解 iOS 系统的安全性机制吗?

    有19位网友表示赞同!

早不爱了

希望看到一些实际案例,来展示 iOS 证书链验证的效果

    有15位网友表示赞同!

红尘烟雨

这个标题看起来很吸引人,一定要去看一看!

    有6位网友表示赞同!

十言i

也许我还能通过这次学习,编写自己的安全脚本

    有16位网友表示赞同!

↘▂_倥絔

iOS系统对安全的重视,真是太赞了!

    有9位网友表示赞同!

古巷青灯

网络安全是一个非常重要的课题,值得我们去深究

    有13位网友表示赞同!

强辩

看一看这篇文章,就能让自己更加了解手机的运作原理吗?

    有14位网友表示赞同!

遗憾最汹涌

学习一些关于系统安全的知识永远不会过分!

    有5位网友表示赞同!

【深入解析iOS平台HTTPS证书链验证机制】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活