背景理解
HTTPS并非是应用层的一种新协议. 只是HTTP通信接口部分用SSL(Secure Socket Layer)和TLS (Transport Layer Security) 协议替代而已.
通常, HTTP直接和TCP通信, 当使用SSL时, 演变成了先和SSL通信, 再由SSL和TCP通信了, 简而言之, 所谓HTTPS, 其实就是身披SSL协议的这层外壳的HTTP.
在采用SSL后, HTTP就拥有了HTTPS的加密, 证书和完整性的保护这些功能.
因为是先有 HTTP 再有 HTTPS。所以,HTTPS 的设计者肯定要考虑到对原有 HTTP 的兼容性。
这里所说的兼容性包括很多方面。比如已有的 Web 应用要尽可能无缝地迁移到 HTTPS;比如对浏览器厂商而言,改动要尽可能小;……
基于“兼容性”方面的考虑,很容易得出如下几个结论:
-
HTTPS 还是要基于 TCP 来传输
(如果改为 UDP 作传输层,无论是 Web 服务端还是浏览器客户端,都要大改,动静太大了) -
单独使用一个新的协议,把 HTTP 协议包裹起来
(所谓的“HTTP over SSL”,实际上是在原有的 HTTP 数据外面加了一层 SSL 的封装。HTTP 协议原有的 GET、POST 之类的机制,基本上原封不动)
打个比方:如果原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。
HTTP+认证+加密+完整性保护 = HTTPS
一、 “SSL/TLS”是什么
SSL 是英文“Secure Sockets Layer”的缩写,中文叫做“安全套接层”。它是在上世纪90年代中期,由网景公司设计的。(顺便插一句,网景公司不光发明了 SSL,还发明了很多 Web 的基础设施——比如“CSS 样式表”和“JS 脚本”)
为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。
到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。
很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。
二、签名和数字证书
1. 签名
签名就是在信息后边加上一段内容,证明信息没有被修改过,怎样达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意这个过程是不可逆的。发送信息时,把这个hash值加密后,和信息一起发出去。接收方在收到信息时,会重新计算hash值,并和信息所附带的hash值(解密后)作比较,如果一致就说明信息没有被篡改过。
利用签名来实现完整性保护。
2. 数字证书
一个证书包含下面的具体内容:
- 证书的发布机构
- 证书的有效期
- 公钥
- 证书所有者(Subject)
- 签名所使用的算法
- 指纹以及指纹算法
证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。
所以数字证书的作用总结有两点:
- 确认对方身份
- 获取公钥
三、通信过程
RSA在整个通信过程中起到的作用:
- 因为私钥只有服务器所有,所以客户端可以通过判断对方是否有私钥来确认对方是否是服务器。
- 客户端通过RSA的保护,安全的把对称加密算法和秘钥告诉服务端,来保证后边通信过程的安全。
现在我们知道,我们可以通过判断对方是否有私钥来确认对方是否是服务器。那么黑客完全可以自己生成一对私钥。
这里问题的根源就在于,大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的。
这就是为什么要用到数字证书了,完整的过程:
- step1,客户端向服务端发送一个通信请求,客户端支持的加密算法,包含生成的随机数A,tls的版本。
- step2,服务端返回确定了的加密算法,向客户端发送一个数字证书,证书中包含了公钥用来加密信息, 服务端保留了私钥,包含生成的随机数B。
- step3,客户端收到服务端的数字证书后,会去验证证书是不是服务端的。证书是否过期、发型服务器证书的CA是否可靠、返回的公钥是否能正确解开返回证书中的数字签名、服务器证书上的域名是否和服务器的实际域名相匹配,如果服务端暂时没有问题,接下来需要确认服务端是不是拥有私钥:客户端会发送一串随机的字符串(预主秘钥)给服务器,服务器用私钥进行加密返回给客户端,客户端用公钥解密,如果是之前发送的随机字符串,那么说明服务端拥有私钥,这样就确认了对方确实是我们要通信的合法服务器。
- step4,客户端使用会话秘钥(随机数A+随机数B+预主秘钥)和商定的对称加密的算法,发送个加密握手消息,客户端同样发送个加密的握手消息,来确认连接的成功建立。这样后边的通信,客户端和服务端的通信就用这个对称加密密钥和算法来加密解密数据了。
以上过程是单向认证,如果是双向认证,在客户端验证完服务端以后,用同样的方式验证客户端的身份。
四、扩展
上述过程已经很接近HTTPS的通信过程了,完全可以通过这个过程理解HTTPS的工作原理。为了更深入的理解,以下增加一些细节,有兴趣的可以看下。
- 问题:
上边通信过程中的第二步,在验证完了证书后,客户端会发送随机字符串给服务端,来判断对方是否真的持有私钥。这样对于服务器来说其实是不安全的,因为黑客也可以发送这样的字符串给服务端,让服务端不断的加密,黑客会发送一些有规律的字符串,不断对比,来猜测私钥。所以服务端随随便便的用私钥来来加密一个来路不明的字符串并把结果返回给他是不安全的。
解决方案:
服务端在收到客户端发送过来的字符串后,并不是对该字符串进行加密,而是对字符串进行hash计算,加密字符串的hash值返回给客户端,客户端收到hash值后通过公钥解密,再和自己计算得到的hash值对比,如果一致就说明对方持有私钥。
参考资料:
聊聊HTTPS和SSL/TLS协议
双向认证SSL原理