数字签名的基础知识、如何使用公钥密码实现数字签名。

使用RSA具体实践数字签名的生成和验证。

探讨针对数字签名的攻击方法以及数字签名与消息验证码之间的关系。

数字签名可以识别篡改和伪装,还可以防止否认。

数字签名是一种非常重要的认证技术,前提是用于验证签名的发送者的公钥没有被伪造。

数字签名

数字签名用于解决消息认证码的遗留问题,即无法防止否认。

发送者生成签名,接收者验证签名。

收发双方使用不同的密钥,确保接收者不能生成签名。

接收者验证签名成功,即可确认消息来自于发送者。

生成与验证

数字签名说明
生成消息签名由消息的发送者完成
验证消息签名由消息的接收者或第三方验证者来完成
签名密钥由签名的人持有,用来生成消息签名
验证密钥任何需要验证签名的人,使用验证密钥无法生成签名。

公钥密码中,加密密钥是任何需要加密的人都可以持有,而数字签名时,只有生成签名的人才可以持有签名密钥(这和公钥密码中的解密密钥类似)。

数字签名就是通过将公钥密码“反过来用”而实现的,公钥密码与数字签名的密钥使用方式:

私钥公钥
公钥密码接收者解密时使用发送者加密时使用
数字签名签名者生成签名时使用验证者验证签名时使用
谁持有密钥?个人持有只要需要,任何人都可以持有

公钥密码与数字签名

公钥加密流程如下:

数字签名流程如下:

根据公钥密码的特性:如果用公钥成功解密了密文,那么就能够证明这段密文是用与该公钥配对的私钥进行加密而得到的(用私钥进行加密只能由持有私钥的人来完成)。

依据上述特性,则可以将用私钥加密的密文作为签名来对待。同时由于公钥是公开的,所以任何人都可以用公钥对签名进行验证。

签名方法

对消息签名

sequenceDiagram     participant 发送者     participant 接收者     autonumber     发送者 ->> 发送者: 用私钥对消息进行加密,生成签名     发送者 ->> 接收者: 消息和签名     接收者 ->> 接收者: 用公钥对签名解密     接收者 ->> 接收者: 解密得到的消息和接收到的消息对比

对消息散列值签名

sequenceDiagram     participant 发送者     participant 接收者     autonumber     发送者 ->> 发送者: 单向散列函数计算消息的散列值     发送者 ->> 发送者: 私钥加密散列值     发送者 ->> 接收者: 消息和签名     接收者 ->> 接收者: 公钥解密签名     接收者 ->> 接收者: 解密的到的散列值对比计算消息得到的散列值

释疑

密文为什么能作为签名使用

数字签名主要解决的问题难点在于防止否认,即可以根据接收到的消息确定消息的发送者。

而能够用公钥解密的密文,根据公钥加密原则,可以确定该密文只能由持有私钥的人生成,由此就可以确定发送者。

并且这里的密文并不是来确保机密性的,而是用来防止否认。

签名可以随意复制么

数字签名可以附加在消息的末尾,也可以和消息分离、单独作为文件来发送。

每个人都可以复制任意个内容相同的副本,但签名是否为原件并不重要。

签名的意义在于将特定的签名者与特定的消息绑定在一起,即可以通过签名来确定特定消息的发送者。所以就算复制任意份签名,并不能改变这一事实。

消息内容会不会被任意篡改

签名之后也可以对签名和消息进行修改,但是修改之后,验证签名就会失败。

验证签名失败,即意味着不能通过消息和签名来确定发送者。

如何防止否认

防止否认与“谁持有密钥”密切相关。

消息认证码中,能够计算MAC值的密钥是由收发双方共同持有的,因此收发双方都可以指认是由另一方计算的。

数字签名中,能够生成签名的密钥只有发送者才持有,只有发送者才能够生成签名,因此发送者无法否认(除非发送者说密钥被盗)。

应用实例

安全信息公告

一些信息安全方面的组织会在其网站上发布一些关于安全漏洞的警告,那么如何确认这些警告信息是该组织所发布的,如何确认发布这些信息的网页是否经过篡改。

这种情况就可以使用数字签名,即该组织可以对警告信息的文件施加数字签名。

但这种信息发布的目的是让尽可能多的人知晓,因此无需对信息进行加密。这种对明文直接所施加的签名,一般称为明文签名。

软件下载

攻击者有可能会同时篡改网页上的软件和公布的哈希码。

为了防止出现这样的问题,软件的作者可以对软件加上数字签名,只要在下载之后验证数字签名,就可以识别出软件是否遭到攻击者篡改。

公钥证书

在验证数字签名时需要合法的公钥,那么怎么知道得到的公钥是否合法?

可以将公钥当作消息,对其加上数字签名。

对公钥世家数字签名得到的就是公钥证书。

SSL/TLS

SSL/TLS在认证服务器身份是否合法时会使用服务器证书,这就是加了数字签名的服务器公钥。

相对地,服务器为了对客户端进行认证也会使用客户端证书。

简单实现

RSA实现数字签名

在RSA中,被签名的消息、密钥以及最终生成的签名都是数字。在对文本进行签名时,需要先将文本编码为数字。

术语说明
公钥数$E$和数$N$
私钥数$D$和数$N$
生成签名$签名 = 消息^{D} \mod N$
验证签名$签名得到的消息 = 签名^{E} \mod N$

实践

取公钥$E=5; N=323$, 私钥$D=29;N=323$,消息为$123$。

生成签名:$123^{29} \mod 323 = 157$。

验证签名:$157^{5} \mod 323 = 123$。

其他数字签名算法

算法作者用途说明
ElGamalTaher ElGamal公钥密码和数字签名公钥算法,利用$\mod N$中求离散对数的困难度
DSA(Digital Signature Algorithm)NIST,1991年数字签名NIST于1991年制定的数字签名规范DSS。
ECDSANIST数字签名算法一种利用椭圆曲线密码来实现的数字签名算法。
RabinM.O.Rabin公钥密码和数字签名利用在$\mod N$ 中求平方根的困难度。

攻击

中间人攻击

针对公钥密码的中间人攻击,对数字签名也具有威胁。

要防止中间人攻击,就需要接收者确认自己得到的公钥来自正确的发送者。

单向散列函数攻击

数字签名中的的单向散列函数必须具有抗碰撞性,否则攻击者就可以生成另外一条不同的消息,使其于签名所绑定的消息具有相同的散列值。

利用数字签名攻击公钥密码

  1. 攻击者截取公钥密码发送的密文。
  2. 攻击者将密文作为附件发送给接受者,请求接收者对其签名(其实相当于解密)并返回签名。

解决方式:不要对消息本身进行签名,应该对消息的散列值进行签名。

密码技术对比

对称密码公钥密码
发送者用共享密钥加密用公钥加密
接收者用共享密钥加密用私钥解密
密钥配送问题存在不存在,但公钥需要另外认证
机密性
消息认证码数字签名
发送者用共享密钥计算MAC值用私钥生成签名
接收者用共享密钥计算MAC值用公钥验证签名
密钥配送问题存在不存在,但公钥需要另外认证
完整性
认证✅仅限通信对象双方✅可适用于第三方
防止否认

混合密码系统中,消息由对称密码加密,对称密码密钥由公钥密码加密。

数字签名中,消息本身通过单向散列函数得到散列值,再对散列值进行签名。

对称密码的密钥是机密性的保证;单向散列函数的散列值是完整性的关键。

遗留问题

数字签名可以识别篡改、伪装以及防止否认。

但是正确使用数字签名的一个大前提是用于验证签名的公钥必须属于真正的发送者,即用于验证签名的公钥没有被伪装。

这就形成了一个死循环。

问题的解决方法:将此数字签名中使用的公钥作为另一个可信数字签名的消息进行签名,并发送。这样就可以保证该数字签名的公钥的合法性。

将公钥作为消息并对其进行签名的结果就是证书

这样也只是转移问题,关键问题是建立一个可信的数字签名链条。

目前的解决方法是建立公钥基础设施(Public Key Infrastructure) 简称PKI,来完成这项工作。