Https 为什么是安全的? 这可以说是一个高频面试题了。但要完全说明白这个问题,你需要具备一些前置知识。所以在本篇中,暂时不会涉及到 Https 的具体通信流程。
让我们先思考一个问题,如何安全的传输信息 ?
- 保证传输内容的安全,即不传输明文
- 防止传输内容被篡改,即可以识别篡改
- 确认对方真的是对方,即通信双方身份的认证
围绕这几点,我们来看一看常见的加密通信方法以及存在的问题。
最古典的加密
加密技术最初起源于战争。比如著名的 凯撒密码 ,它的原理很简单,如下图所示:
将明文字母按照一定的 数字 向右平移,得到相应的 密文 。拿上图来说 ,就是把每个字母都往后挪两位,明文 BAG ,经过变换之后就是 DCH 。这样即使信息被拦截,敌人也无法获知真正的信息。
凯撒密码的密钥就是 字母向右移动的位数(上图中的 2 ) 。密钥和明文的重要程度其实是一样的,丢失密钥和丢失明文并没有什么区别。显而易见,这样的密钥强度太低了。即使后来出现了 乱序对应的字母表 ,仍然很容易被破译。
随着科学技术的进步,依托计算机发展的现代密码学提供了经过数学验证的加密方法和(伪) 随机生成的密钥,使得加密一段信息变得快速而安全。
对称加密
人如其名,对称加密的 加密 和 解密 是对称的,加密密钥和解密密钥是同一个密钥。典型的对称加密算法有 DES 和 AES 。
DES 是 1977 年美国联邦信息处理标准中所采用的一种对称加密,现在已经可以被暴力破解,所以除了考虑到兼容性问题以外,不应该再继续使用 DES 。 此外,还有为了加强 DES 强度的 三重 DES,即将 DES 重复三次。由于其处理速度不高,除了特别重视向下兼容性的情况下,很少被用于新的用途。
现在使用最为广泛的对称加密是在全世界范围内公开选拔出来的 AES 加密。经过全世界密码学家的共同论证,其安全性是毋庸置疑的。那么,我们直接使用 AES 加密通信内容不就可以了吗?
对称加密的一个致命问题就是 密钥的传输问题 。由于加解密过程都使用同一个密钥,所以通信一方必须将密钥首先传给另一方,双方才能正常的进行通信。可是,如果有可靠的方法来传输密钥,那么用同样的方法就可以安全的传递通信内容。使用对称加密,只是把 如何安全的传输通信内容 转化为了 如何安全的传输密钥 ,本质上并没有解决任何问题。
那么,如何解决密钥传输问题呢 ?
非对称加密
要解决密钥传输问题,我们可以 “不传输” 密钥。
非对称加密通过公私钥完美解决了密钥传输问题。发送方使用公钥进行加密,接收方使用私钥进行解密。公钥可以公开存在于网络中,私钥由接收方保管,不能泄露。私钥是通信安全的重要保障,一旦泄露,加密通信都会被破解。我们最常使用的非对称加密是 RSA 。
看似完美解决密钥传输问题的非对称加密,仍然存在明显的问题。
非对称加密的性能只有对称加密的几百分之一。在浏览器或者即时聊天的场景下,这个速度可能是用户所接受不了的。所以真正使用时,往往是对称加密和非对称加密结合使用,如下图所示。
用非对称加密来保护对称加密的密钥 ,既解决了对称加密的密钥传输问题,又解决了非对称加密速度慢的问题。
现在已经解决了通信内容的加密问题。即使通信内容和加密过的对称密钥被拦截,由于没有私钥,也无法解密查看。那么,现在的通信流程是安全的吗?并不是,目前还有一个核心问题,在缤纷繁杂的互联网上,对方真的是对方吗? 就好比和你语音聊天的萌妹子,其实可能是个抠脚大汉。中间人攻击 就是典型的例子,下面这张图描述了中间人攻击的基本流程。
中间人通过特定技术手段拦截了双方的通信链路,然后调包了发送给发送者的公钥,神不知鬼不觉的拦截并伪造了通信内容。发送方无法确定收到的公钥到底是不是接收方的,接收方也无法识别到消息被篡改。
在 防止通信内容被篡改 和 认证对方身份 的问题上,此时依然无法解决。
哈希算法
聊到防止通信内容被篡改,很容易想到哈希算法。输入任意长度的内容,计算出固定长度的哈希值 ,也可以叫 散列值 或 消息摘要。哈希算法并不是加密算法,它只是用来校验消息的完整性,例如在官网上下载软件,通常会提供哈希值供用户比对。
常见的 MD4/MD5,包括 SHA1,都已经不再安全,不建议使用。目前推荐使用 SHA2/SHA3。
其实哈希算法很少被直接单独使用在加密通信中,因为它仍然无法解决上一节的问题。如果发送方把消息和消息的哈希值一起发送过来,中间人要做的无非就是把哈希值也替换了,仍然无济于事。这时候就得把哈希算法揉进既有体系中使用。
消息验证码
消息验证码其实和哈希很像,它也是输入任意长度的内容,计算出固定长度的验证码。但是这个计算过程需要一个发送者和接收者共享的密钥。消息认证码是一种和密钥相关联的哈希算法 。
发送者在发送数据的同时,使用共享密钥计算出消息验证码,和数据一起发送。接收方接收到数据后,使用共享密钥计算出消息认证码,再和发送方发送过来的消息验证码进行比对。比较常见的消息认证码有 HMAC 算法。
由于共享密钥只有通信双方才有,所以即使中间人拦截并修改了消息,接收方通过计算消息认证码也可以识别到篡改。
什么?共享密钥?共享密钥怎么安全传输并且不被中间人拦截?没错,消息认证码同样存在密钥传输问题。可以通过引入非对称加密来解决。
同时,由于使用了共享密钥,消息认证码存在 对第三方证明 和 防止否认 的问题。因为通信双方都有共享密钥,所以无法判断某一条消息究竟是谁发送的,也就无法对第三方证明和防止否认。比如类似 “我欠你 500W” 的这种消息,发送方可以说是接收方发给我的,接收方也可以说是发送方发给我的。
为了解决这个问题,数字签名出场了。
数字签名
数字签名听起来高大上,其实它的原理很简单。我先把 非对称加密 的图搬过来,
非对称加密是发送方持有公钥,接收方持有私钥。公钥可以直接在网络中传送,私钥仅有接收方才有。
现在假设这样一种场景,把上图中的流程倒过来, 接收方给发送方发送消息,接收方使用私钥加密消息,发送方接收到消息后用公钥进行解密。由于私钥只有接收方持有,所以一定可以确定收到的消息来自接收方。这是不是就做到了 认证对方身份,防止否认,向第三方证明 。
用私钥加密,用公钥解密,这其实就是数字签名。只不过在数字签名中,用私钥加密的过程叫做 生成签名,用公钥解密的过程叫做 验证签名 ,和非对称加密正好反了过来。来个图对比一下。
这只是一个简单的示意图。在真正的使用过程中,并不会用私钥直接对原数据进行签名,而是先对原数据做哈希,再对哈希值签名,这样可以减少数据传输量。再来个图:
图中直接发送的原数据,但这个原数据并不是指明文。实际使用中,可以配合非对称加密保护对称加密密钥的方式对原数据进行保护。
数字签名可谓是功能齐全,再来回顾一下文章开头提到的安全传输的几点要求:
- 保证传输内容的安全,即不传输明文
- 防止传输内容被篡改,即可以识别篡改
- 确认对方真的是对方,即对方身份的认证
数字签名已经完全符合这几点要求。但......
无论是单独使用非对称加密,还是数字签名,只要是涉及到公钥,都会存在一个问题。公钥是公开存在于网络中的,如何保证用于非对称加密,或者数字签名验签的公钥不是伪造的?
这就依赖于本文最后一节内容 —— 证书。
证书
证书要解决的问题是 公钥的合法性 。也就是说,公钥要安全的从一方传给另一方,不能被掉包,不能被篡改。
等等,这不就是这篇文章的主题,如何安全的传输信息 吗?现在要传输的信息就是公钥。毫无疑问,上面讨论过的方法都可以在这里应用,数字签名就是一个好选择。
没错,证书就是对公钥进行数字签名 。
对于公钥的发送者来说,公钥就是一个普通的待传输的数据,下面用 待传输公钥 表示,以防混淆。发送者生成自己的一对公私钥(公钥A 和 私钥 A),用 私钥 A 对 待发送公钥 进行数字签名,表示这个公钥的确来自于我。这样接收到公钥的第三方(浏览器等) 就可以拿发送者的 公钥 A 进行验证签名,校验公钥是否合法。
不知道有没有把你看晕。如果没有的话,你应该很容易发现其中的逻辑 Bug 。本身就是为了验证 待传输公钥 的合法性,却因此又引入了 公钥 A 。那么 公钥 A 的合法性又如何保证呢?再引入一对公私钥吗?这样无限套娃,依旧无法解决问题的实质。但是又能有什么办法呢?
对,就是没有办法,事实上也就是这么套娃的。我们以 Github 为例,点击 Chrome 网址左边的小锁,就可以查看证书信息。
在证书路径中,可以看到有三层。这其实就是一个完整的证书链。github.com 证书的安全性由上一层 DigiCert SHA2 High Assurance Server CA 来保证,DigiCert SHA2 High Assurance Server CA 的安全性由再上一层的 DigiCertA 来保证。而这个 DigiCertA 的安全性则由它自己保证,也就是说我们必须无条件相信它,否则套娃永远没有尽头。
这个 DigiCertA 就叫做 根证书 ,它内置在我们的计算机系统或者浏览器中。正是由这些根证书,来一级一级向下保证,直到保证到某次通信中使用到的证书是安全的。除了内置的根证书以外,用户也可以安装自己信任的证书。
证书中除了 公钥 和 签名 之外,还包含了其他一些附加信息。大部分证书都遵循 X.509 标准规范,这里就不详细描述了,感兴趣的可以自行查阅。我们在 Chrome 上简单看下基本的证书信息。
总结
写到这里,安全通信的大部分问题都已经被解决了。我们再来回顾一下。
通信内容一般直接使用 对称加密 ,但对称加密存在 密钥传输问题 。
非对称加密 性能只有对称加密的几百分之一,不会用来直接加密通信内容。但是可以配合对称加密,用非对称加密保护对称加密的密钥,以解决密钥传输问题。
哈希算法 主要用于信息的完整性。
消息认证码 是一种和密钥相关联的哈希算法。它通过共享密钥,不仅能确保信息的完整性,还可以提供认证功能,确保消息来自期望的通信对象,但同样也存在密钥传输问题。
数字签名 技术使用私钥签名,公钥验证签名,同时兼具确认信息完整性,确认通信对方身份,防止否认的功能。
证书 的目的是确保公钥的合法性,它的本质就是为公钥加上数字签名。它的安全性由证书链顶端的根证书来保证。
了解了这些常用技术之后,Https 无非就是这些技术的组合罢了。下篇中,我们就来探究 Https 的具体通信流程以及这些加密技术的应用。