1. HTTPS协议基础:HTTP与HTTPS的区别、SSL/TLS握手过程、数字证书与CA体系

大家好,我是你们这堂课的主讲。咱们今天聊点实在的——HTTPS。很多做移动开发的朋友,天天跟它打交道,但真要问起「HTTPS到底比HTTP强在哪?」,能说清楚的人其实不多。我当年刚入行时也吃过这个亏,有一次给客户演示App,结果抓包工具一开,所有请求明文暴露,那叫一个尴尬。从那以后,我就把HTTPS的底裤给扒了个干净。

好,咱们正式开始。

1.1 HTTP与HTTPS:一个天一个地

先问个问题:HTTP和HTTPS,本质上差在哪?

说白了,HTTP就是裸奔。你发出去的数据,就像在大街上喊话,谁都能听见。而HTTPS呢,相当于你俩之间拉了个加密的帘子,外面的人只能看到帘子在动,但不知道里面在干啥。

核心区别一览:

对比项 HTTP HTTPS
传输协议 明文传输 SSL/TLS加密传输
默认端口 80 443
数据完整性 无校验,可被篡改 有消息认证码,防篡改
身份验证 数字证书验证服务器身份
性能 快(无加密开销) 稍慢(握手+加解密)
安全性

我个人习惯把HTTPS理解为「HTTP + SSL/TLS」。它不是在HTTP外面包了一层,而是在传输层和应用层之间,插了一个安全层。这个安全层负责三件事:加密、校验、认证。

小提示: 你在Android里用HttpsURLConnection或者OkHttp时,底层走的都是SSL/TLS。别以为加了https前缀就万事大吉,证书校验没做好,照样能被中间人攻击。

1.2 SSL/TLS握手过程:一场精心设计的「对暗号」

握手过程,是HTTPS最核心的部分。我当年第一次看RFC文档时,差点被绕晕。后来我画了一张图,才彻底搞明白。咱们先看图,再细讲。

客户端(App) 服务端 ① ClientHello(支持的TLS版本、密码套件) ② ServerHello + 数字证书 + 公钥 ③ 客户端验证证书,生成Pre-Master Secret(用公钥加密) ④ 服务端用私钥解密,得到Pre-Master Secret ⑤ 双方各自计算会话密钥(对称密钥) ⑥ 发送ChangeCipherSpec + Finished(加密通信开始) 握手完成后,后续所有数据使用对称加密传输(如AES)

嗯,这张图我画了好一会儿。咱们一步步拆解:

  1. ClientHello: 客户端(你的App)告诉服务器:「我支持TLS 1.3,我这里有这些密码套件,你挑一个吧。」
  2. ServerHello + 证书: 服务器回应:「好,咱们用TLS 1.3 + AES-256-GCM。这是我的数字证书,里面有我的公钥。」
  3. 证书验证 + 密钥生成: 客户端检查证书是否合法(后面细讲)。验证通过后,生成一个随机数(Pre-Master Secret),用服务器的公钥加密后发过去。
  4. 私钥解密: 服务器用自己的私钥解密,拿到Pre-Master Secret。
  5. 计算会话密钥: 双方用同样的算法,基于Pre-Master Secret计算出对称密钥。
  6. 加密通信开始: 双方互相确认:「我准备好了,咱们开始用对称密钥加密通信吧。」

注意: 我曾经在项目中遇到过一个问题——客户端和服务器的系统时间不一致,导致证书验证失败。因为证书有有效期,如果手机时间被改到了证书过期之后,握手就会失败。所以,做Android开发时,记得用NTP同步时间。

1.3 数字证书与CA体系:谁来证明「我是我」?

你想想看,如果中间人伪造了一个证书,说「我是支付宝」,客户端怎么知道它是假的?这就引出了CA(证书颁发机构)体系。

数字证书,说白了就是一张「电子身份证」。它包含以下关键信息:

  • 主体信息: 域名(比如 *.alipay.com)、组织名称
  • 公钥: 服务器的公钥
  • 颁发者: 哪个CA签发的(比如DigiCert、Let's Encrypt)
  • 有效期: 从哪天到哪天
  • 签名: CA用它的私钥对以上内容做的签名

验证流程是这样的:

  1. 客户端拿到服务器的证书后,先看颁发者是谁。
  2. 客户端本地预置了信任的CA根证书列表(Android系统里就有)。
  3. 用CA根证书里的公钥,去验证服务器证书上的签名。
  4. 如果签名验证通过,说明这个证书确实是CA签发的,不是伪造的。
  5. 再检查域名是否匹配、是否在有效期内。

关键点: 整个信任链的根,是CA根证书。如果根证书被攻破,或者你手机里被安装了恶意CA证书,那所有HTTPS连接都不安全了。这就是为什么Android 7.0+默认不信任用户安装的CA证书——就是为了防中间人攻击。

我举个例子。你在Android上做抓包时,经常需要安装Fiddler或Charles的CA证书。这个操作本质上就是「把你的手机变成信任中间人证书的状态」。一旦装了这个证书,中间人就能解密你的HTTPS流量。所以,生产环境的App,一定要做证书绑定(Certificate Pinning),防止这种攻击。

避坑指南: 我曾经见过一个App,开发时为了方便,直接信任了所有证书。结果上线后,用户只要装个抓包工具,就能看到所有接口数据。后来被安全团队通报,紧急修复。所以,千万别在正式环境里用 TrustManagercheckClientTrusted 空实现——那是给自己挖坑。

1.4 证书链与自签名证书

实际场景中,服务器证书很少直接由根CA签发,而是由中间CA签发。这样做的目的是保护根CA的私钥——根CA的私钥平时离线保存,只有中间CA的私钥在线使用。

证书链长这样:

根CA证书(自签名)
  └── 中间CA证书(由根CA签发)
        └── 服务器证书(由中间CA签发)

客户端验证时,会沿着这条链一直验证到根证书。如果链上任何一个环节的证书有问题,验证就会失败。

说到自签名证书,很多开发者在测试环境会用。自签名证书就是自己给自己签发的证书,没有CA背书。客户端默认不信任它,除非你手动把它加到信任列表里。我个人建议,测试环境可以用自签名证书,但生产环境绝对不要用——你想想看,如果连CA都不验证,那跟HTTP裸奔有什么区别?

1.5 总结一下

好了,这一章的内容就这些。咱们回顾一下:

  • HTTP是明文,HTTPS是加密的,中间加了一层SSL/TLS。
  • 握手过程就是「对暗号」——先交换公钥,再协商对称密钥。
  • 数字证书是服务器的身份证,CA体系是背后的信任机制。
  • 证书绑定是防止中间人攻击的关键手段。

下一章,咱们会深入Android端的抓包实战,包括怎么用Fiddler、Charles抓HTTPS包,以及怎么绕过证书绑定。到时候我会分享一些我在实际项目中踩过的坑,保证让你少走弯路。


公众号:蓝海资料掘金营,微信 deep3321