12.1 概述
签名算法是公钥密码学的“消息认证码”,它主要包括3个部分:
- 一个密码生成算法,该部分可以和公钥算法一致
- 一个签名生成算法
- 一个签名认证算法
签名算法可以在加密算法的基础上构建。使用一个私钥,可以对一个消息产生一个值,通常是使用hash算法来生成。任何人都可以用公钥来检查这个值,计算该值是否由消息计算得到,然后将两者进行验证。和公钥加密算法一个明显的不同是,使用私钥来产生消息(这个情形下就是签名),使用公钥去解析它,这个和加密的过程是反过来的。
上面的说明是对后面很多重要细节的概述。本文将继续讨论一些细节。
12.2 基于RSA的签名算法
PKCS#1 v1.5(TODO)
PSS TODO
12.3 DSA
数字签名算法(Digital Signature Algorithm DSA)是英国联邦政府的一个数字签名标准。它由NIST(National Institute of Standards and Technology)在1991年第一次提出,用来作为数字签名的标准(Digital Signature Standard DDS)。该算法由NSA的技术顾问David W.Kravitz发布。
DSA的密钥生成分为两步:第一步,选择在用户中共享的参数。第二步,为每一个用户生成一份公私钥对。
参数生成
首先需要挑选一个被推荐的密码hash函数H,密钥长度L和一个素数长度N。原始的DSS中推荐L的长度为512和1024之间,现在NIST推荐密钥的长度为3072位这样密钥的安全生命周期就可以到2030年。随着L的增长,N也需要增长。
接下来选择素数q,其长度为N位。N需要小于或者等于hash输出的长度。再选择一个L位长度的素数p,使得p-1是q的倍数。
最后一部分是最容易让人困惑的。需要找到一个数字g,它的乘法序模p是q。最简单的方法是设
也可以尝试其他比2大,比p-1小的数。
一旦确定了(p,q,g),可以将其在用户中共享。
密钥生成
有了参数,就该来位用户计算公钥和私钥了。首先,选择随机数x (0<x<q), 接下来计算y y=g^x(mod p).这样私钥就是x,公钥为(p,q,g,y)。
签名
为了对消息进行签名,签名者在0-q之间挑选一个随机数k。如何挑选k是一个很敏感和相关的过程,这个在之后进行讨论。当k选定后,可以计算消息m的签名的两部分r和s:
如果两者中任意一个是0(罕见时间),再重新选择一个k。
验签
验证签名需要一个复杂的计算。给定消息m和签名(r,s):
如果签名是有效的,那么v就会等于r,也就是签名的第二部分。
k的问题
虽然目前DSA算法自身没有什么问题,但是它却很容易出错。进一步说,DSA是非常敏感的,仅仅是一个很小的实现上的错误就可以毁掉整个机制。
特殊来看,签名参数k的选择是非常严格的。可以说是密码系统中对于随机数选择中最严格的。例如,很多算法需要一个nonce值。nonce值仅仅需要唯一,它不需要私密。它也不需要不可预测。nonce值通常可以使用简单的计数器或者时钟。很多其他算法例如CBC模式,需要一个初始化向量。它不需要是唯一的,只需要是不可预测的。它也不需要是私密的:初始化向量通常和密文一起。但是DSA算法的随机数k是以上的组合:
- 它必须要是唯一的。
- 它必须要是不可预测的。
- 它必须是私密的。
如果没有满足这些特性,攻击者可以尝试从一定数量的签名中得到你的私钥。例如,攻击者只要知道k的一些位,和比较多的有效签名,就可以恢复出私钥。[NS00]
实际中DSA的很多实现都不能保证唯一性,愉快地重用随机数k。这就使得只需要使用简单的数学就可以恢复密钥。因为这个攻击很容易理解,应用非常广泛并且可以造成非常严重的影响,本节将讨论它的细节。
假设攻击者看到了很多对于不同消息mi的签名(ri,si),它们使用了相同的k。攻击者可以挑选出两个签名(r1,s1)和(r2,s2),假设它们的原消息位m1和m2.s1和s2的是通过如下计算得到的
攻击者可以推断出r1和r2是相同的,因为
重用了相同的k,而r仅仅依赖于k,所以r是相同的。另外由于签名者使用的是同一个密钥,两个公式中的x也是相同的。
将两个s相减,得到一下的计算:
可以得到k
两个hash值H(m1)和H(m2)很容易计算。它们并没有加密,被签名的消息是公开的。签名的两个s1和s2是签名的组成部分,攻击者都可以看到。所以攻击者可以计算得到k。目前它还没有得到私钥x,然后用私钥去伪造签名。
再次看下s的计算过程,这次把k当作是已知项,x作为需要解决的变量。
所有有效的签名都满足这个等式,所以可以尝试任意一个签名。来解出x
同样的H(m)是公开的,攻击者可以计算出k。假设他们已经计算出了k,s本身就是签名的一部分。现在只需要计算r^(-1)(mod q)(也就是r相对于模q的逆元),这个同样也可以计算出来。(更多信息可以查看附录中有关于现代数学,记住q是个素数,所以这个模的逆元是可以直接计算的)。这也就意味着攻击者,只要发现了任何签名的k,就可以得到私钥的值。
目前为止,本节中假设的是签名者一直使用的同一个随机数k。更糟的是,签名者只要在攻击者可以看到的签名中,有两个签名复用k一次。如上,k重复了,r就会重复。而r是签名的一部分,签名者的这个错误非常容易被观察到。这样即便签名者只是很罕见地重用了k(比方说随机数生成器的问题),只一次,攻击者就可以打破这个DSA系统。
简而言之,在DSA签名算法中重用参数k就意味着攻击者可以破解出私钥。
12.4 ECDSA
TODO:
和一般的DSA相同,k的选择是极为严格的。攻击者可以使用几千个签名,这些签名的nonce仅仅有一些位泄漏,攻击者便可以破解出签名的私钥。
12.5 可拒绝的认证者
本章描述的签名算法有一个特点被称为:不可抵赖性。简单说,它意味着不可以否认自己就是签名消息的发送者。任何人都可以验证你用私钥签署的签名。但是签名只有你可以做。
这通常并不是一个有用的特性,只有少数接受者可以验证签名可能更加谨慎。这种算法通常需要只有接受者才可以计算出这个特殊的值。
这些消息是可以拒绝的,例如一种通常被称为“可以否认的消息认证”。一个发送者认证一条消息给接收者,发送者之后可以否认它发送了这条消息。接收者也无法向任何人证明发送者给他发送了特定的消息。