文章目录
一、本章学习内容
本章中我们将学习 数字签名 的相关知识。数字签名是一种将相当于现实世界中的 盖章、签字 的功能在计算机世界中进行实现的技术。
使用数字签名可以 识别篡改和伪装,还可以防止否认。
二、数字签名
1、Alice 的借条
假设 Alice 要向 Bob 借 100万元,不过,Alice 和 Bob 离得很远,无法直接见面。通过银行汇款,Alice 可以立刻从 Bob 那里收到钱,但是 Alice 的 借条 应该怎样发送给 Bob 呢?可以用 挂号信 寄过去,不过那样需要花上一段时间,能不能用 电子邮件 来发送借条呢?比如:“Bob,我向你借款 100 万元。——Alice”
显然,这样的邮件无法代替借条,Bob 看到这封邮件也不会轻易相信,因为电子邮件是很容易被 篡改、伪装、否认 的。
2、从消息认证码到数字签名
2.1、消息认证码的局限性
通过使用 消息认证码,我们可以保证消息的 完整性,以及对消息进行 认证。然而,在出具借条这个场景中,却无法使用消息认证码,因为 消息认证码 无法 防止否认。
消息认证码之所以无法防止否认,是 因为消息认证码需要在 发送者Alice 和 接收者Bob 两者之间 共享同一个密钥。正是因为密钥是共享的,所以 能够使用消息认证码计算出正确 MAC值 的并不只有 发送者Alice,还有 接收者Bob。由于 Alice 和 Bob 双方都能够计算出正确的 MAC值,因此对于 第三方 来说,我们 无法证明这条消息的确是由 Alice 生成的。
2.2、通过数字签名解决问题
假设 发送者Alice 和 接收者Bob 不需要共享一个密钥,也就是说,Alice 和 Bob 各自使用不同的密钥。
我们假设 Alice 使用的密钥是一个只有 Alice 自己才知道的私钥。当 Alice 发送消息时,她 用私钥生成一个 “签名”。相对地,接收者Bob 则 使用一个和 Alice 不同的密钥,对签名进行验证。
Bob 的密钥 无法根据消息生成签名,但是 Bob 的密钥却可以 对 Alice 所计算的签名进行验证,也就是说可以知道这个签名是否是通过 Alice 的密钥计算出来的。如果真有这么一种方法的话,那么不管是别篡改、伪装还是防止否认就都可以实现了吧?
实际上,这种看似很神奇的技术早就已经问世了,这就是 数字签名 digital signature。
3、签名的生成和验证
在数字签名技术中,出现了下面两种行为:
- 生成 消息签名的行为:
由 发送者Alice 完成的,也称为 对消息签名。生成签名就是 根据消息内容 计算 数字签名的值,这个行为意味着 “我认可该消息的内容”。 - 验证 消息签名的行为:
由 接收者Bob 或 第三方 完成的,第三方也称为 验证者 Victor。验证签名就是检查该消息的签名是否真的属于 Alice,验证的结果可以是成功或者失败。
在数字签名中,生成签名和验证签名这两个行为需要使用各自专用的密钥来完成。
Alice 使用 签名密钥 来生成消息的签名,而 Bob 和 Victor 则使用 验证密钥 来验证消息的签名。数字签名对 签名密钥 和 验证密钥 进行了区分,使用 验证密钥 是无法生成签名的。这一点非常重要。此外,签名密钥 只能由签名的人持有,而 验证密钥 则是任何需要验证签名的人都可以持有。
4、公钥密码与数字签名
公钥密码 和上面讲的数字签名的结构非常相似。在公钥密码中,密钥分为 加密密钥 和 解密密钥,用加密密钥无法进行解密。此外,解密密钥只能由需要解密的人持有,而加密密钥则是任何需要加密的人都可以持有。
简而言之,数字签名 就是通过 将公钥密码 “反过来用” 而实现的。
私钥 | 公钥 | |
---|---|---|
公钥密码 | 接收者解密时使用 | 发送者加密时使用 |
数字签名 | 签名者生成签名时使用 | 验证者验证签名时使用 |
谁持有密钥? | 个人持有 | 只要需要,任何人都可以持有 |
通过图片来看看 公钥密码 和 数字签名 的区别:
三、数字签名的方法
下面我们来具体介绍两种生成和验证数字签名的方法:
- 直接对消息签名的方法
- 对消息的散列值签名的方法
直接对消息签名的方法比较容易理解,但实际上并不会使用;对消息的散列值签名的方法稍微复杂一点,但实际中我们一般都使用这种方法。
1、直接对消息签名的方法
Alice 需要事先生成一个包括公钥和私钥的 密钥对,而需要验证签名的 Bob 则需要得到Alice 的公钥。在此基础上,签名和验证的过程如下图所示。
- Alice 用自己的私钥对消息进行加密
用 私钥 加密得到的密文就是 Alice 对这条消息的 签名,由于只有 Alice 才持有自己的私钥,因此除了 Alice 以外,其他人是无法生成相同的签名 (密文) 的。 - Alice 将消息和签名发送给 Bob
- Bob 用 Alice 的 公钥 对收到的签名进行 解密,解密的结果应该等于发送的消息
- Bob 将签名解密后得到的消息与 Alice 直接发送的消息进行对比,如果两者一致,则签名验证成功;如果两者不一致,则签名验证失败。
2、对消息的散列值签名的方法
上一节中直接签名的方法,看起来非常地简单直接,但是 这种方法需要对整个消息进行加密,非常耗时,这是因为公钥密码算法本来就非常慢。那么,我们能不能生成一条 很短的数据 来代替消息本身呢‘?这个时候我们就想到了 单向散列函数。
于是我们不必再 对整个消息进行加密,即 对消息签名,而是只要 先用单向散列函数求出消息的 散列值,然后 再将散列值进行加密,即 对散列值签名,就可以了。无论消息有多长,散列值永远都是这么短,因此对其进行 加密 (签名) 是非常轻松的。
签名和验证的过程如下图所示:
- Alice 用单向散列函数计算消息的散列值
- Alice 用自己的私钥对散列值进行加密
用私钥加密散列值 所得到的 密文 就是 Alice 对这条散列值的 签名,由于只有 Alke 才持有自己的私钥,因此除了 Alice 以外,其他人是无法生成相同的 签名 (密文) 的。 - Alice 将消息和签名发送给 Bob
- Bob 用 Alice 的公钥对收到的签名进行解密,解密的结果应该等于消息的散列值
- Bob 将签名解密后得到的散列值与 Alice 直接发送的消息的散列值进行对比
如果按照 时间顺序 来看,过程应该如下图所示:
四、对数字签名的疑问
上面我们对数字签名进行了基本的讲解,但恐怕很多读者并不十分认同,至少我在刚听到数字签名这个话题时,心中也产生了不少疑问。下面我们就设想一些读者可能会产生的疑问并进行解答。
1、数字签名不能保证机密性吗
疑问:
从 图9-6 来看,消息没有经过加密就发送了,这样不就无法保证消息的机密性了吗?
解答:
的确如此,数字签名的作用本来就不是保证机密性。如果需要保证机密性,则可以不直接发送消息,而是将消息进行加密之后再发送。这种密码和签名的组合会在 第13章 中详细介绍。
五、数字签名的应用实例
1、安全信息公告
一些信息安全方面的组织会在其网站上发布一些关于安全漏洞的警告,那么这些警告信息是否真的是该组织所发布的呢?我们如何确认发布这些信息的网页没有被第三方篡改呢?
信息发布的目的是尽量让更多的人知道,因此我们没有必要对消息进行加密,但是必须排除有人恶意伪装成该组织来发布假消息的风险。因此,我们 不加密消息,而只是对消息加上数字签名,这种对 明文消息 所施加的签名,一般称为 明文签名 clearsign。
2、软件下载
无论哪种情况,我们都需要判断所下载的软件是否可以安全运行,因为下载的软件有可能被主动攻击者 Mallory 篡改,从而执行一些恶意的操作。
为了防止出现这样的问题,软件的作者 可以对软件加上 数字签名,而我们只要在下载之后验证数字签名,就可以识別出软件是否遭到了主动攻击者 Mallory 的篡改。
一种名为 带签名的 Applet 的软件就是一个具体的例子。这种软件是用 Java 编写的 (一种浏览器进行下载并执行的软件),并加上了 作者的签名,而浏览器会在下载之后对签名进行验证。
3、公钥证书
在验证数字签名时我们需要 合法的公钥,那么怎么才能知道自己得到的公钥是否合法呢?
我们可以 将公钥当作消息,对它加上数字签名。像这样 对公钥施加数字签名 所得到的就是 公钥证书,关于 证书 我们会在 第10章 详细介绍。
4、SSL/TLS
SSL/TLS 在 认证服务器身份是否合法时 会使用 服务器证书,它就是 加上了数字签名的服务器公钥。相对地,服务器为了对客户端 (用户) 进行认证也会使用 客户端证书。关于SSL/TLS 我们会在 第14章 详细介绍。