数字签名
——消息到底是谁写的
数字签名的应用实例
安全信息公告
一些信息安全方面的组织会在其网站上发布一些关系安全漏洞的警告,那么这些警告的信息是否真的是该组织所发布的呢?
在这样的情况下就可以使用数字签名,即该组织可以对警告的信息的文件施加数字签名,这样一来世界上的所有人就都可以验证警告信息的发布者是否合法。
一般发布消息都是尽量让人知道,所以一般不对消息进行加密,但也必须排除有人伪装的风险,因此不加密消息,只对消息加上数字签名,一般称为明文签名。
软件下载
我们经常会从网上下载软件进行安装使用,因为下载的软件可能被攻击者篡改过,所以为了防止这样的问题,软件的作者对软件加上数字签名,而我们下载后只要验证数字签名,就可以识别软件是否被攻击过了。
公钥证书
在验证数字签名时我们需要合法的公钥,那怎么才知道自己得到公钥是否合法呢?我们可以将公钥当作是消息,对它进行数字签名。像这样对公钥施加数字签名所得到的就是公钥证书。
SSL/TLS
SSL/TLS在认证服务器是否合法时会使用证书服务器证书,它就是加上了数字签名的服务器公钥。相对地,服务器为了对客户端(用户)进行认证也会使用客户端证书。
通过RSA实现数字签名
为了简单,我们不适用单向散列函数,而是直接对消息进行签名。关于将RSA和单向散列函数相结合来进行数字签名的详细说明,请参见RFC 3447(Public-Key Cryptography Standards(PKCS) #1)。
用RSA生成签名
签名 = 消息^D mod N (用RSA生成签名)
这里所使用的D和N就是签名者的私钥。签名就是对消息D次方求mod N的结果,也就是说将消息和自己相乘D次,然后再除以N次余数,最后求得余数就是签名。
生成签名后,发送者就可以将消息和签名发送给接收者了。
用RSA验证签名
由签名求得的消息= 签名^E mod N。
这里所使用的E和N就是签名者的公钥。接收者计算签名的E次方并求mod N,得到“由签名求得的消息”,并将其与发送者直接发送过来的消息内容进行对比。如果两者一致则签名验证成功,否则验证失败。
其他数字签名
EIGamal方式
EIGamal方式是由Taher EIGamal设计公钥算法,利用了在mod N汇总求离散对数的困难度。EIGamal方式可以被用于公钥密码和数字签名。密码软件GnuPG中也曾使用过EIGamal方式,但是由于1.0.2版本中数字签名的实现上存在漏洞,因此在GnuPG中EIGamal也仅被用于公钥密码。
DSA
DSA(Digital Signature Algorithm)是一种数字签名算法,是由NIST于1991年制定的数字签名规范,DSS是Schnorr算法与EIGammal方式的变体,只能被用于数字签名。
ECDSA
ECDSA(Elliptic Curve Digital Signature Algorithm)是一种利用椭圆曲线密码来实现的数字签名算法。
Rabin方式
Rabin方式是由M.O.Rabin设计的公钥算法,利用了mod N中求平方根的困难度。Rabin方式可以被用于公钥密码和数字签名。
对数字签名的攻击
中间人攻击
对数字签名中间人攻击,具体来说就是主动攻击者Mallory介入发送者和接收者中间,对发送者伪装成接收者,对接收者伪装成发送者,从而能够在无需要破译数字签名算法的前提下完成攻击。
要防止中间人攻击,就需要确认自己所得到的公钥是否真的属于自己通信对象的。比如打个电话确认一下,但是在电话念一遍公钥内容太难了,有一个简单办法就是 分别用单向散列函数计算出散列值,然后电话中可以相互确认,这个散列值其实就是指纹。
对单向散列函数攻击
数字签名中所使用的单向散列函数必须具有抗碰撞性,否则攻击者就可以生成另外一条不同的消息,使其与签名所绑定的消息具有相同散列值。
利用数字签名攻击公钥密码
在RSA中,生成签名的公司是:
签名= 消息^D mod N
这个公式和公钥密码中解密的操作是等同的,也就是说可以将“请对消息签名”这一请求理解为你“请解密消息”。利用这一点,攻击者可以发动一种巧妙的攻击,即利用数字起那么来破译密码。
我们假设现在Alice 和Bob进行通信,主动攻击者Mallory正在窃听。Alice用Bob的公钥加密消息后发送给Bob,发送的密文是用下面的公式计算出来的。
密文=消息 ^E mod N
Mallory窃听到Alice发送的密文并将其保存袭来,由于Mallory想要破译这段信息,因此他给Bob写了这样一封信。
Mallory将刚刚窃听到的密文作为上述邮件的附件一起发送给Bob,即
附件数据=密文
当Bob看到了Mallory的邮件,发现附件数据的确只是随机数据,于是Bob对附件数据进行了签名,具体情形如下:
签名 = 附件数据^D mod N (RSA生成签名)
= 密文^D mod N (附件数据实际上是密文)
= 消息 (进行了解密操作)
Bob的本意是对随机的附件数据施加数字签名,但结果却无意中解密了密文。如果不小心将上述签名的内容发送给了Mallory,那么Mallory就这么破译了密文了。
对于这样的攻击,我们应该采取怎样的对策呢?
首先,不要直接对象进行签名,对散列值进行签名比较安全;
其次,公钥密码和数字签名最好分别使用不同的密钥对。
实际上,GnuPG和PGP都可以生成多个密钥对。
然后,最重要的是就是绝对不要对意思不清楚的消息进行签名,尤其是不要对看起来只是随机数据消息进行签名。
潜在伪造
如果一个没有私钥的攻击者能够对有意义的消息生成合法的数字签名,那么这个数字签名的算法一定是不安全的,因为这样的签名时可以被伪造的。
然而,即使签名的对象是无意义的消息,如果攻击者能够生成合法的数字签名,我们也应该讲其当成是对这种签名算法的一种潜在威胁。这种情况称为对数字签名的潜在伪造。
为了应对潜在伪造,人们在改良RSA的基础上开发出一种签名算法,叫作RSA-PSS。其不是对消息本身进行签名,而是对其散列值进行签名。另外,为了提高安全性,在计算散列值的时候还要对消息加盐。
其他攻击
针对公钥密码的攻击方法大部分都能够用于攻击数字签名,例如用暴力破解来找出私钥,或是尝试对RSA的N进行质因数分解等。
各种密码的比较
混合密码系统与对散列值签名
在混合密码系统中,消息本身是用对称密码加密的,而只有对称密码的免邮是公钥密码加密的,即在这里对称密码的密钥就相当于消息。
另一方面,数字签名也使用了同样的方法,将消息本身输入单向散列函数求散列值,然后再对散列值进行签名,在这里散列值相当于消息。
如果将两者的特点总结一下,我们可以说:对称密码的密钥是机密性的精华,单向散列函数的散列值是完整性的精华。
数字签名无法解决的问题
用数字签名既可以识别出篡改和伪装,还可以防止否认。也就是说,我们同时实现了确认消息的完整性、进行认证以及否认防止。
然而要真正使用数字签名,有一个大前提,那就是用于验证签名的公钥必须属于真正的发送者。即便数字签名算法在强大,如果你得到的公钥是伪造的,那么数字签名也会完全失效。
为了能够确认自己的公钥是合法的,我们需要使用证书。所谓证书,就是将公钥当作一条消息,由一个科学的第三方对其签名后所得到的公钥。