1.HTTPS传输流程

2.常用加密算法

3.AFN证书校验策略及核心方法

4.SSL Pinning

5.CA证书申请流程


HTTPS经由超文本传输协议进行通信,但利用SSL/TLS来对数据包进行加密。HTTPS开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性

1.HTTPS传输流程

 
HTTPS传输流程.png

由于不相信服务器生成的随机数,所以需要客户端生成pre-master-securet,然后再由服务端加密,最后得到master-securet(主密钥),建立密道通信。(减少被猜中的可能)

2.常用加密算法

非对称加密算法:RSA,DSA/DSS
对称加密算法:AES,RC4,3DES
HASH算法:MD5,SHA1,SHA256

非对称加密算法用于握手过程中的加密生成的密码,
对称加密算法用于对真正传输的数据进行加密,
HASH算法用于验证数据的完整性,是否被篡改等

非对称加密生成密码是整个加密过程的关键,非对称加密会生成公钥和私钥,
公钥负责数据加密,(可以随意传输)
私钥负责解密,(重中之重)

3.AFN证书校验策略及核心方法

NSURLSession 封装了HTTPS链接的建立加密解密功能,但并没有验证证书的合法性,无法避免中间人攻击,要真正的安全通讯,需要我们手动去验证证书,

客户端校验策略

 sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];  

 * AFSSLPinningModeNone 不做SSL pinning 只信任证书颁发机构证书,自己生成证书不通过
* AFSSLPinningModeCertificate 客户端保存证书拷贝 第一步验证证书的域名/有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。
* AFSSLPinningModePublicKey 客户端保存证书拷贝 只是验证时只验证证书里的公钥,不验证证书的有效期等信息

核心证书校验方法

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
forDomain:(NSString *)domain
{ **** AFSSLPinningModeNone 不做SSL Pinning 当需要使用证书验证域名时,需要使用AFSSLPinningModePublicKey或AFSSLPinningModeCertificate if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { // According to the docs, you should only trust your provided certs for evaluation.
Pinned certificates are added to the trust. Without pinned certificates,
there is nothing to evaluate against. From Apple Docs:
"Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).
Instead, add your own (self-signed) CA certificate to the list of trusted anchors."
NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning.");
return NO;
} NSMutableArray *policies = [NSMutableArray array];
**** 需要验证域名时,添加一个域名验证策略
if (self.validatesDomainName) {
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
} else {
[policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
}
**** 设置验证策略
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); if (self.SSLPinningMode == AFSSLPinningModeNone) {
**** AFSSLPinningModeNone 时,allowInvalidCertificates为YES ,则代表服务器任何证书都能验证
**** 如果是NO,则需要判断此服务器是否是系统信任证书 return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);
} else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { **** 如果服务器证书不是系统信任证书,且不允许不信任证书通过验证则返回NO
return NO;
} switch (self.SSLPinningMode) {
case AFSSLPinningModeNone:
default:
return NO;
case AFSSLPinningModeCertificate: { **** AFSSLPinningModeCertificate 是直接将本地证书设置为信任的根证书,然后来进行判断,并且比较本地证书内容和服务器证书内容是否一致,如果有一个相同则返回YES NSMutableArray *pinnedCertificates = [NSMutableArray array];
for (NSData *certificateData in self.pinnedCertificates) {
[pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
} **** 设置本地证书为根证书
SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); **** 通过本地证书来判断服务器证书是否可信,不可信则不通过
if (!AFServerTrustIsValid(serverTrust)) {
return NO;
} // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA)
NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
**** 判断本地证书和服务器证书是否相同
for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
return YES;
}
} return NO;
}
case AFSSLPinningModePublicKey: {
NSUInteger trustedPublicKeyCount = 0;
NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
**** AFSSLPinningModePublicKey 是通过比较证书中公钥部分来进行校验。通过SecTrustCopyPublicKey方法获取本地证书和服务器证书,进行比较,如果有一个相同则验证通过 for (id trustChainPublicKey in publicKeys) {
for (id pinnedPublicKey in self.pinnedPublicKeys) {
if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
trustedPublicKeyCount += 1;
}
}
}
return trustedPublicKeyCount > 0;
}
}
return NO;
}

4.SSL Pinning

SSL Pinning
SSL Pinning 即证书绑定,客户端直接保存服务端证书,建立HTTPS连接时会校验服务端返回证书和客户端证书是否一致,一致则不再去信任证书机构里验证。

SSL Pinning 为什么安全

其实如果中间人从客户端取出证书(公钥),并使用证书冒充服务器与客户端进行通信时,也可以通过证书验证,但后续流程走不下去,因为客户端会用公钥加密,中间人从客户端截取的证书是公钥,缺少对应私钥即使截获了信息也无法解密。所以能够最大程度保护信息安全

PS: 从上面的通信过程中,最重要的是存储在服务器的私钥。因为只有私钥生成了在通信过程中传递的证书(公钥),且只有通过私钥才能对公钥加密的信息进行解密,所以在开发过程中保护好私钥的安全。

什么时候使用SSL Pinning

如果证书是从受信任的CA机构颁布的,验证是没有问题的,如果是自己颁发证书,无法通过系统受信任的CA机构列表验证证书时,需要通过SSL Pinnig的方式来验证

如何使用SSL Pinning

1.将.cer 证书放进工程中
2.设置securityPolicy证书校验策略

 #pragma mark - SecurityPolicy
+ (void)securityPolicy:(AFHTTPSessionManager *)sessionManager{ sessionManager.securityPolicy = [AFSecurityPolicy defaultPolicy];
sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
/** allowInvalidCertificates 是否允许不信任的证书(证书无效、证书时间过期)通过验证 ,默认为NO */
[sessionManager.securityPolicy setAllowInvalidCertificates:NO]; /** validatesDomainName 是否验证域名证书的CN(common name)字段 默认YES*/
sessionManager.securityPolicy.validatesDomainName = YES; /** NSSet<NSData*> *pinnedCertificates 根据验证模式来返回用于验证服务器的证书。*/
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"XXXX" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
[sessionManager.securityPolicy setPinnedCertificates:[NSSet setWithArray:@[certData]]]; }
iOS设备已有哪些CA证书

每个版本的iOS设备中,都会包含一些既有的CA根证书。如果接收到的证书是iOS信任的CA根证书签名的,那么则为合法证书;否则则为“非法”证书
iOS已有的CA根证书:https://support.apple.com/en-us/HT204132


作者:StarkShen
链接:http://www.jianshu.com/p/309d5359d5cb
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

iOS安全策略之HTTPS的更多相关文章

  1. ios 中使用https的知识

    先看文章,这篇文章说的是使用AFNetworing进行https时的事项,十分好!http://blog.cnbang.net/tech/2416/ ios中使用https,主要就是使用NSURLCr ...

  2. IOS 采用https 协议访问接口

    申请好证书后,发现ios 仍无法使用https协议访问到数据,发现ios 需要ssl 支持 TLS1.2 . 更改nginx 配置: ssl_protocols TLSv1 TLSv1. TLSv1. ...

  3. 微信H5页面嵌入百度地图---解决手机的webKit定位,ios系统对非https网站不提供支持问题

    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=yGQt ...

  4. iOS app 支持HTTPS iOS开发者相关

    2016年12月21日更新开发者中心链接https://developer.apple.com/news/?id=12212016b该链接是苹果昨天刚在官网给的正式回复 如下: App Transpo ...

  5. Charles抓包(iOS的http/https请求)

    Charles抓包(iOS的http/https请求) Charles安装 HTTP抓包 HTTPS抓包 1. Charles安装 官网下载安装Charles:https://www.charlesp ...

  6. iOS + Nodejs SSL/Https双向认证

    移动互联网的大力发展,安全越来越重要. 什么是双向认证呢?双向认证就是client要验证server的合法性,同一时候server也要验证client的合法性. 这样两方都相互验证,提高安全性. 关于 ...

  7. 使用Fiddler 对ios 设备进行HTTPS 的抓取

    http://blog.csdn.net/skylin19840101/article/details/43485911  使用Fiddler 对ios 设备进行HTTPS 的抓取

  8. iOS ASIHTTPRequest用https协议加密请求

    iOS 终端请求服务端数据时,为了保证数据安全,我们一般会使用https协议加密,而对于iOS的网络编程,我们一般会使用开源框架:ASIHTTPRequest,但是如果使用传统的http方式,即使忽略 ...

  9. iOS ASIHTTPRequest 请求https

    iOS 终端请求服务端数据时,为了保证数据安全,我们一般会使用https协议加密,而对于iOS的网络编程,我们一般会使用开源框架:ASIHTTPRequest,但是如果使用传统的http方式,即使忽略 ...

随机推荐

  1. ZOJ 3199 Longest Repeated Substring

    Longest Repeated Substring Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on Z ...

  2. E - Period

    For each prefix of a given string S with N characters (each character has an ASCII code between 97 a ...

  3. ORACLE11G设置IP訪问限制

    出于数据安全考虑,对oracle数据库的IP做一些限制,仅仅有固定的IP才干訪问. 改动$JAVA_HOME/NETWORK/ADMIN/sqlnet.ora文件 添加下面内容(红色表示凝视): #开 ...

  4. Atom编辑器折腾记_(15)JS代码片段补全(插件:javascript-snippets)

    题外话 这款插件就比較重量级了-.用熟悉了写原生JS的效率要提升非常多--并且,不仅支持JS还包括了nodejs snippet javascript-snippets 插件作者: zenorocha ...

  5. python (001)----列表

    Python 的列表数据类型包含更多的方法.这里是所有的列表对象方法: list.append(x) 把一个元素添加到列表的结尾,相当于 a[len(a):] = [x]. ""& ...

  6. luogu3119 草鉴定

    题目大意 给出一个有向图,问将图中的哪一个边翻转,会使节点1所在的强连通分量内的节点数最多.输出这个节点数. 题解 让我们看看暴力怎么做,即枚举每一条边,将其翻转,然后求节点1所在强连通分量节点数,然 ...

  7. luogu3358 最长k可重区间集问题 网络流

    题目大意: 关键词:最小费用最大流 不相交路径 如果两个线段重叠了,那我们则把一个线段放在下一层,另一个线段放在上一层.把流量为1的流看作一条线,一条线把位于同一层的线段(互不重叠)都串了起来.最多有 ...

  8. C# SuperWebSocket服务端学习(二)

    首先需要下载DLL类库  地址详见:http://download.csdn.NET/detail/u011269801/9590935 1,打开VS2012,新建一个控制台应用程序,选择.NET4. ...

  9. maven变量

    一.pom文件,maven内置变量 ${basedir} 项目根目录 ${project.build.directory} 构建目录,缺省为target ${project.build.outputD ...

  10. awk查找特定字段

    在一行中,查找字段包含exe的: ###########awk.awk######## { for(i=1;i<NF;i++) { if($i ~ /exe/) { print $i } } } ...