1. 数字签名初识

上一篇博客的最后我们介绍了在非对称加密中,可以用私钥加密而用公钥解密。

那这个机制有什么用呢?公钥是公开的,任何人都可以用其解密消息了,这还怎么保密明文呢?其实在这种场景下,我们的目的不再是保密了,而是认证(certificate)!所以加密解密也得换个名字,在这里私钥被用来签名,公钥被用来验证

具体来讲,如果接受方(B)收到了用发送方(A)的私钥加密(签名)的消息,则肯定可以用 A 的公钥将其解密(验证)。如果验证成功,这就说明了这条消息肯定是从 A 发过来的,因为只有 A 有对应的私钥,所以不可能有其他人能加密出一个可以用 A 的公钥解密的密文。所以,这里的认证的含义就是这样,一方对数据签了一个只有自己能签的名,另一方用对应的密钥验证这个签名的归属。

即使攻击者 C 在中途截获了密文,并用 A 的公钥解开了签名,但其也无法做成任何事,因为就算其将原文的内容做了修改,但他也无法使用 A 的私钥再次将原文签名。

数字签名在现代 Web 商务中具有重要意义。大多数国家已经把数字签名看成与手工签名具有相同法律效力的授权机制。这也使得网上银行及相关业务可以蓬勃的发展。例如,你通过 Internet 向银行发送一条消息,要求把你的钱从你的账户转到某个朋友的账户,并对这条消息进行了数字签名。则日后你不能再跳出来说我从来没有授权过银行挪动我的资金并要求银行赔偿,因为银行可以拿出那个被数字签名的消息,然后光明正大的用你公钥验证,如果验证成功那你可就丢脸了。

2. 消息摘要

上面说的数字签名还有个小问题,其还是没有解决非对称加密速度慢的问题,因为如果你对大段的原文进行数字签名的话,还是需要耗费很多时间。所以在现实中我们常常不直接对原文进行数字签名,而是对原文的消息摘要进行数字签名。

2.1. 简介

消息摘要(Message Digest),顾名思义被用来表示一段消息的摘要信息,也常被称作是消息的指纹(fingerprint)。这就类似与计算机网络中常见的的循环冗余校验(CRC),其主要目的就是验证一段消息是否被篡改了,因为如果消息被篡改,则此段消息的摘要一定会发生变化,接收方收到消息后再算一次摘要就会发现和发送方计算的摘要不同,由此判断消息已被篡改。

而攻击者很难将消息篡改后还能计算出同样的摘要,这是消息摘要算法的任务,消息摘要算法需要下面这些要求:

  1. 给定一个消息,应该很容易求出消息摘要。当然是为了便于计算。
  2. 给定消息摘要,应该很难求出原先的消息。
  3. 给定两个消息,其计算出的消息摘要应该不同。这一点其实不好完美的达成,因为一般而言消息摘要都是定长的,就是说不管你的原文多长,我计算出来的消息摘要一定会是这么长。既然是定长的我们就知道总有穷尽的时候,而消息一定是无穷的,所以想要完美的做到消息摘要不重复是不可能的,但我们可以增大其难度。首先著名的消息摘要算法 MD5 的摘要长度为 128 位,所以会有 $2^{128}$ 种不同的摘要,我们要让摘要的产生尽可能的随机,这样攻击者虽然有可能找到两个摘要一样的消息,但其很难保证这两个消息都是有意义的。例如 I love you 的 MD5 消息摘要是 e4f58a805a6e1fd0f6bef58c86f9ceb3 ,而 I hate you 的 MD5 消息摘要是 d2ec37d88bcbc82daf652c2a0a50d123 。可以看到天壤之别,而攻击者很难找到一个摘要相同但是同样有意义的消息。

有了消息摘要后,数字签名就能更进一步了。我们首先对原文进行消息摘要算法得到原文的消息摘要,然后用私钥签名这个消息摘要,这样就可以避免签名大段消息造成时间的浪费了。最终将消息摘要和原文一同发送给接收者,接收者验证的时候用对应的公钥进行验证,得到原文的消息摘要信息,然后运用同样的消息摘要算法计算一遍原文,如果相同,则说明消息一定来自对应的发送方。而若不同,则说明消息一定被篡改过。这样数字签名就具有了最重要的验证篡改的功能。

2.2. 消息摘要算法

具体的消息摘要算法有很多,下面来简要介绍。

MD5

MD5 是最著名的消息摘要算法之一,曾广泛的使用在各种场景中。这个算法最后的 5 说明了这其实是一系列算法,MD5 是其中的第 5 代。关于这个算法我写过一篇博客详细介绍过,参见:https://laihaodong.cn/2209.html

SHA

随着时间的推进,不断有学者提出 MD5 碰撞的例子。所谓的碰撞就是指拿出两个摘要相同的消息,当然这两个消息都有意义还是很难。总之现在在高安全性的场景下 MD5 已经被禁止使用了,因此人们要寻找更好的消息摘要算法,于是出现了 SHA 。

美国国家标准与技术学会(NIST)和 NSA 开发了安全散列算法(Secure Hash Algorithm, SHA),后来更名为 SHA-1 。其是在 MD4 的基础上修改而成的,与 MD4 的设计非常相似。

SHA-1 可以处理长度在 $2^{64}$ 以内的任何输入消息。SHA-1 输出的消息摘要长度为 160 位(比 MD5 多了 32 位)。

SHA-1 脱胎自 MD4 ,所以和 MD4 家族的算法原理都差不多,暂时不多介绍,只需要记住摘要长度变为了 160 位,所以简单的理解为更难被破解了。

SHA-2

2005 年 SHA-1 第一次被发现了可能的脆弱性,就在这之前,NIST 就宣布要寻找更安全的 SHA 版本。因此,SHA 算法家族出现了更多的变体,称为 SHA-256、SHA-384 和 SHA-512,其后面的数字表示的是消息摘要的长度(以位为单位)。其统一被归为 SHA-2 家族。

(H)MAC

上面的所有消息摘要算法都有一个攻击方法,就是彩虹表。这也是为什么软件在让你设置口令的时候会加那么多条件,什么大小写了,特殊字符了,长度了,因为彩虹表的存在会让弱口令变得非常脆弱。彩虹表其实就是把单向的哈希函数的很多具体实例存储起来,例如将 abcd 的 MD5 值 e2fc714c4727ee9395f324cd2e7f331f 记起来,这样如果黑客监听到消息摘要是 e2fc714c4727ee9395f324cd2e7f331f 的话就直接可以反推出消息是 abcd ,这很明显是一种空间换时间的方法,免去了把 MD5 算个几万遍的繁杂方法。

那么应对彩虹表的方法就是加盐(salt),在密码学中,加盐就代表着对输入增加一些额外的信息,例如加入一些相对随机的字符,这样就可以保证即使输入相同输出也不会一样。

而在消息摘要算法中,加盐有一个实际的例子就是 MAC(Message Authentication Code, 消息认证码)。MAC 实际上只是一种思想,而具体实现的算法叫做 HMAC(Hash-based Message Authentication Code, 基于散列的消息认证码)。

HMAC 的基本思想是复用 MD5 与 SHA-1 之类的现有消息摘要算法,显然没必要一切都从头开始对吧。首先,通信双方需要共享一个对称密钥 K ,然后发送方首先使用 MD5 等消息摘要算法对消息计算一次摘要,然后使用对称密钥 K 将算出来的消息摘要进行加密,而将最终加密的到的消息作为最终的消息摘要发送给接收方。接收方收到消息后只需要和发送方做一遍同样的流程,即先用消息摘要算法算出摘要,然后再对摘要加密,最终只需要对比自己算出来的消息摘要和发过来的消息摘要是否一样就可以判断消息是否被篡改。

3. 数字签名技术

RSA 数字签名

有了前面的知识,我们终于可以讨论到底 RSA 签名是怎么回事了。下面介绍一下 RSA 数字签名的流程。为此,假设发送方(A)要向接收方(B)发一个消息 M ,并对消息 M 计算数字签名(DS)。

  1. 发送方 A 使用一个消息摘要算法例如 SHA-1 对消息 M 计算消息摘要(MD1)。
  2. 发送方 A 用 RSA 数字签名的私钥加密(签名)这个消息摘要,输出 A 的数字签名(DS)。
  3. 发送方 A 将消息 M 和数字签名 DS 一起发送给接收方 B。
  4. 接收方 B 收到后使用相同的消息摘要算法对消息 M 计算消息摘要,得到消息摘要 MD2 。
  5. 接收方 B 使用发送方 A 的 RSA 数字签名的公钥解密(验证)数字签名 DS ,得到消息摘要 MD1 。
  6. 最后只需要对比 MD1 和 MD2 即可。如果 MD1 = MD2 ,则可以表明消息 M 未经篡改且一定来自 A 。

这种数字签名技术的有效性之前已经讨论过了。可以看到,数字签名的原理相当强大、安全和可靠。

4.公钥交换的问题

有关非对称加密体系已经写了两篇博客了,不知道有一个问题是否足够明显。在前面的内容中,不管是 RSA 加密还是 RSA 签名中,我们都有一个前提假设!即通信双方可以自由的交换公钥。毕竟在说非对称密钥加密体系相对于对称密钥加密体系的优点的时候就说过,非对称密钥加密不需要考虑密钥交换的问题,因为公钥可以放心的在网络中交换,不怕被别人看到。

那么,公钥不怕被别人看到是否就意味着这一过程不会有问题呢?例如,你怎么知道通信的另一方的公钥?假如直接通过网络将公钥发给你的话,怎么证明公钥没有被篡改?甚至你怎么知道给你发公钥的这个人就真的是你希望通信的那个人呢?呵,这最后这种情况,不就是之前提到的中间人攻击吗。你以为你在和正确的对端通信,其实和你通信的是一个恶意的中间人,你收到的其实只是中间人的公钥,所以你最终确实可以建立起一条安全的 RSA 加密信道,只不过你压根就不知道你只是在向中间人发消息而已。类似的,中间人再和你希望通信的另一方建立一个 RSA 加密信道,从而成为了一个真正的中间人,它可以仅仅中转你和对端的通信数据,甚至可以稍微修改修改其中的数据。

哎呀,说了半天怎么非对称加密体系也有公钥交换的问题呀。没办法,这确实是个缺陷,对称加密体系我们介绍了 DH 算法用于密钥交换,那非对称加密体系怎么办呢?其实,这个问题也引出了我们现代互联网的信任体系,即如何表明消息的真实来源,说白了就是你怎么证明你就是你?这个博客介绍的数字签名技术看似可以解决我证明我是我的问题,那么这一节的讨论就指出了其中的不足,公钥如何交换?所以在数字签名技术之外还需要一个公钥交换技术,这就是我们下一篇博客介绍的公钥基础设施

最后修改:2020 年 03 月 15 日
如果觉得我的文章对你有用,请随意赞赏