1. HTTPS为什么出现
HTTPS协议是Hyper Text Transfer Protocol over SecureSocket Layer(超文本传输安全协议)的缩写,是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。
HTTPS 是 HTTP 协议的一种扩展,它本身并不保传输的证安全性,那么谁来保证安全性呢?在 HTTPS 中,使用传输层安全性(TLS)或安全套接字层(SSL)对通信协议进行加密。也就是 HTTP + SSL(TLS) = HTTPS
1.1 HTTPS解决了什么问题?
一个简单的回答可能会是 HTTP 它不安全。
- 由于 HTTP 天生明文传输的特性,在 HTTP 的传输过程中,任何人都有可能从中
截获、修改或者伪造请求发送,所以可以认为 HTTP 是不安全的,信息容易被窃取 - 在 HTTP 的传输过程中不会验证通信方的身份,因此 HTTP 信息交换的双方可能会遭到伪装,也就是
没有用户验证,身份容易被伪装 - 在 HTTP 的传输过程中,接收方和发送方并
不会验证报文的完整性,信息容易被篡改
1.2 HTTPS做了什么?
HTTPS 协议提供了三个关键的指标:
信息加密: HTTP 交互信息是被加密的,第三⽅就⽆法被窃取;校验机制:校验信息传输过程中是否有被第三⽅篡改过,如果被篡改过,则会有警告提示;身份证书:证明淘宝是真的淘宝⽹;
2. 密码学/数字证书
在了解HTTPS的整个流程前我们先来学习一些密码学和数字证书相关的知识点。
2.1 对称加密
在了解对称加密前,我们先来了解一下密码学的东西,在密码学中,有几个概念:明文、密文、加密、解密.
-
明文(Plaintext):一般认为明文是有意义的字符或者比特集,或者是通过某种公开编码就能获得的消息。明文通常用 m 或 p 表示。 -
密文(Ciphertext):对明文进行某种加密后就变成了密文。 -
加密(Encrypt):把原始的信息(明文)转换为密文的信息变换过程。 -
解密(Decrypt):把已经加密的信息恢复成明文的过程。
对称加密 (Symmetrical Encryption) 顾名思义就是指加密和解密时使用的密钥都是同样的密钥。只要保证了密钥的安全性,那么整个通信过程也就是具有了机密性。
TLS 里面有比较多的加密算法可供使用,比如 DES、3DES、AES、ChaCha20、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK 等。目前最常用的是 AES-128, AES-192、AES-256 和 ChaCha20。
AES-128, AES-192 和 AES-256 都是属于 AES ,AES 的全称是Advanced Encryption Standard(高级加密标准),它是 DES 算法的替代者,安全强度很高,性能也很好,是应用最广泛的对称加密算法。
ChaCha20 是 Google 设计的另一种加密算法,密钥长度固定为 256 位,纯软件运行性能要超过 AES,曾经在移动客户端上比较流行,但 ARMv8 之后也加入了 AES 硬件优化,所以现在不再具有明显的优势,但仍然算得上是一个不错算法。
(其它可自行搜索)
2.2 非对称加密
非对称加密(Asymmetrical Encryption) 也被称为公钥加密,相对于对称加密来说,非对称加密是一种新的改良加密方式。密钥通过网络传输交换,它能够确保及时密钥被拦截,也不会暴露数据信息。
非对称加密中有两个密钥,一个是公钥,一个是私钥,公钥进行加密,私钥进行解密。公开密钥可供任何人使用,私钥只有你自己能够知道。
公钥加密的文本只能使用私钥解密,同时使用私钥加密的文本也可以使用公钥解密。公钥不需要具有安全性,因为公钥需要在网络间进行传输,非对称加密可以解决密钥交换的问题。
网站保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密。而黑客因为没有私钥,所以就无法破解密文。
其中 RSA 加密算法是最重要的、最出名的一个了。例如 DHE_RSA_CAMELLIA128_GCM_SHA256。它的安全性基于 整数分解,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。
TLS 是使用对称加密和非对称加密 的混合加密方式来实现机密性。
2.3 混合加密
RSA 的运算速度非常慢,而 AES 的加密速度比较快,而 TLS 正是使用了这种混合加密方式。
在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE ,首先解决密钥交换的问题。
然后用随机数产生对称算法使用的会话密钥(session key),再用公钥加密。对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换。
使用混合加密的方式实现了机密性,是不是就能够安全的传输数据了呢?还不够,在机密性的基础上还要加上完整性、身份认证的特性,才能实现真正的安全。而实现完整性的主要手段是 摘要算法(Digest Algorithm).
2.4 了解HASH算法
Hash算法,也叫做散列算法,就是把任意长度的输入通过散列函数变化成固定长度的输出,该输出就是散列值。可以用来以一种较短的信息来标识输入信息的唯一性。常见的Hash算法有MD5、SHA1。
Hash算法特点:
正向快速:给定指定明文和Hash算法,能在有限资源和时间内计算输出散列值。
逆向困难:在有限时间内,基本不可能推断出明文。
输入敏感:明文的微小变动,产生的散列值区别非常大。
2.4 数字证书/签名
黑客伪装成你,来向服务器发送信息,也可以伪装称为服务器,接受你发送的信息。那么怎么解决这个问题呢?
如何确定你自己的唯一性呢?我们在上面的叙述过程中出现过公钥加密,私钥解密的这个概念。提到的私钥只有你一个人所有,能够辨别唯一性,所以我们可以把顺序调换一下,变成私钥加密,公钥解密。使用私钥再加上摘要算法,就能够实现数字签名,从而实现认证。
个数字证书通常包含了:
公钥;
持有者信息;
证书认证机构(CA)的信息;
CA 对这份⽂件的数字签名及使⽤的算法;
证书有效期;
还有⼀些其他额外信息
我们⽤证书来认证公钥持有者的身份(服务端的身份),那证书⼜是怎么来的?⼜该怎么认证证书呢?
为了让服务端的公钥被⼤家信任,服务端的证书都是由 CA (Certificate Authority,证书认证机构)签名的,CA 就是⽹络世界⾥的公安局、公证中⼼,具有极⾼的可信度,所以由它来给各个公钥签名,信任的⼀⽅签发的证书, 那必然证书也是被信任的。
之所以要签名,是因为签名的作⽤可以避免中间⼈在获取证书时对证书内容的篡改。
数字证书签发和验证流程:
- CA 签发证书的过程,如上图左边部分:
- ⾸先 CA 会把持有者的公钥、⽤途、颁发者、有效时间等信息打成⼀个包,然后对这些信息进⾏ Hash 计算, 得到⼀个 Hash 值;
- 然后 CA 会使⽤⾃⼰的私钥将该 Hash 值加密,⽣成 Certificate Signature,也就是 CA 对证书做了签名;
- 最后将 Certificate Signature 添加在⽂件证书上,形成数字证书;
- 客户端校验服务端的数字证书的过程,如上图右边部分:
- ⾸先客户端会使⽤同样的 Hash 算法获取该证书的 Hash 值 H1;
- 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使⽤ CA 的公钥解密 Certificate Signature 内容,得到⼀个 Hash 值 H2 ;
- 最后⽐较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。
3. 探究HTTPS
经过上面的学习你基本上已经学习到了https的精髓了。
传统的 TLS 握⼿基本都是使⽤ RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书⽂件中包含⼀对公私钥,其中公钥会在 TLS 握⼿阶段传递给客户端,私钥则⼀直留在服务端,⼀定要确保私钥不能被窃取。
在 RSA 密钥协商算法中,客户端会⽣成随机密钥,并使⽤服务端的公钥加密后再传给服务端。根据⾮对称加密算法,公钥加密的消息仅能通过私钥解密,这样服务端解密后,双⽅就得到了相同的密钥,再⽤它加密应⽤消息。
⽤ Wireshark ⼯具抓了⽤ RSA 密钥交换的 TLS 握⼿过程,你可以从下⾯看到,⼀共经历来四次握⼿:
3.1 TLS第一次握手
客户端⾸先会发⼀个「Client Hello」消息,字⾯意思我们也能理解到,这是跟服务器「打招呼」。
消息⾥⾯有客户端使⽤的 TLS 版本号、⽀持的密码套件列表,以及⽣成的随机数(Client Random),这个随机 数会被服务端保留,它是⽣成对称加密密钥的材料之⼀。
3.2 TLS第二次握手
当服务端收到客户端的「Client Hello」消息后,会确认 TLS 版本号是否⽀持,和从密码套件列表中选择⼀个密码 套件,以及⽣成随机数(Server Random)。
返回「Server Hello」消息,消息⾥⾯有服务器确认的 TLS 版本号,也给出了随机数(Server Random), 然后从客户端的密码套件列表选择了⼀个合适的密码套件。
服务端选择的密码套件是 Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256, 密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法
- 服务端为了证明⾃⼰的身份,会发送「Server Certificate」给客户端,这个消息⾥含有数字证书。
- 随后,服务端发了「Server Hello Done」消息,⽬的是告诉客户端,我已经把该给你的东⻄都给你了,本次打招 呼完毕。
3.3 客户端验证证书
在这⾥刹个⻋,客户端拿到了服务端的数字证书后,要怎么校验该数字证书是真实有效的呢?
在说校验数字证书是否可信的过程前,我们先来看看数字证书是什么?
⼀个数字证书通常包含了:
- 公钥;
- 持有者信息;
- 证书认证机构(CA)的信息;
- CA 对这份⽂件的数字签名及使⽤的算法;
- 证书有效期;
- 还有⼀些其他额外信息;
那数字证书的作⽤,是⽤来认证公钥持有者的身份,以防⽌第三⽅进⾏冒充。说简单些,证书就是⽤来告诉客户 端,该服务端是否是合法的,因为只有证书合法,才代表服务端身份是可信的。
我们⽤证书来认证公钥持有者的身份(服务端的身份),那证书⼜是怎么来的?⼜该怎么认证证书呢?
为了让服务端的公钥被⼤家信任,服务端的证书都是由 CA (Certificate Authority,证书认证机构)签名的,CA 就是⽹络世界⾥的公安局、公证中⼼,具有极⾼的可信度,所以由它来给各个公钥签名,信任的⼀⽅签发的证书, 那必然证书也是被信任的。
之所以要签名,是因为签名的作⽤可以避免中间⼈在获取证书时对证书内容的篡改。
数字证书签发和验证流程:
- CA 签发证书的过程,如上图左边部分:
- ⾸先 CA 会把持有者的公钥、⽤途、颁发者、有效时间等信息打成⼀个包,然后对这些信息进⾏ Hash 计算, 得到⼀个 Hash 值;
- 然后 CA 会使⽤⾃⼰的私钥将该 Hash 值加密,⽣成 Certificate Signature,也就是 CA 对证书做了签名;
- 最后将 Certificate Signature 添加在⽂件证书上,形成数字证书;
- 客户端校验服务端的数字证书的过程,如上图右边部分:
- ⾸先客户端会使⽤同样的 Hash 算法获取该证书的 Hash 值 H1;
- 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使⽤ CA 的公钥解密 Certificate Signature 内容,得到⼀个 Hash 值 H2 ;
- 最后⽐较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。
3.4 TLS第三次握手
客户端验证完证书后,认为可信则继续往下⾛。接着,客户端就会⽣成⼀个新的随机数 (pre-master),⽤服务器 的 RSA 公钥加密该随机数,通过「Change Cipher Key Exchange」消息传给服务端
服务端收到后,⽤ RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
客户端和服务端双⽅都共享了三个随机数,分别是 Client Random、Server Random、pre-master。 于是,双⽅根据已经得到的三个随机数,⽣成会话密钥(Master Secret),它是对称密钥,⽤于对后续的 HTTP 请求/响应的数据加解密.
- ⽣成完会话密钥后,然后客户端发⼀个「Change Cipher Spec」,告诉服务端开始使⽤加密⽅式发送消息
- 客户端再发⼀个「Encrypted Handshake Message(Finishd)」消息,把之前所有发送的数据做个摘 要,再⽤会话密钥(master secret)加密⼀下,让服务器做个验证,验证加密通信是否可⽤和之前握⼿信息是否有 被中途篡改过
可以发现,「Change Cipher Spec」之前传输的 TLS 握⼿数据都是明⽂,之后都是对称密钥加密的密⽂。
3.5 TLS第四次握手
服务器也是同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双⽅都 验证加密和解密没问题,那么握⼿正式完成。
最后,就⽤「会话密钥」加解密 HTTP 请求和响应了。
4. HTTPS的优化点
因为 HTTPS 相⽐ HTTP 协议多⼀个 TLS 协议握⼿过程,⽬的是为了通过⾮对称加密握⼿协商或者交换出对称加密 密钥,这个过程最⻓可以花费掉 2 RTT,接着后续传输的应⽤数据都得使⽤对称加密密钥来加密/解密。
- 对于协议优化的⽅向:
- 密钥交换算法应该选择 ECDHE 算法,⽽不⽤ RSA 算法,因为 ECDHE 算法具备前向安全性,⽽且客户端可 以在第三次握⼿之后,就发送加密应⽤数据,节省了 1 RTT。
- 将 TSL1.2 升级 TSL1.3,因为 TSL1.3 的握⼿过程只需要 1 RTT,⽽且安全性更强。
- 对于证书优化的⽅向:
- 服务器应该选⽤ ECDSA 证书,⽽⾮ RSA 证书,因为在相同安全级别下,ECC 的密钥⻓度⽐ RSA 短很多,这 样可以提⾼证书传输的效率;
- 服务器应该开启 OCSP Stapling 功能,由服务器预先获得 OCSP 的响应,并把响应结果缓存起来,这样 TLS 握⼿的时候就不⽤再访问 CA 服务器,减少了⽹络通信的开销,提⾼了证书验证的效率;
- 对于重连 HTTPS 时,我们可以使⽤⼀些技术让客户端和服务端使⽤上⼀次 HTTPS 连接使⽤的会话密钥,直接恢 复会话,⽽不⽤再重新⾛完整的 TLS 握⼿过程。
- 常⻅的会话重⽤技术有 Session ID 和 Session Ticket,⽤了会话重⽤技术,当再次重连 HTTPS 时,只需要 1 RTT 就可以恢复会话。对于 TLS1.3 使⽤ Pre-shared Key 会话重⽤技术,只需要 0 RTT 就可以恢复会话。
这些会话重⽤技术虽然好⽤,但是存在⼀定的安全⻛险,它们不仅不具备前向安全,⽽且有重放攻击的⻛险,所以 应当对会话密钥设定⼀个合理的过期时间