互联网的通信安全,建立在SSL/TLS之上
引自 阮一峰《SSL/TLS协议运行机制的概述》。
为什么使用SSL/TLS
不使用SSL/TLS的HTTP通信,即明文通信,存在三大风险
- 窃听风险
- 篡改风险
- 访问网页插播小广告
- 冒充风险
- 钓鱼网站
SSL/TLS怎么解决以上问题:
- 防窃听:通信过程加密
- 防篡改:具备校验机制,一旦被篡改,通信双方会立刻发现
- 防冒充:配备证书,防止被冒充
发展历程
- SSL(Secure Socket Layer,安全套接字层)
- 1994年Netscape公司设计了SSL 1.0,但是未发布
- 1995年Netscape公司发布SSL 2.0,存在严重的安全漏洞被3.0替代
- 1996年Netscape发布SSL 3.0,得到大规模应用
- TLS(Transport Layer Security,传输层安全性协议)
- 1999年IETF将SSL标准化,并称作TLS,发布了SSL的升级版TLS 1.0版本
- 2006年发布TLS 1.1
- 2008年发布TLS 1.2,目前应用最广泛的版本
- 2018年8月发布TLS 1.3版本
TLS是SSL的升级版,TLS 1.0的版本号是3.1
SSL/TLS如何工作
SSL混合使用了多种加密技术,理解SSL之前先理解这些加密技术:
- SSL使用公开密钥加密(public key cryptography)来提供认证
- 私钥加密(secret key cryptography)保证数据隐私
- 数字签名来保证数据完整性
公开密钥加密(public key cryptography)
- 也称非对称加密
- 加解密采用一对密钥,公钥公开,私钥保密。
- 用公钥加密只有私钥能解开,反之亦然。
- 主要用于身份验证。(B使用自己的私钥加密数据发送给A,如果A能够采用B的公钥进行解密,则可以相信数据确实来自B)
- 数字签名
- 公钥存在形式:数字证书
- 缺点:计算耗时
- 常见的公开密钥加密算法
- RSA、ElGamal、背包算法、Rabin、迪菲-赫尔曼密钥交换协议中的公钥加密算法、椭圆曲线加密算法(ECC)
私钥加密(secret key cryptography)
- 也称对称加密、共享密钥加密
- 加解密采用采用相同的密钥,因此是对称的,且在通信双方共享
- 加解密速度比公开密钥加密快很多。
- 常见的对称加密算法有DES、3DES、AES、Blowfish、IDEA、RC5、RC6。
- 缺点:如何在通信双方之间安全的共享密钥?
工作原理
对称加密算法加密速度快,而且很安全,因此可被用作数据传输的加密算法。但是其薄弱点是如何在通信双方之间安全的共享密钥,即密钥分发问题。
有没有办法在非安全的通信信道上协商出一个安全的密钥用于后续采用对称加密进行通信使用(即使通信过程被第三方截获,但是只有通信双方才知道密钥)?答案是肯定的。
为了解决这个问题,协议设计者引入了公开密钥加密算法(即非对称加密),利用该算法作为基础,可以在非安全的传输通道上协商出一个安全的通信密钥。
以公开密钥加密算法为基础可以解决密钥分发问题:
- Alice含有一对密钥,公钥公开,私钥保留。
- Bob使用Alice的公钥加密信息发给Alice,Alice用其私钥解开。即使Charlie截获了Bob发给Alice的信息,但是由于其没有Alice的私钥,因此其无法解开。
- Bob向Alice发消息是没有问题的,但是Alice向Bob发送经过Alice私钥加密后的消息还是可以被Charlie解开(因为Alice的公钥是公开的,Charlie可以使用Alice的公钥解开Alice发送给Bob的消息)
所以,单纯使用公开密钥加密是不行的,可利用公开密钥加密算法协商出一套后期双方通信的密钥,并且保证即使第三方知道双方通信的过程,依然无法知晓后期通信的真正密钥。
基于此,可以看出SSL/TLS的工作原理简单来说就是,使用公开密钥加密算法为基础对通信双方进行认证,并协商出一套用于后期对称加密的密钥和算法。
密钥协商过程
对SSL/TLS的密钥协商过程简单抽象成下面的通信(实际上比这个更复杂)
- Bob 生成一个随机数a,使用Alice公钥加密成A后发送给Alice(Charlie无法将A解密成a,因为它没有Alice私钥)
- Alice生成一个随机数b,使用Alice私钥加密成B后发送给Bob(Charlie可以利用Alice的公钥将B解密成b)
- Bob再生成一个随机数c,使用Alice的公钥加密成C后发送给Alice(Charlie不知道C)。这一步,Bob和Alice都知道三个数(a、b、c),但Charlie只知道b
- 然后,Bob和Alice分别使用一个已知算法PRF,对三个随机数a、b、c进行计算生成最终的共享密钥K,后期通信就使用K进行。
- 由于K没有明文传输,且攻击者由于没有获取到足够信息也无法生成,每次协商都生成不同的密钥。因此具有很强的安全性。
中间人攻击
以上协商过程还存在漏洞:中间人攻击。
Charlie可以自己生成一套公钥和私钥,然后将Alice的公钥替换成自己的公钥,从而伪装成Alice跟Bob通信,然后伪装成Bob跟Alice进行通信。从而可以知晓双方通信的各种随机数,然后可以计算出Bob和Alice通信的密钥。或者单纯就伪装成Alice跟Bob通信
这里的关键是如何防止Alice的公钥被替换?或者是Bob(客户端)如何识别出Alice(服务端)是一个冒牌货?防止公钥被替换,我们忽略了一个细节:公钥怎么保存,客户端如何拿到公钥的?
事实上,公钥是通信时候,另一方告诉我的。
任何人都可以生成自己的公钥和私钥,在Bob向Alice发请求询问Alice的公钥的时候,可以被Charlie拦截,然后Charlie将自己的公钥发给Bob,从而伪装成Alice。Bob无法识别出来Charlie是冒牌的。
解决办法:
- 提供一个由权威机构(CA)颁发的证书来证明这个公钥就是属于Alice的。
- Alice发送给Bob的不再是单纯的公钥,而是由CA认证的证书,这个证书里面包含了Alice的公钥,发行机构信息(CA),以及证书持有者(Alice),还有CA的签名,证书有效期
- Bob相信CA,从而可以相信CA颁发的证书,从而相信其拿到的公钥就是Alice的公钥,从而相信和它通信的就是Alice(因为只有Alice才有私钥)。
如何校验证书
Alice发给Bob的证书,Bob如何校验真伪?
- 首先Bob拿到证书后,查看证书的颁发者是否可信,如果不可信则终止连接。
- 怎么知道证书的颁发者是否可信?
- 系统里面预装根证书,或者用户自己安装根证书,根证书是CA自己给自己颁发的证书。这个信任靠得就是平台本身和用户自己。
- 如果CA在你信任的CA表里面,那么说明是受信任的。
- CA可信任后,需要进一步检查证书有没有被篡改。
- 完整性校验依赖于数字签名。
- 证书上面有CA的签名。签名生成过程:
- 利用HASH算法对证书内容计算出HASH值,然后CA用自己的私钥对HASH进行加密,这就是CA对该证书的签名
- 校验:
- 利用CA的公钥(根证书里面有)对签名进行解密,得到的就是解密后的HASH值
- 利用HASH算法对证书内容计算出HASH,和上一步解密后的HASH对比,如果不一致则认为被篡改
- 为啥篡改者不连签名也一起改了?
- 因为它没有CA的私钥。
- 别忘了,还有证书有效期检查
证书知识
证书格式标准目前主要为X.509
证书包括的主要内容:
- 颁发机构(CA)的名字(issuer)
- 证书持有者(subject)
- 证书持有者的公钥和算法
- 证书有效期
- 证书内容本身的数字签名和算法(用CA私钥加密)
- 证书序列号(具有唯一性,可以吊销)
证书可以自签名(自己给自己颁发),也可以由权威的CA颁发。
证书颁发机构CA分根CA和中间CA,通常证书不是直接由根CA颁发,而是由一个或多个中间CA签发。根CA给中间CA颁发证书,中间CA再给你颁发证书。最终用户用来认证公钥的证书被称作end user 证书。
这些证书构成了一条证书链。在服务端向客户端发送证书的时候,就需要发送证书链。
SSL/TLS 协议
工作原理讲了,来看看协议实际过程。
位于传输层和应用层之间,与应用层协议无关。
SSL/TLS通信开始于信息交换,这里的信息交换叫做SSL握手。
SSL握手有三个主要目的:
- 协商加密套件
- 认证通信方(可选)
- 基于协商好的加密机制构建信息安全
SSL握手过程
1. ClientHello
客户端向服务器发起加密通信的请求
主要提供以下信息
- 最高支持的TLS协议版本
- 一个客户端生成的随机数,稍后用于生成“对话密钥”
- 支持的加密套件列表
- 支持的压缩算法
加密套件格式(TLS 1.3之前): 密钥交换算法_对称加密算法_MAC算法_PRF
2. Server hello
服务端选择双方都支持的SSL版本、最佳加密套件、压缩算法,产生一个随机数返回。
3. Certificate (可选)
服务端发送给客户端它的证书或者证书链(以公钥证书开始,链到根CA)。这一步可选,依赖于前两步是否要求验证服务端。
4. Certificate request(可选)
服务端要求验证客户端身份的时候才会用到,用来请求客户端发送它的证书给服务端
金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。
5. Server key exchange(可选)
依赖于Server hello阶段选择密码交换算法,如果是基于Diffie-Hellman算法,则需要发送该消息,里面包含了Server的DH公钥。
6. Server hello done
7. Certificate(可选)
如果第4步,服务端要求客户端发送证书,则发送该消息。
格式和服务端发送证书一样
8. Client key exchange
客户端生成用于创建用于对称加密的密钥的信息(premaster key,看作第三个随机数?)。 对于RSA,客户端然后使用服务器的公钥加密此密钥信息并将其发送到服务器。 对于基于Diffie-Hellman的密码套件,此消息包含客户端的DH公钥。
这个消息发送个服务端后,客户端和服务端可以根据之前的两个随机数,加上premaster key,然后利用前面协商好的PRF算法生成后续通信用的加密密钥。
9. Certificate verify(可选)
这个消息是向服务端提供了证书之后才需要发送,它使用自己的私钥加密到现在为止发送的所有消息的hash,然后服务端通过客户端证书里的公钥解密后进行hash验证,来确保确实由客户端的私钥签署。
10 Change Cipher Spec
客户端告诉服务端,后续通信就用协商好的密钥进行加密
11. Client Finished
客户端握手结束通知。这一项也是前面发送的所有内容的hash值。应该是用协商好的密钥进行加密,供服务端进行验证。(不确定)
12 Server Change cipher spec
服务端发送改变密钥通知
13 Server Finished
服务端握手结束通知
SSL协议握手完成之后就已经生成了一套后续通信用的对称密钥以及算法,后续则使用协商好的密钥进行加解密通信。
总结
SSL/TLS构建的是一个加密通道,和上层应用协议无关。
HTTP over TLS = HTTPS
MQTT也支持TLS
你也可以自定义协议基于SSL、TLS
参考资料
- http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
- https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E6%80%A7%E5%8D%94%E5%AE%9A
- https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
- https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc785811(v=ws.10)
- https://developer.android.com/training/articles/security-ssl?hl=zh-cn
- https://security.stackexchange.com/questions/20803/how-does-ssl-tls-work