HTTPS总结

HTTPS定义

  1. 全称:Hypertext Transfer Protocol over Secure Socket Layer
  2. HTTP的安全版,即HTTP之下TCP之上加入SSL层,与HTTP不同的是不同的默认端口(http通常是80,https通常是443)一个加密/身份验证层
  3. HTTPS协议需要到CA申请证书,免费证书很少,需要交费
  4. HTTP的连接是无状态的;HTTPS协议包含一种类似握手协议的身份认证过程(认证是单向的/双向的)

有两种基本的加解密算法类型

  1. 对称加密:密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES等;

    • 类似传统的账号密码概念,内容是账号密码是密钥
  1. 非对称加密:密钥成对出现,且根据公钥无法推知私钥,根据私钥也无法推知公钥;加密解密使用不同密钥,公钥加密需要私钥解密,私钥加密需要公钥解密,如RSA。

    • 密文 S = A×B,S是加密后的内容,A与B分别是两个大素数(仅可被自己与1整除,如13),这样使用A加密后的结果S只能被B除尽(解开),反之同理。

有两种认证方法(单向/双向)

  1. 单向认证:一般意义的https,如浏览器访问https网站

    • 主要保证服务器是它自己所声明的正确地址
    • 客户端和服务端的内容都是通过对称密钥加密的
    • 对称密钥是由客户端产生,通过服务器派发出的公钥加密后发送给服务器
  2. 双向认证:客户端也具有一个自己的证书,如银行的U盾

    • 客户端本身具备证书,保密的是传输过程本身而不一定能保证服务器本身是安全的
    • 如常见的钓鱼网站或DNS劫持,用户访问的域名并没有指向正确的地址,所以客户端证书本身并无法确保服务器是真实的
    • 双向认证是指客户端不仅要向CA验证服务器本身的真实性,服务器在响应数据时也要验证接收方的真实性
    • 详细链接 Https detail

证书格式以及转化

证书的标准

PKCS 全称是 Public-Key Cryptography Standards 
是由 RSA 实验室与其它安全系统开发商为促进公钥密码的发展而制订的一系列标准
PKCS 目前共发布过 15 个标准。 

常见的标准:

  1. PKCS#7 Cryptographic Message Syntax Standard
  2. PKCS#10 Certification Request Standard
  3. PKCS#12 Personal Information Exchange Syntax Standard
  4. X.509是常见通用的证书格式。所有的证书都符合为Public Key Infrastructure (PKI) 制定的 ITU-T X509 国际标准。

PKCS#7 常用的后缀是: .P7B .P7C .SPC

PKCS#12 常用的后缀有: .P12 .PFX

X.509 DER 编码(ASCII)的后缀是: .DER .CER .CRT

X.509 PAM 编码(Base64)的后缀是: .PEM .CER .CRT

编码与扩展名

X.509证书是一个数字文档,具有扩展名和编码两个属性
  • .DER = DER是一种编码,扩展名有三种。以二进制存放,常见于Windows系统
  • .PEM = PEM是一种编码,扩展名也是三种,文件开始由一行"—– BEGIN …“开始。
  • .CRT = CRT常见于Linux/Unix证书。证书可以是DER编码,也可以是PEM编码。
  • .CER = CRT证书的微软型式。也可以用两种编码。
  • .KEY = 扩展名KEY用于PCSK#8的公钥和私钥。可以是两种编码。
  • 扩展名CER和CRT几乎是同义词,CRT文件和CER文件只有在使用相同编码的时候才可以通过改后缀名代替。

证书之间的转换

只有编码相同可以通过改后缀名代替,正常情况下应该通过专业的编码工具来互相转换,如OpenSSL

    "openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der"

CA签名证书与自签名证书

CA签名证书如何验证

HTTPS连接建立过程大致是:

  1. 客户端和服务端建立一个连接
  2. 服务端返回一个证书
  3. 客户端里存有各个受信任的证书机构根证书(IOS8 预装的根证书Apple Support
    )
  4. 用这些根证书对服务端返回的证书进行验证,经验证如果证书是可信任的,就生成一个pre-master secret
  5. 用这个证书的公钥加密后发送给服务端,服务端用私钥解密后得到pre-master secret
  6. 再根据某种算法生成master secret
  7. 客户端也同样根据这种算法从pre-master secret生成master secret
  8. 随后双方的通信都用这个master secret对传输数据进行加密解密。

自签名的证书通过SSL Pinning使用

  1. 为什么要用SSL Pinning?

如果服务端的证书是从受信任的的CA机构颁发的,验证是没问题的,但CA机构颁发证书比较昂贵,小企业或个人用户 可能会选择自己颁发证书,这样就无法通过系统受信任的CA机构列表验证这个证书的真伪了,所以需要SSL Pinning这样的方式去验证。

  1. 什么是SSL Pinning?

可以理解为证书绑定,是指客户端直接保存服务端的证书(存入Xcode工程),建立https连接时直接对比服务端返回的和客户端保存的两个证书是否一样,一样就表明证书是真的,不再去系统的信任证书机构里寻找验证。

这适用于非浏览器应用,因为浏览器跟很多未知服务端打交道,无法把每个服务端的证书都保存到本地,但CS架构的手机APP事先已经知道要进行通信的服务端,可以直接在客户端保存这个服务端的证书用于校验。

  1. 为什么直接对比就能保证证书没问题?

如果中间人从客户端取出证书,再伪装成服务端跟其他客户端通信,它发送给客户端的这个证书不就能通过验证吗?
确实可以通过验证,但后续的流程走不下去,因为下一步客户端会用证书里的公钥加密,中间人没有这个证书的私钥就解不出内容,也就截获不到数据,这个证书的私钥只有真正的服务端有,中间人伪造证书主要伪造的是公钥。

如何使用AFNetworking发送HTTPS请求

建立自己的安全策略(Security Policy)

AFSecurityPolicy分三种验证模式:

  • AFSSLPinningModeNone

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

  • AFSSLPinningModeCertificate

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

这里还没弄明白第一步的验证是怎么进行的,代码上跟去系统信任机构列表里验证一样调用了SecTrustEvaluate,只是这里的列表换成了客户端保存的那些证书列表。若要验证这个,是否应该把服务端证书的颁发机构根证书也放到客户端里?

  • AFSSLPinningModePublicKey

这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。

整个AFSecurityPolicy就是实现这这几种验证方式,剩下的就是实现细节了,详见源码。

示例代码

- (void)testClientCertificate {
NSString *url = @"https://218.244.131.231/ManicureShop/api/order/pay/%@";
NSDictionary *dic = @{@"request" : @{
                        @"orderNo" : @"1409282102222110030643",
                        @"type" : @(2)
                        }
                    };

NSData *postData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
//stringWithFormat 自定义文字混淆函数
NSString *sign = [self signWithSignKey:@"test" params:dic];
NSMutableData *body = [postData mutableCopy];
NSLog(@"%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
 url = [NSString stringWithFormat:url, sign];

//设置可以解析的文本
//code =1016错误因为这里
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json", @"text/plain",@"text/html"]];
//自定义安全策略
manager.securityPolicy = [self customSecurityPolicy];

[manager POST:url parameters:dic success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

NSLog(@"Error: %@", error);
}];
}

//某种和服务器约定的混淆方式 默认使用不混淆
-(id) signWithSingleKey:(NSString *)inString params:    (NSDictionary *)inDictionnary {

return inString;
}

//AFNetworking的自定义安全措施
-(AFSecurityPolicy *) customSecurityPolicy {
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"工程根目录中证书的名字" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
//初始化时使用证书绑定加密  也可以使用公钥绑定加密 可选有3种模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
//允许使用非CA签名的证书
//这里有个问题,如果使用的是IP测试模式 不通过DNS 需要去AFNet的安全.m文件里注销掉验证域名的代码 code=1012因为这里
[securityPolicy setAllowInvalidCertificates:YES];
[securityPolicy setPinnedCertificates:@[certData]];


return securityPolicy;
}

注销域名验证

前面说过,验证站点证书,是通过域名的,如果服务器端站点没有绑定域名(万恶的备案),仅靠IP地址上面的方法是绝对不行的。
需要修改AFNetworking2的源代码!打开AFSecurityPolicy.m文件,找到方法:

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain

将下面这部分注释掉

//            SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
//
//            if (!AFServerTrustIsValid(serverTrust)) {
//                return NO;
//            }
//
//            if (!self.validatesCertificateChain) {
//                return YES;
//            }

这样,AFSecurityPolicy就只会比对服务器证书和内嵌证书是否一致,不会再验证证书是否和站点域名一致了。

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

推荐阅读更多精彩内容