HTTPS

HTTPS

学习时间:2020.06.14

学习章节:透视HTTP协议

一、主要知识点

  • 什么是 HTTPS
  • 什么是 SSL/TLS
  • 什么是加密、摘要算法
  • 数字签名与证书
  • TLS 连接过程

1. HTTPS

1.1 为什么要有 HTTPS

因为 HTTP 天生 “明文” 的特点,传输过程完全透明,任何人都可以在链路中截获或者修改 请求/响应报文 ,数据不具有可信性。各种应用场景暴露的问题:

  • 网络购物、网上银行、证券交易等需要高度信任的应用场景没有得到安全保护。
  • 新闻、视频、搜索等网站,容易遭到 “流量劫持” 攻击,在页面嵌入广告,或者分流用户。
  • 普通网民的上网记录被截获,黑客可以伪装成银行网站,盗取用户信息,威胁客户人身和财产安全。

1.2 什么是 HTTPS

HTTPS 的协议名为 “https“ 默认端口为 443,其他的 请求-应答模式、报文结构、请求方法、URI、头字段、连接管理等都完全沿用 HTTP,没有其他新的东西。

它为 HTTP 添加了四大安全特性:

  • 机密性:对数据保密,只能由可信的人访问。
  • 完整性:数据传输过程没有被篡改,完完整整的保持着原状。
  • 身份认证:确认对方的真实身份,保证消息只能发送给可信的人。
  • 不可否认:不能否认已经发生过的行为。

在 HTTPS 中,它把 HTTP 下层的传输协议由 TCP/IP 换成了 SSL/TLS,由 “HTTP over TCP/IP” 变成了 “HTTP over SSL/TLS”,让 HTTP 运行在安全的 SSL/TLS 协议上。这就是 HTTPS 中的 “S” 的意思。

2. SSL/TLS

SSL(Secure Sockets Layer)安全套接层,它在 1999 年被改名为 TLS(Transport Layer Security)传输层安全。它由 记录协议、握手协议、警告协议、更新密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等技术。

3. 什么是加密

3.1 加密

加密就是把消息用某种方式转换成谁也看不懂的乱码,只有掌握特殊 “钥匙” 的人才能再转换出原始文本。钥匙叫做密钥,加密前的消息叫做明文,加密后的乱码叫密文,使用密钥还原明文的过程叫解密,加密解密的过程叫做加密算法

由于 HTTPS、TLS 都运行在计算机上,密钥是一长串的数字,但约定俗成的度量单位是位(bit),而不是字节(byte)。比如:密钥长度是 128,就是16字节的二进制串,密钥长度1024,就是128字节的二进制串。

加密可以分为两大类:对称加密和非对称加密。

3.2 对称加密

对称加密:就是指加密和解密时使用的密钥都是同一个,是对称的,只要保证了密钥的安全,那整个通信过程就可以说具有了机密性。

WX20200615-224004@2x

TLS 里有很多的对称加密算法可供选择,比如 RC4、DES、3DES、AES、ChaCha20等,前三种算法被认为是不安全的,通常禁止使用,目前常用的只有AES 和 ChaCha20。

加密分组模式:对称算法还有一个 分组模式 的概念,它可以让算法用固定长度的密钥加密任意长度的明文。最早有ECB、CBC、CFB、OFB几种分组模式,但是都被发现有安全漏洞,所以不怎么用了。现在最新的分组模式被称为AEAD(Authenticated Encryption with Associated Data),加密的同事增加了认证的功能,常用的是 GCM、CCM 和 Poly1305.

上面这些组合起来就得到 TLS 密码套件中定义的对称加密算法。

3.2.1 AES算法原理

3.3 非对称加密

上面的对称加密看起来好像实现了机密性,但是其中一个很大的问题就是如何把密钥安全的传递给对方,术语叫做密钥交换

对称加密算法中只要持有密钥就可以解密,如果你和网站约定的密钥在传输中被窃取。通信过程就无机密性了。所以出现了非对称加密。

非对称加密有两个密钥,一个叫公钥,一个叫私钥。两个密钥是不同的,公钥可以给任何人使用,而私钥必须严格保密。公钥和私钥都是单向性的,虽然可以用来加密解密,但是公钥加只能私钥解,私钥加只能公钥解。

非对称加密可以用于解决以上 密钥交换 的问题。网站保管私钥,在网上分发公钥。公钥对原文加密,传输加密后的密文给网站,网站使用私钥解密出密文得到原文。黑客没有私钥,所以解不出密文。

WX20200615-235954@2x

非对称加密的算法设计比对称算法难得多,在 TLS 里只有很少几种,比如 DH、DSA、RSA、ECC 等。RSA 的安全性基于 “整数分解” 的数学难题,使用两个超大质数的乘积作为生成密钥的材料。想要从公钥推算出私钥是非常困难的。

素数和质数是没有区别的。质数(又称素数),是指在大于1的自然数中,除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数)。

3.3.1 RSA 算法

  1. 随机选取两个质数p和q
  2. 计算 n = pq
  3. 计算 φ(n) = (p-1)(q-1)
  4. 找一个与φ(n)互质的小奇数e,互质是指两个数的公约数只有1
  5. 对模φ(n),计算e的乘法逆元d,即找到一个d,使下列等式成立:(e*d) mod φ(n) = 1
  6. 得到公钥:(e, n),私钥: (d, n)
  7. 加密过程:c = (m^e) mod n, (c为加密后的密文,m为原文)
  8. 解密过程:m = (c^d) mod n

示例:

  1. 随便选两个质数23和61
  2. 计算 n = 23 * 61 = 1403
  3. 计算 φ(n) = (23-1) (61-1) = 22 60 = 1320
  4. 找一个与φ(n)互质的小奇数e,我们选7
  5. 计算乘法逆元d,我这里算好的是 d =943。对乘法逆元感兴趣的朋友可以网上搜搜怎么算,因为不是本文主题,我就不展开了。
  6. 得到公钥(7, 1403),私钥(943, 1403)
  7. 我们用公钥随便加密一个5试试,加密 c = (m^e) mod n = (5^7) % 1403 = 78125 % 1403 = 960
  8. 私钥解密: m = (c^d) mod n = (960^943) % 1403 = 5,(960^943)这个数字超级大,一般计算器算不出来,JS计算更不行,我是用这个网站算的:https://defuse.ca/big-number-calculator.htm
  9. 再试试私钥加密:c = (m^d) mod n = (5^943) % 1403 = 283
  10. 公钥解密: m = (c^e) mod n = (283 ^ 7) % 1403 = 5

3.4 混合加密

非对称加密虽然没有了 “密钥交换” 中存在的问题,但是它们都是因为基于复杂的数学难题,所以运算速度很慢。所以出现了混合加密的方式,也就是两种加密方式之间的取长补短。既能高效加密,又能安全的密钥交换。

这就是现在 TLS 里使用的混合加密方式,在通信刚开始的时候使用非对称加密解决密钥交换的问题。然后随机产品对称算法的会话密钥,再用公钥加密得到密文,对方拿到密文之后使用私钥解密,取出会话密钥,之后就都使用对称加密了。

WX20200616-002946@2x

混合加密解决了对称加密算法的密钥交换问题,也解决了非对称加密算法的性能问题。完美的实现了机密性。

4. 数字签名与证书

通过上面的混合加密,黑客拿不到密钥,无法破解密文,但是可以通过收集足够多的密文,尝试修改、重组后发送给网站。因为没有完整性保证,服务器只能照单全收。然后黑客通过服务器的响应获取线索,最终破解出明文。

还有黑客可以伪造身份发布公钥,如果你拿到假的公钥,混合加密就失效了。你以为是在和真实的网站通信,实际上确实和黑客通信。身份信息也就泄漏了。因为不具备身份认证的特性

所以机密性的基础上还得加上完整性身份认证等特性、才能实现真正的安全。

4.1 摘要算法

实现完整性的手段主要是摘要算法,它能够把任意长度的数据压缩成固定长度、而且独一无二的摘要字符串,就好像是给这段数据生成一个数字指纹。(摘要算法加密后的数据无法解密,不能从摘要逆推原文)。

WX20200616-130637@2x

摘要算法实际上是把数据从一个 大空间 映射到 小空间。所以就存在冲突(也叫碰撞)的可能性。因为摘要算法对输入具有单向性雪崩效应,输入微小的不同导致输出的剧烈变化,所以也被 TLS 用来生成伪随机数(PRF,pseudo random function)。

常用的摘要算法有:MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1),它们就是最常用的两个摘要算法,能够生成 16 字节和 20 字节长度的数字摘要。但是这两个算法的安全强度比较低,不够安全,在 TLS 里已经被禁止使用了。目前 TLS 推荐使用的是 SHA-1 的后继者: SHA-2。

4.1.1 那么如何通过摘要算法保证数据的完整性

假设你发送了一条消息,“转账1000元”,再加上 SHA-2 的摘要。两个一起传输给网站,网站拿到之后也计算一下得到消息的摘要。然后比对一下两份摘要是否一致,就能知道消息是否完整可信,有没有被修改。

不过摘要算法不具有机密性,如果明文传输,黑客可以修改消息后把摘要也一起改了。网站还是鉴别不出完整性。

所以,真正的完整性必须要建立在机密性之上,在混合加密系统里用会话秘钥加密消息和摘要,黑客就无法得知明文,也就没办法动手脚了。

WX20200616-203436@2x

4.2 数字签名

加密算法结合摘要算法,我们的通信过程可以说是比较安全了,但这里还有个漏洞,就是通信的两个端点。黑客可以伪装成网站来窃取信息。他也可以伪装成你,向网站发送支付、转账等消息,网站没有办法验证你的身份,钱就被盗走了。

现实生活中,解决身份认证的手段是签名和印章,只要在纸上写下签名或者盖个章,就能够证明这份文件确实是本人而不是其他人发出的。而 TLS 里的非对称加密的 私钥 就像这个印章。使用私钥加上摘要算法,就能够实现 数字签名,同时实现 身份认证不可否认

数字签名的原理就是把公私钥的用法反过来,之前公钥加密、私钥解密。现在是私钥加密、公钥解密。但是因为非对称加密效率太低,所以私钥只加密原文的摘要,这样子运算量小很多。得到的数字签名也很小,方便保管和传输。

数字签名公钥 一样完全公开,任何人都可以获取,但这个签名只有私钥对应的公钥才能解开,拿到 摘要后,再对比原文验证完整性,就可以像签署文件一样证明消息确实是你发的了。

WX20200618-000454@2x

这两个行为也有专业术语,叫 签名验签

只要你和网站互相交换公钥,就可以用 签名 和 验签 来确认消息的真实性,因为私钥保密,黑客不能伪造签名,就能够保证通信双方的身份。

比如你用自己的私钥签名一个消息,“我是小秦”,网站收到你的公钥之后验签确认身份。然后网站也用它的私钥签名一个消息 “我是网站”,发送给你。你收到以后拿它的公钥验证一下,也没有问题。这样你和网站都知道对方没问题了。时候就可以用混合加密进行安全通信了。

4.3 数字证书与 CA

到现在综合使用对称、非对称加密和摘要算法之后,还存在一个问题,就是 公钥的信任问题,上面说的签名与验签只能保证通信双方的身份没问题。但是却不能知道对方是什么身份(是真实的网站还是黑客呢)。因为谁都可以发布公钥,这里还缺少防止黑客伪造公钥的手段。也就是说怎么判断 公钥就是小秦的或者是网站的呢

CA(Certificate Authority,证书认证机构),它像是网络世界的公安局、公正中心,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。

CA 对公钥的签名认证也是有格式的,不是简单的把公钥绑定在持有者身份上就完事了,还要包含序列号、用途、颁发者、有效时间等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成 数字证书

操作系统和浏览器中都内置了各大 CA 的根证书,上网的时候只要服务器发过来它的证书,就可以验证证书是否可信。从而验证里面的公钥也是否是可信的了。

五、TLS 连接过程

5.1 TLS 协议组成

记录协议(Record Protocol):规定了 TLS 收发数据的基本单位:记录(record),它有点像是 TCP 里的 segment,所有的其他自协议都需要通过记录协议发出。但多个记录数据可以再一个 TCP 包里一次性发出,也冰不需要像 TCP 那样返回 ACK。

警报协议(Alert Protocol):的职责是向对方发出警报信息,有点像是 HTTP 协议里的状态 码。比如,protocol_version 就是不支持旧版本,bad_certificate 就是证书有问题,收到 警报后另一方可以选择继续,也可以立即终止连接。

握手协议(Handshake Protocol):是 TLS 里最复杂的子协议,要比 TCP 的 SYN/ACK 复 杂的多,浏览器和服务器会在握手过程中协商 TLS 版本号、随机数、密码套件等信息,然 后交换证书和密钥参数,最终双方协商得到会话密钥,用于后续的混合加密系统。

变更密码规范协议(Change Cipher Spec Protocol):它非常简单,就是一 个“通知”,告诉对方,后续的数据都将使用加密保护。那么反过来,在它之前,数据都是 明文的。

TLS 握手简要过程:

WX20200618-121716@2x

TLS 握手的前几个消息都是明文的,在 Change Copher Spec 之后数据都是密文的。

5.2 详细握手过程

WechatIMG906

  1. 在浏览器输入 https 开头的 URI,并且回车之后,浏览器从 URI 里提取出协议名和域名,因为协议名是 https ,所以浏览器就知道了端口号默认是 443,它在用 DNS 解析域名,得到目标的 IP 地址,然后就可以使用三次握手与网站建立 TCP 连接
  2. 建立 TCP 连接后,浏览器首先发送一个 Client Hello 的消息,里面有客户端的版本号、支持的密码套件、还有一个随机数WX20200619-092539@2x
  3. 服务器收到 Client Hello 后,会返回一个 Server Hello 的消息,把版本号对一下,也给出一个随机数、从客户端列表里选一个作为本地通信使用的密码套件(比如椭圆曲线加 RSA、AES、SHA384)WX20200619-093020@2x然后服务器为了证明自己的身份,就把证书也发给了客户端(Server Cenrtificate),接下来服务器因为选择了ECDHE 算法,所以它会在证书后发送 Server Key Exchange 消息,里面是 椭圆曲线的公钥(Server Params)用来实现密钥交换算法,再加上自己的私钥签名认证。之后就是 Server Hello Done 的消息,服务器说 我的信息就是这些,打招呼完毕。WX20200619-093057@2x
  4. 客户端拿到服务器的证书,需要验证证书是不是真实有效的。验证完之后把证书里携带的(服务器的)公钥拿出来验证签名,就确认了服务器的身份。
  5. 客户端按照密码套件的要求,也生成一个 椭圆曲线的公钥(client params),用 Client Key Exchange 消息发给服务器。WX20200619-120334@2x

  6. 客户端和服务器都拥有了密钥交换算法的两个参数 Client ParamsServer Params,之后通过 ECDHE 算法得到一个新的随机数 “Pre-Master“,这个算法保证了黑客截获之前的参数,也绝对算不出这个随机数。

  7. 现在客户端和服务端一共拥有三个随机数:Client Radndom、Server Random 和 Pre-Master。用这三个作为原始材料,就可以生成用于加密会话的主密钥,叫 Master Secret。因为黑客拿到不到 Pre-Master 所以得不到主密钥。
  8. 主密钥有 48 字节,但它也不是最终用于通信的会话密钥,还会拓展出更多的密钥,比如客户端发送用的会话密钥(client_write_key),服务器发送用的会话密钥(serve_write_key)等等,避免只用一个密钥带来的安全隐患。
  9. 有了主密钥和会话密钥,握手就快结束了。客户端发一个 Change Cipher Spec ,然后再发一个 Finished 消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证
  10. 服务器也同样的炒作,发 Change Cipher Spec 和 Finished 消息,双方都验证加密解密ok。握手就结束了,后面就开始收发被加密的 HTTP 请求和响应。