4

OfferKiller | Https 为什么是安全的?(上)

 3 years ago
source link: https://luyao.tech/archives/https1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

OfferKiller | Https 为什么是安全的?(上)

Https 为什么是安全的? 这可以说是一个高频面试题了。但要完全说明白这个问题,你需要具备一些前置知识。所以在本篇中,暂时不会涉及到 Https 的具体通信流程。

让我们先思考一个问题,如何安全的传输信息

  • 保证传输内容的安全,即不传输明文

  • 防止传输内容被篡改,即可以识别篡改

  • 确认对方真的是对方,即通信双方身份的认证

围绕这几点,我们来看一看常见的加密通信方法以及存在的问题。

最古典的加密

加密技术最初起源于战争。比如著名的 凯撒密码 ,它的原理很简单,如下图所示:

%E5%8F%A4%E5%85%B8%E5%8A%A0%E5%AF%86.png

将明文字母按照一定的 数字 向右平移,得到相应的 密文 。拿上图来说 ,就是把每个字母都往后挪两位,明文 BAG ,经过变换之后就是 DCH 。这样即使信息被拦截,敌人也无法获知真正的信息。

凯撒密码的密钥就是 字母向右移动的位数(上图中的 2 ) 。密钥和明文的重要程度其实是一样的,丢失密钥和丢失明文并没有什么区别。显而易见,这样的密钥强度太低了。即使后来出现了 乱序对应的字母表 ,仍然很容易被破译。

随着科学技术的进步,依托计算机发展的现代密码学提供了经过数学验证的加密方法和(伪) 随机生成的密钥,使得加密一段信息变得快速而安全。

%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

人如其名,对称加密的 加密解密 是对称的,加密密钥和解密密钥是同一个密钥。典型的对称加密算法有 DES 和 AES 。

DES 是 1977 年美国联邦信息处理标准中所采用的一种对称加密,现在已经可以被暴力破解,所以除了考虑到兼容性问题以外,不应该再继续使用 DES 。 此外,还有为了加强 DES 强度的 三重 DES,即将 DES 重复三次。由于其处理速度不高,除了特别重视向下兼容性的情况下,很少被用于新的用途。

现在使用最为广泛的对称加密是在全世界范围内公开选拔出来的 AES 加密。经过全世界密码学家的共同论证,其安全性是毋庸置疑的。那么,我们直接使用 AES 加密通信内容不就可以了吗?

对称加密的一个致命问题就是 密钥的传输问题 。由于加解密过程都使用同一个密钥,所以通信一方必须将密钥首先传给另一方,双方才能正常的进行通信。可是,如果有可靠的方法来传输密钥,那么用同样的方法就可以安全的传递通信内容。使用对称加密,只是把 如何安全的传输通信内容 转化为了 如何安全的传输密钥 ,本质上并没有解决任何问题。

那么,如何解决密钥传输问题呢 ?

非对称加密

%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

要解决密钥传输问题,我们可以 “不传输” 密钥。

非对称加密通过公私钥完美解决了密钥传输问题。发送方使用公钥进行加密,接收方使用私钥进行解密。公钥可以公开存在于网络中,私钥由接收方保管,不能泄露。私钥是通信安全的重要保障,一旦泄露,加密通信都会被破解。我们最常使用的非对称加密是 RSA 。

看似完美解决密钥传输问题的非对称加密,仍然存在明显的问题。

非对称加密的性能只有对称加密的几百分之一。在浏览器或者即时聊天的场景下,这个速度可能是用户所接受不了的。所以真正使用时,往往是对称加密和非对称加密结合使用,如下图所示。

OfferKiller | Https 为什么是安全的?(上)

Https 为什么是安全的? 这可以说是一个高频面试题了。但要完全说明白这个问题,你需要具备一些前置知识。所以在本篇中,暂时不会涉及到 Https 的具体通信流程。

让我们先思考一个问题,如何安全的传输信息

  • 保证传输内容的安全,即不传输明文

  • 防止传输内容被篡改,即可以识别篡改

  • 确认对方真的是对方,即通信双方身份的认证

围绕这几点,我们来看一看常见的加密通信方法以及存在的问题。

最古典的加密

加密技术最初起源于战争。比如著名的 凯撒密码 ,它的原理很简单,如下图所示:

2068242063

将明文字母按照一定的 数字 向右平移,得到相应的 密文 。拿上图来说 ,就是把每个字母都往后挪两位,明文 BAG ,经过变换之后就是 DCH 。这样即使信息被拦截,敌人也无法获知真正的信息。

凯撒密码的密钥就是 字母向右移动的位数(上图中的 2 ) 。密钥和明文的重要程度其实是一样的,丢失密钥和丢失明文并没有什么区别。显而易见,这样的密钥强度太低了。即使后来出现了 乱序对应的字母表 ,仍然很容易被破译。

随着科学技术的进步,依托计算机发展的现代密码学提供了经过数学验证的加密方法和(伪) 随机生成的密钥,使得加密一段信息变得快速而安全。

%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

人如其名,对称加密的 加密解密 是对称的,加密密钥和解密密钥是同一个密钥。典型的对称加密算法有 DES 和 AES 。

DES 是 1977 年美国联邦信息处理标准中所采用的一种对称加密,现在已经可以被暴力破解,所以除了考虑到兼容性问题以外,不应该再继续使用 DES 。 此外,还有为了加强 DES 强度的 三重 DES,即将 DES 重复三次。由于其处理速度不高,除了特别重视向下兼容性的情况下,很少被用于新的用途。

现在使用最为广泛的对称加密是在全世界范围内公开选拔出来的 AES 加密。经过全世界密码学家的共同论证,其安全性是毋庸置疑的。那么,我们直接使用 AES 加密通信内容不就可以了吗?

对称加密的一个致命问题就是 密钥的传输问题 。由于加解密过程都使用同一个密钥,所以通信一方必须将密钥首先传给另一方,双方才能正常的进行通信。可是,如果有可靠的方法来传输密钥,那么用同样的方法就可以安全的传递通信内容。使用对称加密,只是把 如何安全的传输通信内容 转化为了 如何安全的传输密钥 ,本质上并没有解决任何问题。

那么,如何解决密钥传输问题呢 ?

非对称加密

%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

要解决密钥传输问题,我们可以 “不传输” 密钥。

非对称加密通过公私钥完美解决了密钥传输问题。发送方使用公钥进行加密,接收方使用私钥进行解密。公钥可以公开存在于网络中,私钥由接收方保管,不能泄露。私钥是通信安全的重要保障,一旦泄露,加密通信都会被破解。我们最常使用的非对称加密是 RSA 。

看似完美解决密钥传输问题的非对称加密,仍然存在明显的问题。

非对称加密的性能只有对称加密的几百分之一。在浏览器或者即时聊天的场景下,这个速度可能是用户所接受不了的。所以真正使用时,往往是对称加密和非对称加密结合使用,如下图所示。

%E6%B7%B7%E5%90%88%E5%8A%A0%E5%AF%86%E7%B3%BB%E7%BB%9F.png

用非对称加密来保护对称加密的密钥 ,既解决了对称加密的密钥传输问题,又解决了非对称加密速度慢的问题。

现在已经解决了通信内容的加密问题。即使通信内容和加密过的对称密钥被拦截,由于没有私钥,也无法解密查看。那么,现在的通信流程是安全的吗?并不是,目前还有一个核心问题,在缤纷繁杂的互联网上,对方真的是对方吗? 就好比和你语音聊天的萌妹子,其实可能是个抠脚大汉。中间人攻击 就是典型的例子,下面这张图描述了中间人攻击的基本流程。

%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB.png

中间人通过特定技术手段拦截了双方的通信链路,然后调包了发送给发送者的公钥,神不知鬼不觉的拦截并伪造了通信内容。发送方无法确定收到的公钥到底是不是接收方的,接收方也无法识别到消息被篡改。

防止通信内容被篡改认证对方身份 的问题上,此时依然无法解决。

聊到防止通信内容被篡改,很容易想到哈希算法。输入任意长度的内容,计算出固定长度的哈希值 ,也可以叫 散列值消息摘要。哈希算法并不是加密算法,它只是用来校验消息的完整性,例如在官网上下载软件,通常会提供哈希值供用户比对。

常见的 MD4/MD5,包括 SHA1,都已经不再安全,不建议使用。目前推荐使用 SHA2/SHA3。

其实哈希算法很少被直接单独使用在加密通信中,因为它仍然无法解决上一节的问题。如果发送方把消息和消息的哈希值一起发送过来,中间人要做的无非就是把哈希值也替换了,仍然无济于事。这时候就得把哈希算法揉进既有体系中使用。

消息验证码

消息验证码其实和哈希很像,它也是输入任意长度的内容,计算出固定长度的验证码。但是这个计算过程需要一个发送者和接收者共享的密钥。消息认证码是一种和密钥相关联的哈希算法

%E6%B6%88%E6%81%AF%E8%AE%A4%E8%AF%81%E7%A0%81.png

发送者在发送数据的同时,使用共享密钥计算出消息验证码,和数据一起发送。接收方接收到数据后,使用共享密钥计算出消息认证码,再和发送方发送过来的消息验证码进行比对。比较常见的消息认证码有 HMAC 算法。

由于共享密钥只有通信双方才有,所以即使中间人拦截并修改了消息,接收方通过计算消息认证码也可以识别到篡改。

什么?共享密钥?共享密钥怎么安全传输并且不被中间人拦截?没错,消息认证码同样存在密钥传输问题。可以通过引入非对称加密来解决。

同时,由于使用了共享密钥,消息认证码存在 对第三方证明防止否认 的问题。因为通信双方都有共享密钥,所以无法判断某一条消息究竟是谁发送的,也就无法对第三方证明和防止否认。比如类似 “我欠你 500W” 的这种消息,发送方可以说是接收方发给我的,接收方也可以说是发送方发给我的。

为了解决这个问题,数字签名出场了。

数字签名听起来高大上,其实它的原理很简单。我先把 非对称加密 的图搬过来,

%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

非对称加密是发送方持有公钥,接收方持有私钥。公钥可以直接在网络中传送,私钥仅有接收方才有。

现在假设这样一种场景,把上图中的流程倒过来, 接收方给发送方发送消息,接收方使用私钥加密消息,发送方接收到消息后用公钥进行解密。由于私钥只有接收方持有,所以一定可以确定收到的消息来自接收方。这是不是就做到了 认证对方身份,防止否认,向第三方证明

用私钥加密,用公钥解密,这其实就是数字签名。只不过在数字签名中,用私钥加密的过程叫做 生成签名,用公钥解密的过程叫做 验证签名 ,和非对称加密正好反了过来。来个图对比一下。

%E9%AA%8C%E7%AD%BE.png

这只是一个简单的示意图。在真正的使用过程中,并不会用私钥直接对原数据进行签名,而是先对原数据做哈希,再对哈希值签名,这样可以减少数据传输量。再来个图:

%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D.png

图中直接发送的原数据,但这个原数据并不是指明文。实际使用中,可以配合非对称加密保护对称加密密钥的方式对原数据进行保护。

数字签名可谓是功能齐全,再来回顾一下文章开头提到的安全传输的几点要求:

  • 保证传输内容的安全,即不传输明文
  • 防止传输内容被篡改,即可以识别篡改
  • 确认对方真的是对方,即对方身份的认证

数字签名已经完全符合这几点要求。但......

无论是单独使用非对称加密,还是数字签名,只要是涉及到公钥,都会存在一个问题。公钥是公开存在于网络中的,如何保证用于非对称加密,或者数字签名验签的公钥不是伪造的?

这就依赖于本文最后一节内容 —— 证书。

证书要解决的问题是 公钥的合法性 。也就是说,公钥要安全的从一方传给另一方,不能被掉包,不能被篡改。

等等,这不就是这篇文章的主题,如何安全的传输信息 吗?现在要传输的信息就是公钥。毫无疑问,上面讨论过的方法都可以在这里应用,数字签名就是一个好选择。

没错,证书就是对公钥进行数字签名

对于公钥的发送者来说,公钥就是一个普通的待传输的数据,下面用 待传输公钥 表示,以防混淆。发送者生成自己的一对公私钥(公钥A 和 私钥 A),用 私钥 A待发送公钥 进行数字签名,表示这个公钥的确来自于我。这样接收到公钥的第三方(浏览器等) 就可以拿发送者的 公钥 A 进行验证签名,校验公钥是否合法。

不知道有没有把你看晕。如果没有的话,你应该很容易发现其中的逻辑 Bug 。本身就是为了验证 待传输公钥 的合法性,却因此又引入了 公钥 A 。那么 公钥 A 的合法性又如何保证呢?再引入一对公私钥吗?这样无限套娃,依旧无法解决问题的实质。但是又能有什么办法呢?

对,就是没有办法,事实上也就是这么套娃的。我们以 Github 为例,点击 Chrome 网址左边的小锁,就可以查看证书信息。

github_ca.png

在证书路径中,可以看到有三层。这其实就是一个完整的证书链。github.com 证书的安全性由上一层 DigiCert SHA2 High Assurance Server CA 来保证,DigiCert SHA2 High Assurance Server CA 的安全性由再上一层的 DigiCertA 来保证。而这个 DigiCertA 的安全性则由它自己保证,也就是说我们必须无条件相信它,否则套娃永远没有尽头。

这个 DigiCertA 就叫做 根证书 ,它内置在我们的计算机系统或者浏览器中。正是由这些根证书,来一级一级向下保证,直到保证到某次通信中使用到的证书是安全的。除了内置的根证书以外,用户也可以安装自己信任的证书。

证书中除了 公钥签名 之外,还包含了其他一些附加信息。大部分证书都遵循 X.509 标准规范,这里就不详细描述了,感兴趣的可以自行查阅。我们在 Chrome 上简单看下基本的证书信息。

ca_info.png

写到这里,安全通信的大部分问题都已经被解决了。我们再来回顾一下。

通信内容一般直接使用 对称加密 ,但对称加密存在 密钥传输问题

非对称加密 性能只有对称加密的几百分之一,不会用来直接加密通信内容。但是可以配合对称加密,用非对称加密保护对称加密的密钥,以解决密钥传输问题。

哈希算法 主要用于信息的完整性。

消息认证码 是一种和密钥相关联的哈希算法。它通过共享密钥,不仅能确保信息的完整性,还可以提供认证功能,确保消息来自期望的通信对象,但同样也存在密钥传输问题。

数字签名 技术使用私钥签名,公钥验证签名,同时兼具确认信息完整性,确认通信对方身份,防止否认的功能。

证书 的目的是确保公钥的合法性,它的本质就是为公钥加上数字签名。它的安全性由证书链顶端的根证书来保证。

了解了这些常用技术之后,Https 无非就是这些技术的组合罢了。下篇中,我们就来探究 Https 的具体通信流程以及这些加密技术的应用。

想了解 OfferKiller ,戳 这里
%E6%B7%B7%E5%90%88%E5%8A%A0%E5%AF%86%E7%B3%BB%E7%BB%9F.png

用非对称加密来保护对称加密的密钥 ,既解决了对称加密的密钥传输问题,又解决了非对称加密速度慢的问题。

现在已经解决了通信内容的加密问题。即使通信内容和加密过的对称密钥被拦截,由于没有私钥,也无法解密查看。那么,现在的通信流程是安全的吗?并不是,目前还有一个核心问题,在缤纷繁杂的互联网上,对方真的是对方吗? 就好比和你语音聊天的萌妹子,其实可能是个抠脚大汉。中间人攻击 就是典型的例子,下面这张图描述了中间人攻击的基本流程。

%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB.png

中间人通过特定技术手段拦截了双方的通信链路,然后调包了发送给发送者的公钥,神不知鬼不觉的拦截并伪造了通信内容。发送方无法确定收到的公钥到底是不是接收方的,接收方也无法识别到消息被篡改。

防止通信内容被篡改认证对方身份 的问题上,此时依然无法解决。

聊到防止通信内容被篡改,很容易想到哈希算法。输入任意长度的内容,计算出固定长度的哈希值 ,也可以叫 散列值消息摘要。哈希算法并不是加密算法,它只是用来校验消息的完整性,例如在官网上下载软件,通常会提供哈希值供用户比对。

常见的 MD4/MD5,包括 SHA1,都已经不再安全,不建议使用。目前推荐使用 SHA2/SHA3。

其实哈希算法很少被直接单独使用在加密通信中,因为它仍然无法解决上一节的问题。如果发送方把消息和消息的哈希值一起发送过来,中间人要做的无非就是把哈希值也替换了,仍然无济于事。这时候就得把哈希算法揉进既有体系中使用。

消息验证码

消息验证码其实和哈希很像,它也是输入任意长度的内容,计算出固定长度的验证码。但是这个计算过程需要一个发送者和接收者共享的密钥。消息认证码是一种和密钥相关联的哈希算法

%E6%B6%88%E6%81%AF%E8%AE%A4%E8%AF%81%E7%A0%81.png

发送者在发送数据的同时,使用共享密钥计算出消息验证码,和数据一起发送。接收方接收到数据后,使用共享密钥计算出消息认证码,再和发送方发送过来的消息验证码进行比对。比较常见的消息认证码有 HMAC 算法。

由于共享密钥只有通信双方才有,所以即使中间人拦截并修改了消息,接收方通过计算消息认证码也可以识别到篡改。

什么?共享密钥?共享密钥怎么安全传输并且不被中间人拦截?没错,消息认证码同样存在密钥传输问题。可以通过引入非对称加密来解决。

同时,由于使用了共享密钥,消息认证码存在 对第三方证明防止否认 的问题。因为通信双方都有共享密钥,所以无法判断某一条消息究竟是谁发送的,也就无法对第三方证明和防止否认。比如类似 “我欠你 500W” 的这种消息,发送方可以说是接收方发给我的,接收方也可以说是发送方发给我的。

为了解决这个问题,数字签名出场了。

数字签名听起来高大上,其实它的原理很简单。我先把 非对称加密 的图搬过来,

%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.png

非对称加密是发送方持有公钥,接收方持有私钥。公钥可以直接在网络中传送,私钥仅有接收方才有。

现在假设这样一种场景,把上图中的流程倒过来, 接收方给发送方发送消息,接收方使用私钥加密消息,发送方接收到消息后用公钥进行解密。由于私钥只有接收方持有,所以一定可以确定收到的消息来自接收方。这是不是就做到了 认证对方身份,防止否认,向第三方证明

用私钥加密,用公钥解密,这其实就是数字签名。只不过在数字签名中,用私钥加密的过程叫做 生成签名,用公钥解密的过程叫做 验证签名 ,和非对称加密正好反了过来。来个图对比一下。

%E9%AA%8C%E7%AD%BE.png

这只是一个简单的示意图。在真正的使用过程中,并不会用私钥直接对原数据进行签名,而是先对原数据做哈希,再对哈希值签名,这样可以减少数据传输量。再来个图:

%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D.png

图中直接发送的原数据,但这个原数据并不是指明文。实际使用中,可以配合非对称加密保护对称加密密钥的方式对原数据进行保护。

数字签名可谓是功能齐全,再来回顾一下文章开头提到的安全传输的几点要求:

  • 保证传输内容的安全,即不传输明文
  • 防止传输内容被篡改,即可以识别篡改
  • 确认对方真的是对方,即对方身份的认证

数字签名已经完全符合这几点要求。但......

无论是单独使用非对称加密,还是数字签名,只要是涉及到公钥,都会存在一个问题。公钥是公开存在于网络中的,如何保证用于非对称加密,或者数字签名验签的公钥不是伪造的?

这就依赖于本文最后一节内容 —— 证书。

证书要解决的问题是 公钥的合法性 。也就是说,公钥要安全的从一方传给另一方,不能被掉包,不能被篡改。

等等,这不就是这篇文章的主题,如何安全的传输信息 吗?现在要传输的信息就是公钥。毫无疑问,上面讨论过的方法都可以在这里应用,数字签名就是一个好选择。

没错,证书就是对公钥进行数字签名

对于公钥的发送者来说,公钥就是一个普通的待传输的数据,下面用 待传输公钥 表示,以防混淆。发送者生成自己的一对公私钥(公钥A 和 私钥 A),用 私钥 A待发送公钥 进行数字签名,表示这个公钥的确来自于我。这样接收到公钥的第三方(浏览器等) 就可以拿发送者的 公钥 A 进行验证签名,校验公钥是否合法。

不知道有没有把你看晕。如果没有的话,你应该很容易发现其中的逻辑 Bug 。本身就是为了验证 待传输公钥 的合法性,却因此又引入了 公钥 A 。那么 公钥 A 的合法性又如何保证呢?再引入一对公私钥吗?这样无限套娃,依旧无法解决问题的实质。但是又能有什么办法呢?

对,就是没有办法,事实上也就是这么套娃的。我们以 Github 为例,点击 Chrome 网址左边的小锁,就可以查看证书信息。

github_ca.png

在证书路径中,可以看到有三层。这其实就是一个完整的证书链。github.com 证书的安全性由上一层 DigiCert SHA2 High Assurance Server CA 来保证,DigiCert SHA2 High Assurance Server CA 的安全性由再上一层的 DigiCertA 来保证。而这个 DigiCertA 的安全性则由它自己保证,也就是说我们必须无条件相信它,否则套娃永远没有尽头。

这个 DigiCertA 就叫做 根证书 ,它内置在我们的计算机系统或者浏览器中。正是由这些根证书,来一级一级向下保证,直到保证到某次通信中使用到的证书是安全的。除了内置的根证书以外,用户也可以安装自己信任的证书。

证书中除了 公钥签名 之外,还包含了其他一些附加信息。大部分证书都遵循 X.509 标准规范,这里就不详细描述了,感兴趣的可以自行查阅。我们在 Chrome 上简单看下基本的证书信息。

ca_info.png

写到这里,安全通信的大部分问题都已经被解决了。我们再来回顾一下。

通信内容一般直接使用 对称加密 ,但对称加密存在 密钥传输问题

非对称加密 性能只有对称加密的几百分之一,不会用来直接加密通信内容。但是可以配合对称加密,用非对称加密保护对称加密的密钥,以解决密钥传输问题。

哈希算法 主要用于信息的完整性。

消息认证码 是一种和密钥相关联的哈希算法。它通过共享密钥,不仅能确保信息的完整性,还可以提供认证功能,确保消息来自期望的通信对象,但同样也存在密钥传输问题。

数字签名 技术使用私钥签名,公钥验证签名,同时兼具确认信息完整性,确认通信对方身份,防止否认的功能。

证书 的目的是确保公钥的合法性,它的本质就是为公钥加上数字签名。它的安全性由证书链顶端的根证书来保证。

了解了这些常用技术之后,Https 无非就是这些技术的组合罢了。下篇中,我们就来探究 Https 的具体通信流程以及这些加密技术的应用。

想了解 OfferKiller ,戳 这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK