什么是 HTTPS
HTTPS 解决了 HTTP 不安全的问题
HTTP 整个传输过程数据都是明文的,任何人都能够在链路中截获 、修改 或者伪造请求/响应报文,数据不具有可信性。
-
① HTTPS 使用加密算法 对报文进行加密,黑客截获了也看不懂
-
② HTTPS 使用摘要算法 对报文进行完整性确认,黑客一旦修改报文,那么 HTTPS 可以及时发现并做相应处理
-
③ HTTPS 使用数字签名 ,保证黑客不能伪造请求或响应报文
HTTPS 由 HTTP + SSL/TLS 组成 ,即在 HTTP 下面增加了一个 SSL 安全套接层(运行在SSL 之上的HTTP协议)
SSL 即安全套接层 (Secure Sockets Layer),在 OSI 七层网络模型中处于第 5 层(会话层),由网景公司于 1994 年发明,常用 v2 和 v3 两个版本。
IETF 在1999 年把它改名为 TLS (传输层安全 ,Transport Layer Security),正式标准化,版本号从 1.0 重新算起,所以 TLS1.0 实际上就是 SSLv3.1。
今天 TLS 已经发展出了三个版本,分别是 2006 年的 1.1、2008 年的 1.2 和 2018 年的1.3,目前应用的最广泛的 TLS 是 1.2 。
HTTPS 的安全性是基于 TLS 的加密算法,因此要理解 HTTPS 其实就是要理解 TLS 背后的加密算法原理。
数据加密算法
古典密码学
在古代战争中,为了防止书信被截获后重要信息泄露,人们开始对书信进行加密。
移位式加密
如密码棒,使用布条缠绕在木棒上的方式来对书信进行加密。
- 加密算法:缠绕后书写
- 密钥:木棒的尺寸
替换式加密
按规则使用不同的文字来替换掉原先的文字来进行加密。
例如,码表:
原始字符:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密码字符:BCDEFGHIJKLMNOPQRSTUVWXYZA
原始书信:I love you
加密书信:J mpwf zpv
解读后:I love you
- 加密算法:替换文字
- 密钥:替换的码表
与古典密码学相对应的就是现代密码学 ,主要包括两大分类:对称加密算法 和非对称加密算法
- 可以加密任何二进制数据
- 非对称加密的出现使得密码学有了更广泛的用途:数字签名
对称加密算法
对称加密算法:使用相同的密钥,不同的加密和解密算法,对明文加密,对密文解密。
TLS 里有非常多的对称加密算法可供选择,比如 RC4、DES、3DES、AES、ChaCha20 等,前三种被认为不安全,目前常用的只有 AES 和 ChaCha20
-
AES 的意思是"高级加密标准 "(Advanced Encryption Standard) ,密钥长度可以是 128 位(比特)、192 位(比特)或 256 位(比特)。安全强度很高,性能也很好,而且有的硬件还会做特殊优化,所以非常流行,是应用最广泛的对称加密算法。
-
ChaCha20 是 Google 设计的另一种加密算法,密钥长度固定为 256 位,纯软件运行性能要超过 AES ,曾经在移动客户端上比较流行,但 ARMv8 之后也加入了 AES 硬件优化,所以现在不再具有明显的优势,但仍然算得上是一个不错的算法。
对称加密的破解
破解思路:
- 拿到一组或多组原文-密文对
- 设法找到一个密钥,这个密钥可以将这些原文-密文对中的原文加密为密文,以及将密文解密为原文的组合,即为成功破解
反破解:
- 一种优秀的对称加密算法的标准是,让破解者找不到比穷举法(暴力破解法)更有效的破解手段,并且穷举法的破解时间足够长(例如数千年)。
对称加密的缺点
对称加密算法面临的最大问题:如何把密钥安全地传递给对方 ,术语叫做"密钥交换"。
对称加密算法的缺点就是不能在不安全的网络上传输密钥,因为一旦密钥泄露则加密通信失败。
非对称加密算法
非对称加密算法是使用相同的加密算法 + 两个不同的密钥(不对称),一个叫公钥(public key),一个叫私钥(private key),公钥可以公开给任何人使用,而私钥必须严格保密。
公钥和私钥有个特点:单向性,虽然都可以用来加密解密,但公钥加密后只能用私钥来解密,反过来,私钥加密后也只能用公钥来解密。
使用非对称加密通信,可以在不可信网络上将双方的公钥传给对方,然后在发消息前分别对消息使用对方的公钥来加密和使用自己的私钥来签名,做到不可信网络上的可靠密钥传播及加密通信。
RSA
非对称加密算法的设计要比对称算法难得多,在 TLS 里只有很少的几种,比如 DH、DSA、RSA、ECC 等。
RSA 可能是其中最著名的一个,几乎可以说是非对称加密的代名词,它的安全性基于"整数分解 "的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。
10 年前 RSA 密钥的推荐长度是 1024 ,但随着计算机运算能力的提高,现在 1024 已经不安全,普遍认为至少要 2048 位。
ECC
ECC (Elliptic Curve Cryptography)是非对称加密里的"后起之秀",它基于"椭圆曲线离散对数 "的数学难题,使用特定的曲线方程和基点生成公钥和私钥 ,子算法 ECDHE 用于密钥交换 ,ECDSA 用于数字签名。
目前比较常用的两个曲线是 P-256 (secp256r1,在 OpenSSL 称为 prime256v1) 和 x25519。P-256 是 NIST (美国国家标准技术研究所)和 NSA(美国国家安全局)推荐使用的曲线,而 x25519 被认为是最安全、最快速的曲线。
比起 RSA,ECC 在安全强度和性能上都有明显的优势。160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA。因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能就上去了,对于现在的移动互联网非常有吸引力。
非对称加密的破解
破解思路:
- 和对称加密不同之处在于,非对称加密的公钥很容易获得,因此制造原文-密文对是没有困难的事
- 所以,非对称加密的关键只在于,如何找到一个正确的私钥,可以解密所有经过公钥加密过的密文。找到这样的私钥即为成功破解
- 由于非对称加密的自身特性,怎样通过公钥来推断出私钥通常是一种思路(例如RSA),但往往最佳手段依然是穷举法,只是和对称加密破解的区别在于,对称加密破解是不断尝试自己的新密钥是否可以将自己拿到的原文-密文对进行加密和解密,而非对称加密时不断尝试自己的新私钥是否和公钥互相可解。
反破解:
- 和对称加密一样,非对称加密算法优秀的标准同样在于,让破解者找不到比穷举法更有效的破解手段,并且穷举法的破解时间足够长。
非对称加密的优缺点
- 优点:可以在不安全网络上传输密钥
- 缺点:计算复杂,因此性能相比对称加密差很多
对称加密 VS 非对称加密
对称加密 | 非对称加密 |
---|---|
有密钥交换问题 | 没有密钥交换问题 |
运算速度快 | 运算速度很慢 因为非对称加密算法基于复杂的数学难题,即使是 ECC 也要比 AES 差上好几个数量级 |
如果只用非对称加密,虽然保证了安全,但通信速度非常慢,实用性就变成了零。
TLS 使用混合加密的方式
在通信刚开始的时候使用非对称算法 ,比如 RSA、ECDHE ,首先解决密钥交换的问题。
混合加密 就解决了对称加密算法 的密钥交换问题,而且安全和性能兼顾。
然后用随机数产生对称算法 使用的"会话密钥 "(session key),再用公钥加密。因为会话密钥很短,通常只有 16 字节或 32 字节,所以慢一点也无所谓。
数据完整性
摘要算法
黑客虽然拿不到会话密钥,无法破解密文,但可以通过窃听收集到足够多的密文,再尝试着修改、重组后发给网站。因为没有完整性保证,服务器只能"照单全收",然后他就可以通过服务器的响应获取进一步的线索,最终就会破解出明文。
实现完整性的手段主要是摘要算法(Digest Algorithm)。
你可以把摘要算法近似地理解成一种特殊的压缩算法 ,它能够把任意长度的数据"压缩"成固定长度、而且独一无二的"摘要"字符串 ,就好像是给这段数据生成了一个数字"指纹"。
换一个角度,也可以把摘要算法理解成特殊的"单向"加密算法 ,它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文。
MD5 (Message-Digest 5) 和 SHA-1 (Secure Hash Algorithm 1)就是最常用的两个摘要算法,能够生成 16 字节和 20 字节长度的数字摘要。但这两个算法的安全强度比较低,不够安全,在 TLS 里已经被禁止使用了。
目前 TLS 推荐使用的是 SHA-1 的后继者:SHA-2
SHA-2 实际上是一系列摘要算法的统称,总共有 6 种,常用的有 SHA224 、SHA256 、SHA384,分别能够生成 28 字节、32 字节、48 字节的摘要。
如果黑客在中间哪怕改动了一个标点符号,摘要也会完全不同,网站计算比对就会发现消息被窜改,是不可信的。
数字签名
黑客可以伪装成网站来窃取信息。而反过来,他也可以伪装成你,向网站发送支付、转账等消息,网站没有办法确认你的身份,钱可能就这么被偷走了。
实际生活中,解决身份认证的手段是签名和印章,只要在纸上写下签名或者盖个章,就能够证明这份文件确实是由本人而不是其他人发出的。
在 TLS 里有什么东西和现实中的签名、印章很像,只能由本人持有,而其他任何人都不会有呢?只要用这个东西,就能够在数字世界里证明你的身份。
这个东西就是非对称加密里的"私钥 ",使用私钥再加上摘要算法,就能够实现"数字签名" ,就可以实现"身份认证"。
数字签名 就是把摘要算法生成的摘要 再用私钥进行加密后的内容,将这部分内容与原摘要一起放入报文,作为身份认证。
私钥加密 - 公钥解密
客户端向服务端发送加密报文的流程:
客户端签名流程:
- ① 对明文执行摘要算法(SHA-2)生成摘要
- ② 使用客户端私钥对生成的摘要进行加密生成签名 ,只对摘要进行加密是因为摘要比较短,这样加解密都比较快
- ③ 将摘要和签名一起附加到原文中,然后使用会话密钥对报文进行加密,生成密文,进行传输。
服务端验证签名流程:
- ① 使用会话秘钥对密文进行解密,得到明文
- ② 对明文执行摘要算法(SHA-2)生成摘要,比对报文中的摘要
- ③ 使用客户端公钥对签名进行解密得到摘要的明文,比对报文中的摘要
服务端向客户端发送加密报文流程与上面类似:
服务端签名流程:
- ① 对明文执行摘要算法(SHA-2)生成摘要
- ② 使用服务端私钥对生成的摘要进行加密生成签名
- ③ 将摘要和签名一起附加到原文中,然后使用会话密钥对报文进行加密,生成密文,进行传输。
客户端验证签名流程:
- ① 使用会话秘钥对密文进行解密,得到明文
- ② 对明文执行摘要算法(SHA-2)生成摘要,比对报文中的摘要
- ③ 使用服务端公钥对签名进行解密得到摘要的明文,比对报文中的摘要
公钥的信任问题
找一个公认的可信第三方,让它作为"信任的起点,递归的终点",构建起公钥的信任链。
这个"第三方"就是我们常说的 CA (Certificate Authority,证书认证机 构)。它就像网络世界里的公安局、教育部、公证中心,具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。
CA 数字证书
CA 对公钥的签名认证也是有格式的,不是简单地把公钥绑定在持有者身份上就完事了,还要包含序列号、用途、颁发者、有效时间 等等,把这些打成一个包再签名 ,完整地证明公钥关联的各种信息,形成"数字证书"(Certificate)。
知名的 CA 全世界就那么几家,比如 DigiCert、VeriSign、Entrust、Let's Encrypt 等,它们签发的证书分 DV、OV、EV 三种,区别在于可信程度。
DV 是最低的,只是域名级别的可信,背后是谁不知道。EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份。
问题:CA 怎么证明自己值得信任呢?
- 小一点的 CA 可以让大 CA 签名认证,但链条的最后,也就是 Root CA ,就只能自己证明自己了,这个就叫"根证书 "(Root Certificate)。 你必须相信,否则整个证书信任链就走不下去了。
有了这个证书体系,操作系统和浏览器都内置了各大 CA 的根证书,上网的时候只要服务器发过来它的证书,就可以验证证书里的签名,顺着证书链(Certificate Chain)一层层地验证,直到找到根证书,就能够确定证书 是可信的,从而里面的公钥也是可信的。
TLS 握手流程
ECDHE 和 RSA 的详细 TLS 握手流程请参考:https://www.processon.com/view/link/62bed0685653bb214fa3d58f
总结
HTTPS:
- HTTPS = HTTP + SSL/TLS,它是运行在 SSL 之上的 HTTP 协议,在 HTTP 层之下,传输层之上添加了一层 SSL/TLS 安全套接层,在 OSI 模型中位于第 5 层会话层
HTTPS的安全性主要体现在三个方面:
- ① 使用加密算法对报文进行加密,黑客截获了也看不懂
- ② HTTPS 使用摘要算法对报文进行完整性确认,黑客一旦修改报文,那么 HTTPS 可以及时发现并做相应处理
- ③ 使用数字签名数字签名,保证黑客不能伪造请求或响应报文
对称加密算法:
- 使用相同的密钥,不同的加密和解密算法,对明文加密,对密文解密
- TLS 中的对称性加密算法有 RC4、DES、3DES、AES、ChaCha20 等,前三种被认为不安全,目前常用的只有AES和ChaCha20
- AES: 高级加密标准(Advanced Encryption Standard),密钥长度可以是128位、192位或256位,安全强度高,性能好。
ChaCha20:Google设计的加密算法,密钥长度固定256位,曾经在移动客户端上比较流行,但ARMv8之后加入了AES硬件优化,所以现在不再具有明显优势,但仍然是一个不错的算法。 - 对称性加密需要解决的问题是密钥交换,其缺点是不能在不安全的网络上传输密钥
非对称加密算法:
- 非对称性加密使用两个不同的不对称的密钥,一个公钥,一个私钥,公钥可以公开给任何人使用,私钥必须严格保密。
- 公钥和私钥具有单向性的特点,公钥加密后只能用私钥来解密,反过来,私钥加密后也只能用公钥来解密。
- 非对称加密算法比较有名的是RSA,它的安全性基于整数分解的数学难题,ECC比RSA安全和性能更好,也是基于数学难题的算法。
- 非对称加密算法虽然解决了密钥交换问题,但是由于是基于复杂的数学难题,运算速度很慢,如果只用非对称加密,实用性为零。
TLS 使用混合加密的方式:
-
先通过非对称加密算法解决密钥交换的问题,用随机数生成用于对称加密算法使用的"会话密钥",然后用公钥加密"会话密钥"发给对方,对方使用私钥解密出"会话密钥",后续双方就可以使用"会话密钥"基于对称加密算法进行通信了。
1)服务端下发公钥(非对称加密算法)
2)客户端使用公钥来加密生成的 [会话密钥] (非对称加密算法)
3)服务端使用私钥来解密客户端发来的 [会话密钥](非对称加密算法)
4)然后客户端和服务端后面使用该 [会话密钥] 来通信(对称加密算法)
这样首先用非对称加密算法解决了密钥交换问题,又利用对称性加密算法提高了性能。
数据完整性:
-
摘要算法:可以理解为一种特殊的压缩算法,或者Hash算法,它可以把任意长度的数据压缩成固定长度且独一无二的摘要字符串,也可以把摘要算法理解成特殊的单向加密算法,它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文。
-
常用的摘要算法有 MD5、SHA-1 但这两个不够安全已经被 TLS 禁用了,目前推荐的是SHA-2,SHA-2是一系列的摘要算法,常用的有 SHA224、SHA256、SHA384,分别能够生成 28、32、48 字节的摘要。
数字签名:
- ① 客户端使用私钥对摘要进行加密生成签名,作为身份认证,将签名和加密的摘要跟报文放一起使用 [会话密钥] 进行加密传输,
- ② 服务端先用 [会话密钥] 解出报文,然后执行摘要算法,对比摘要,校验数据完整性,然后再用客户端公钥对签名进行解密,对比摘要,进行身份认证。
这是客户端向服务端发送加密报文的流程,反过来,服务端向客户端发送加密报文流程与这个类似。
公钥信任问题:
- 由 CA 机构对公钥进行签名认证,生成数字证书, 操作系统和浏览器内置了各大 CA 的根证书,只要服务器发过来它的证书,就可以验证证书里的签名,顺着证书链一层层地验证,直到找到根证书,就能够确定证书是可信的,从而里面的公钥也是可信的。
交互流程图:
补充其他和编码相关的内容:
Base64
将二进制数据转换成由 64 个字符组成的字符串的编码算法。
算法:将原数据每 6 位对应成 Base 64 索引表中的一个字符编排成一个字符串(每个字符 8 位)。
Base64 索引表:
编码示例:把「Man」进行 Base64 编码
编码示例:Base64 的末尾补足
Base64 的用途
- 将二进制数据扩充了储存和传输途径(例如可以把数据保存到文本文件、可以通过聊天对话框或短信形式发送二进制数据、可以在 URL 中加入简单的二进制数据)
- 普通的字符串在经过 Base64 编码后的结果会变得肉眼不可读,因此可以适用于一定条件下的防偷窥(较少用)
Base64 的缺点
- 因为自身的原理(6 位变 8 位),因此每次 Base64 编码之后,数据都会增大约 1/3,所以会影响存储和传输性能。
「Base64 加密图片传输更安全和高效」???
-
不。首先,Base64 并不是加密;另外,Base64 会导致数据增大 1/3,降低网络性能,增大用户流量开销,是画蛇添足的手段。
-
Base64 对图片进行编码的用处在于,有时需要使用文本形式来传输图片。除此之外,完全没必要使用 Base64 对图片进行额外处理。
变种:Base58
- 比特币使用的编码方式,去掉了 Base64 中的数字 "0",字母大写 "O",字母大写"I",和字母小写 "l",以及 "+" 和 "/" 符号,用于比特币地址的表示。
- Base58 对于 Base64 的改动,主要目的在于用户的便捷性。由于去掉了难以区分的字符,使得 Base58 对于「人工抄写」更加方便。另外,去掉了 "+" "/" 号后也让大多数的软件可以方便双击选取。
压缩与解压缩
- 压缩:将数据使用更具有存储优势的编码算法进行编码。
- 解压缩:将压缩数据解码还原成原来的形式,以方便使用。
压缩的目的是减小数据占用的存储空间。
粗暴算法举例
将下面文本内容压缩:
kotlin
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
使用某种算法压缩后的数据为:
kotlin
compress:a:1062;b:10
注:具体的压缩场景有很多,因此压缩算法也会复杂得多,上面只是一个原型算法。
压缩是编码吗?
- 是。所谓编码,即把数据从一种形式转换为另一种形式。压缩过程属于编码过程,解压缩过程属于解码过程。
常见压缩算法:DEFLATE、JPEG、MP3 等。
Hash
把任意数据转换成指定大小范围(通常很小,例如 256 字节以内)的数据。
作用:相当于从数据中提出摘要信息,因此最主要用途是数字指纹。
Hash 的实际用途:
- 唯一性验证 ,例如 Java 中的
hashCode()
方法。(怎么重写 hashCode 方法?把equals()
方法中的每个用于判断相等的变量都放进hashCode()
中,一起生成一个尽量不会碰撞的整数即可) - 数据完整性验证,从网络上下载文件后,通过比对文件的 Hash 值(例如 MD5、SHA1),可以确认下载的文件是否有损坏。如果下载的文件 Hash 值和文件提供方给出的 Hash 值一致,则证明下载的文件是完好无损的。
- 快速查找,如 HashMap
- 隐私保护,当重要数据必须暴露的时候,有事可以选择暴露它的 Hash 值(例如 MD5),以保障原数据的安全。例如网站登录时,可以只保存用户密码的 Hash 值,在每次登录验证时只需要将输入密码的 Hash 值和数据库中保存的 Hash 值作比对就好,网站无需知道用户的密码。这样,当网站数据失窃时,用户不会因为自己的密码被盗导致其他网站的安全也受到威胁。