iOS深入理解Https的单向认证

SRAM MWA.png

一直知道客户端这边第三步:需要校验服务端的证书.但是需要怎么校验.使用AFN怎么设置使用呢?

先看看AFN配置证书相关的代码:

    NSData *cerData = [[NSData alloc] initWithBase64EncodedString:[self getSSLCertificates] options:0];
    AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    policy.allowInvalidCertificates = YES;
    policy.validatesDomainName = YES;
    policy.pinnedCertificates = [NSSet setWithArray:@[cerData]];
    return policy;

我们可以看到是有一个加载证书的过程.并且有一个mode类型,这里使用的是:AFSSLPinningModeCertificate.我们先了解一下AFN提供的三种类型:

除了去系统信任 CA 机构列表验证的 AFSSLPinningModeNone 模式,AFNetworking 还提供了 SSL Pinning 方式的验证。
SSL Pinning 方式(AFSSLPinningModeCertificate,AFSSLPinningModePublicKey)把服务端下发的证书预先打包到 APP 的 bundle 中,然后通过比较服务端下发的证书和本地证书是否相同来校验证书。
使用该方式的原因是CA机构颁发的证书比较昂贵,一些企业或者个人不申请CA颁发的证书,而是自己手动创建证书。用 SSL Pinning 的方式只要比较证书内容一样,无需验证证书的权威性。

  • AFSSLPinningModeNone这个模式表示不做 SSL pinning,只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书(链)。 若证书是信任机构签发的就会通过;若是自己服务器生成的证书,这里是不会通过的。
    AFSSLPinningModeCertificate这个模式表示用证书绑定方式验证证书,需要客户端保存服务端的证书拷贝。 适用于非浏览器应用,因为浏览器跟很多未知服务端打交道,无法把每个服务端的证书都保存到本地。但CS架构的APP应用一般事先知道要进行通信的服务端(例如 QQ 文件后台服务器:.ftn.qq.com),可以直接在客户端保存这些固定服务端的证书用于校验。 验证分两步:第一步验证证书的域名/有效期等信息;第二步是对比服务端返回的证书跟客户端返回的是否一致。 从代码上看,和去系统信任机构列表里验证一样调用 SecTrustEvaluate,只是这里的列表换成了客户端预先保存的证书列表(链)。
  • AFSSLPinningModePublicKey 这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,只是验证时只验证证书里的公钥,不验证证书的有效期等信息。 只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。
AFNetworking单向认证.png

针对AFSecurityPolicyallowInvalidCertificates属性怎么理解呢?
意思是:是否允许非CA机构证书(也就是自建的证书),默认为NO.如果是自建非CA机构证书则需要设置为YES

针对AFSecurityPolicyvalidatesDomainName属性怎么理解呢?

说一下我们一般自建证书时都有一个域名需要注册:
[alt_names]
DNS.1 = flymote.com
DNS.2 = *.flymote.com
DNS.3 = www.flymot.com
DNS.4 = *.flymot.com
IP.1 = 192.168.0.198
实际上不填写也是可以获取证书的.但一般为了保障通信的安全性.防止中间人攻击

中间人攻击.png

因为我们可以从CA获取证明.别人也可以通过CA获取证书.
那么只做证书是否是CA证书机构发布显然不那么安全.所以还需要验证一下域名和颁发机构
validatesDomainName的意思是:是否需要验证域名.域名与证书的是否一致

到这里才对单向认证的第三步:客户端对服务器证书是否合法有所理解!

实践出真理.下面我们做一下验证,帮助理解:

单向认证:
CA证书:https://nemo.zhulongan.com/1.txt
自生成证书:https://nemo.zhulongan.com:8001/1.txt

代码:

AFSecurityPolicy* policy          = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
policy.allowInvalidCertificates   = NO;
policy.validatesDomainName        = YES;
return policy;

结果:

————————————CA的请求成功———————————
调用接口(requestKey=10000)成功,
请求Domain:https://nemo.zhulongan.com/1.txt,返回结果如下:{length = 32, bytes = 0x68656c6c 6f776f72 6c642073 656e6c64 ... 302d3132 2d30390a }

————————————自建的请求失败———————————
https://nemo.zhulongan.com:8001/1.txt,错误信息如下:Error Domain=NSURLErrorDomain Code=-999 "已取消" UserInfo={NSErrorFailingURLStringKey=https://nemo.zhulongan.com:8001/1.txt?_deviceId=4C76CC95-E4C0-49B3-98B9-E78F8E39B7D3&_channel_id=32&_client_version_no=1.0.6, NSErrorFailingURLKey=https://nemo.zhulongan.com:8001/1.txt?_deviceId=4C76CC95-E4C0-49B3-98B9-E78F8E39B7D3&_channel_id=32&_client_version_no=1.0.6, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <35BF7B1D-A6B5-4938-B2E6-9DD25E2BDD99>.<1>"), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <35BF7B1D-A6B5-4938-B2E6-9DD25E2BDD99>.<1>, NSLocalizedDescription=已取消}

自建证书保存到本地
代码:

    NSData *cerData = [[NSData alloc] initWithBase64EncodedString:[self getSSLCertificates] options:0];
    AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    policy.allowInvalidCertificates = YES;
    policy.validatesDomainName = NO;
    policy.pinnedCertificates = [NSSet setWithArray:@[cerData]];
    return policy;

结果:

————————————CA的请求失败———————————
调用接口(requestKey=10000)失败,
请求Domain:https://nemo.zhulongan.com/1.txt,错误信息如下:Error Domain=NSURLErrorDomain Code=-999 "已取消" UserInfo={NSErrorFailingURLStringKey=https://nemo.zhulongan.com/1.txt?_deviceId=4C76CC95-E4C0-49B3-98B9-E78F8E39B7D3&_channel_id=32&_client_version_no=1.0.6, NSErrorFailingURLKey=https://nemo.zhulongan.com/1.txt?_deviceId=4C76CC95-E4C0-49B3-98B9-E78F8E39B7D3&_channel_id=32&_client_version_no=1.0.6, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <7C39B89E-6948-4210-A95C-1DEABF71241D>.<1>"), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7C39B89E-6948-4210-A95C-1DEABF71241D>.<1>, NSLocalizedDescription=已取消}

————————————自建的请求成功———————————
调用接口(requestKey=10001)成功,
请求Domain:
https://nemo.zhulongan.com:8001/1.txt,
返回结果如下:{length = 32, bytes = 0x68656c6c 6f776f72 6c642073 656e6c64 ... 302d3132 2d30390a }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容