Skip to content
On this page

加密

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议)

对称加密

对称加密又叫做私钥加密,即信息的发送方和接收方使用 同一个密钥 去加密和解密数据,对称加密的特点是算法公开、加密和解密速度快,适合于对大数据量进行加密。

加密过程如下:明文 + 加密算法 + 私钥 => 密文
解密过程如下:密文 + 解密算法 + 私钥 => 明文

其加密过程中的私钥与解密过程中用到的私钥是同一个密钥,这也是称加密之所以称之为“对称”的原因。

由于对称加密的算法是 公开 的,所以一旦私钥被泄露,那么密文就很容易被破解,所以对称加密的缺点是密钥安全管理困难。

非对称加密单向

由于加密和解密使用了两个不同的密钥,这就是非对称加密“非对称”的原因。非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

用公钥或私钥中的任何一个进行加密,用另一个进行解密
即公钥加密的内容需要对应的私钥解密,私钥加密的内容需要对应的公钥解密

私钥由服务器自己保存,公钥发送给客户端。客户端拿到公钥后可以对请求进行加密后发送给服务端,这时候就算中间被截获,没有私钥也无法解密发送的内容,这样确保了客户端发送到服务端数据的安全。

非对称加密双向

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2;浏览器拥有用于非对称加密的公钥B1、私钥B2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文传输给浏览器。
  3. 浏览器把公钥B1明文传输给服务器。
  4. 之后浏览器向服务器传输的所有东西都用公钥A1加密,服务器收到后用私钥A2解密。由于只有服务器拥有私钥A2进行解密,所以能保证这条数据的安全。
  5. 服务器向浏览器传输的所有东西都用公钥B1加密,浏览器收到后用私钥B2解密。同上也可以保证这条数据的安全。

HTTPS的加密却没使用这种方案

有很大的漏洞,容易被中间人攻击,而且非对称加密算法非常耗时,特别是加密解密一些较大数据的时候有些力不从心

非对称加密 + 对称加密

非对称加密比较耗时但是安全,对称加密比较快但是不安全, 所以我们采用 非对称加密 + 对称加密

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文给传输浏览器。
  3. 🔥浏览器随机生成一个用于 对称加密的密钥X,用公钥A1加密后传给服务器
  4. 🔥服务器拿到后用私钥A2解密得到密钥X。
  5. 这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都用密钥X加密解密即可

利用网站服务器的公钥加密浏览器随机生成的秘钥X,然后浏览器传递给服务器,服务器使用私钥解密 X

此时双方都知道密码 X,以后可以使用 对称加密 传输

HTTPS基本就是采用了这种方案。但还是有漏洞的

🚀中间人攻击

中间人可以在传输过程中伪造服务器

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文传输给浏览器。
  3. 🔥中间人劫持到公钥A1,保存下来,把数据包中的公钥A1替换成自己伪造的公钥B1(它当然也拥有公钥B1对应的私钥B2)
  4. 🔥浏览器随机生成一个用于对称加密的密钥X,用公钥B1(浏览器不知道公钥被替换了)加密后传给服务器。
  5. 中间人劫持后用私钥B2解密得到密钥X,再用公钥A1加密后传给服务器
  6. 服务器拿到后用私钥A2解密得到密钥X

简单来说,就是中间人两头骗

这样在双方都不会发现异常的情况下,中间人得到了对称密钥X。根本原因是浏览器无法确认自己收到的公钥是不是网站自己的。

那么下一步就是解决这个问题:如何证明浏览器收到的公钥一定是该网站的公钥?

数字证书

网站在使用HTTPS前,需要向 “CA机构” 申请颁发一数字证书,数字证书里有证书持有者、证书持有者的公钥等信息。服务器把证书传输给浏览器,浏览器从证书里取公钥就可以了

然而这里又有一个显而易见的问题:证书本身的传输过程中,如何防止被篡改?即如何证明证书本身的真实性?数字证书怎么防伪呢?

数字签名

我们把证书内容生成一份“签名”,比对证书内容和签名是否一致就能察觉是否被篡改。这种技术就叫数字签名。 下图中左侧是数字签名的制作过程,右侧是验证过程

数字签名的制作过程

  1. CA拥有非对称加密的私钥和公钥。
  2. CA对证书明文信息进行hash。
  3. 对hash后的值用私钥加密,得到数字签名

明文和数字签名共同组成了数字证书,这样一份数字证书就可以颁发给网站了

那浏览器拿到服务器传来的数字证书后,如何验证它是不是真的?(有没有被篡改、掉包)

浏览器验证数字签名过程

  1. 拿到证书,得到明文T1,数字签名S1
  2. 用CA机构的公钥对S1解密(由于是浏览器信任的机构,所以浏览器保有它的公钥。详情见下文),得到S2。
  3. 用证书里说明的hash算法对明文T1进行hash得到T2
  4. 比较S2是否等于T2,等于则表明证书可信。

为什么这样可以证明证书可信?

假设中间人篡改了证书的原文,由于他没有CA机构的私钥,所以无法得到此时加密后签名,无法相应地篡改签名。浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。

既然不可能篡改,那如果整个证书被掉包呢?

假设有另一个网站B也拿到了CA机构认证的证书,它想搞垮网站A,想劫持网站A的信息。于是它成为中间人拦截到了A传给浏览器的证书,然后替换成自己的证书,传给浏览器,之后浏览器就会错误地拿到B的证书里的公钥了,会导致上文提到的漏洞。 其实这并不会发生,因为证书里包含了网站A的信息,包括域名,浏览器把证书里的域名与自己请求的域名比对一下就知道有没有被掉包了。

制作数字签名时为什么需要hash一次?

最显然的是性能问题,前面我们已经说了非对称加密效率较差,证书信息一般较长,比较耗时。而hash后得到的是固定长度的信息(比如用md5算法hash后可以得到固定的128位的值),这样加密解密就会快很多。当然除此之外也有安全上的原因。

HTTPS 工作原理

常见的加密算法

对称加密 算法主要有 DES、3DES、AES 等
非对称算法 主要有 RSA、ECC 等
散列算法 主要有 SHA-1、MD5 等。