HTTP与HTTPS的区别
如上图所示,HTTPS多了一层Security Layer。
TLS与SSL的关系
二者是一个东西,只是不同版本的叫法不同。其对应版本的枚举如下:
TLS_1_3("TLSv1.3"), // 2016.
TLS_1_2("TLSv1.2"), // 2008.
TLS_1_1("TLSv1.1"), // 2006.
TLS_1_0("TLSv1"), // 1999.
SSL_3_0("SSLv3"), // 1996.
TLS的作用
TLS的作用之一就是身份认证,authentication,被认证方需要提供一个身份证明,在HTTPS的世界里,这个身份证明就是TLS证书,或者称为HTTPS证书。
证书样例
导出证书
打开一个https的站点,可以将其tls证书导出,步骤如下:
以Chrome浏览器为例,打开站点后,点击 F12 打开调试界面,选择“Security”tab,如下:
点击“View certificate”按钮查看证书。
点击“详细信息”,点击“导出”按钮。
则可以将证书保存到本地。
查看证书
使用openssl指令将证书详情导出到文本,如下:
openssl x509 -in <证书保存路径> -text > cert.txt
证书格式
证书剖析
证书的验证
在这里的关键是获取证书所有者的公钥,对数据签名进行解密,然后与证书的内容进行比较。二者不一致,则说明证书存在被篡改的问题。
证书链
X.509除了规范证书的内容外,还规范了如何获取CRL(Certificate Revocation List,证书吊销列表)以及Certificate Chain的验证算法。
通过浏览器访问https站点时,浏览器获取到的不仅仅是证书,还有证书链信息,例如:
证书www.minigame.vip的Issuer就是它的父节点“GTS CA 1P5”。因为UserAgent(操作系统或浏览器)会内置一些权威CA颁发的根证书(Root Certificate)或中间证书(Intermedia Certificate),例如上面的“GTS CA 1P5”和“GTS Root R1”。
当获得证书链之后,我们就可以轻松地往上回溯到被UA信任的证书,虽然UA保存的可能是中间证书(Intermediate Certificate),但是如果一个End-Entity证书即使回溯到根证书(Root Certificate)也没有在UA的受信任列表里,那么这个站点就会被标记为不安全。
以上就是证书链的定义和作用。
如何防止中间人攻击
证书锁定
证书锁定(SSL/TLS pinning),顾名思义,就是将服务器提供的SSL/TLS证书,内置到移动端开发的APP客户端中。当客户端发起请求时,通过比对服务器提供的证书和内置的证书来确定是否是安全连接。
证书锁定实现
证书锁定(SSL/TLS pinning)提供了两种锁定实现:证书锁定(Certificate pinning)和公钥锁定(Public Key pinning)。
证书锁定
我们需要将APP代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书,通过这种授权方式,保障了APP与服务端通信的唯一性和安全性,因此我们移动端APP与服务端(例如API网关)之间的通信是可以保证绝对安全。
缺点:CA签发证书都存在有效期问题,所以缺点是在证书续期后需要将证书重新内置到APP中。
公钥锁定
公钥锁定则是提取证书中的公钥并内置到移动端APP中,通过与服务器对比公钥值来验证连接的合法性。
相对于证书锁定,公钥锁定的优点为:在制作证书密钥时,公钥在证书的续期前后都可以保持不变(即密钥对不变),所以可以避免证书有效期问题。
实现
- 获取移动端所需证书
如果采用证书锁定方式,则获取证书的摘要hash,以infinisign.com为例
## 在线读取服务器端.cer格式证书
openssl s\_client -connect infinisign.com:443 -showcerts < /dev/null | openssl x509 -outform DER > infinisign.der
## 提取证书的摘要hash并查看base64格式
openssl dgst -sha256 -binary infinisign.der | openssl enc -base64
wLgBEAGmLltnXbK6pzpvPMeOCTKZ0QwrWGem6DkNf6o=
所以其中的wLgBEAGmLltnXbK6pzpvPMeOCTKZ0QwrWGem6DkNf6o=就是我们将要进行证书锁定的指纹(Hash)信息。
- 获取移动端所需公钥
如果采用公钥锁定方式,则获取证书公钥的摘要hash,以infinisign.com为例
## 在线读取服务器端证书的公钥
openssl x509 -pubkey -noout -in infinisign.der -inform DER | openssl rsa -outform DER -pubin -in /dev/stdin 2>/dev/null > infinisign.pubkey
## 提取证书的摘要hash并查看base64格式
openssl dgst -sha256 -binary infinisign.pubkey | openssl enc -base64
bAExy9pPp0EnzjAlYn1bsSEGvqYi1shl1OOshfH3XDA=
所以其中的bAExy9pPp0EnzjAlYn1bsSEGvqYi1shl1OOshfH3XDA=就是我们将要进行证书锁定的指纹(Hash)信息。
证书锁定旨在解决移动端APP与服务端通信的唯一性,实际通信过程中,如果锁定过程失败,那么客户端APP将拒绝针对服务器的所有 SSL/TLS 请求,FaceBook/Twitter则通过证书锁定以防止Charles/Fiddler等抓包工具中间人攻击。
总结
本文简单介绍了TLS的证书格式、原理以及简单的验证方式。更详细的TLS相关内容,可以参考阅读: