学习《图解密码技术》补充密码学相关基础知识过程中所做的简单学习笔记,只记录要点,所用图例的来源均为《图解密码技术》一书。
本篇主要参考本书第九章——数字签名
引子
消息到底是谁写的?
我们知道,消息认证码的认证功能只能在消息发送者和消息接收者二者之间使用,无法向第三方证明,也无法防止抵赖。这两个问题就由数字签名技术来解决啦
从消息认证码到数字签名
消息认证码之所以无法防止否认以及无法向第三方证明,是因为它需要发送者和接收者之间共享密钥,换而言之,发送者和接收者都拥有这个密钥,都可以使用这个共享密钥生成消息认证码MAC,因此对于第三方来说,无法判断这条消息确实是由“发送者”发送的。
因此可以看到,消息认证码局限性的根本原因在于用于计算消息认证码的密钥并非只有发送者一人拥有(接收者也拥有)。因此在数字签名技术中,为了解决这些个需求,让生成数字签名的发送者和验证数字签名的密钥不相同,也就是说,消息发送者使用自己的密钥(私钥)生成数字签名,而消息接收者(或者说需要认证消息的一方)使用另一个密钥(公钥)去验证数字签名,这样就可以向第三方证明,也可以防止抵赖了,因为生成数字签名的密钥只有消息发送者自己拥有!这个理念和公钥加密非常相似。
签名的生成和验证
在数字签名技术中,有两个行为:
生成消息签名
生成消息签名这一行为是由消息的发送者来进行的,也称为“对消息签名”。根据消息内容以及自己的私钥计算出数字签名的值。
验证消息签名
验证数字签名这一行为一般是由消息的接收者来进行,但也可以由需要验证消息的第三方来完成。验证的时候使用消息内容以及自己的公钥来验证数字签名。
这里有两个密钥,一个签名密钥,一个验证密钥。签名密钥是消息发送者自己持有的,而验证密钥则是任何需要验证该签名的人都可以持有。消息的发送者使用自己的私钥(签名密钥)来生成签名,而消息的验证者使用公钥(验证密钥)来验证消息的签名,注意,前者是“生成”签名,后者是“验证”签名,意思是使用验证密钥是没办法计算出数字签名的,这也是数字签名具有抗抵赖功能的原因。
公钥密码与数字签名
从前面的描述其实可以看出,数字签名好像是将公钥密码反过来用的样子。数字签名中同样使用了一个公钥和私钥,而这个密钥对的使用与公钥密码中的使用是完全相反的(严格来说,RSA算法中的公钥加密和数字签名是完全相反,其他算法不一定),即,公钥密码中使用公钥来加密、使用私钥来解密,而数字签名中使用私钥来加密(生成签名)、使用公钥来解密(验证签名)。
在公钥加密算法中,使用公钥加密所得到的密文,只有使用与之对应的私钥才能解密;同样的,使用私钥加密所得到的密文,也只能用与该私钥配对的公钥才能解密。也就是说,如果某个公钥(验证密钥)成功解密了密文(验证签名),那么就能够证明这段密文是用与这个公钥对应的私钥(签名密钥)来加密(生成签名)所得到的。
用私钥进行加密这一行为只能由持有私钥的人完成,正是基于这一事实,我们才可以将使用私钥加密的密文作为签名来对待,这也是数字签名技术能够有抗抵赖(防否认)功能的原因。而且,由于公钥是公开的,任何人都可以使用公钥去解密密文(验证数字签名),因此,数字签名具备向第三方证明的功能。
公钥密码与数字签名的相反特性如下图所示:
数字签名的方法
有两种生成和验证数字签名的方法:
- 直接对消息签名
- 对消息的散列值签名
直接对消息签名
发送者事先准备一个公钥和私钥,私钥自己持有,而公钥给需要验证签名的消息接收者或者其他第三方持有。
具体步骤如下:
- 发送者A使用自己的私钥对消息进行加密。
- 发送者A将消息和数字签名发送给B。
- B使用A的公钥对收到的签名进行解密。
- B将「步骤3」解密的结果与A发过来的消息进行比对,如果两者一致,则签名验证成功,反之签名验证失败。
如下图所示
对消息的散列值签名
上面介绍的是直接对消息进行签名的方法,但是公钥密码本身计算就慢,如果消息还比较长的话,这个过程就会很慢很耗时。因此,可以使用单向散列函数,无论是多长的消息最终计算出的散列值都是固定的长度。先用单向散列函数计算出消息的散列值,然后再对散列值进行加密(签名)就非常轻松的。
- 发送者A使用单向散列函数计算消息的散列值。
- 发送者A使用自己的私钥对散列值进行加密。加密得到的结果就是数字签名。
- 发送者A将消息和数字签名发送给接收者B
- 接收者B使用发送者A的公钥对收到的数字签名进行解密,得到一个比特序列。
- 接收者B计算发送者A发来的消息的散列值,并将「步骤4」得到的结果与消息的散列值比对,如果两者一致,则签名验证成功,反之则签名验证失败。
如下图所示:
按照时间轴来整理一张时间流程图:
数字签名的应用
安全信息公告
一些信息安全组织会在其网站上发布一些关于安全漏洞的安全公告。为了防止发布这些信息的页面被第三方篡改,就可以使用数字签名技术,对警告的信息进行签名,这样一来所有人都可以验证警告信息的发布者是否合法。这种对明文消息所施加的签名也叫明文签名。
软件下载、校验
软件作者可以对软件加上数字签名,只要在下载后对软件验证数字签名,就可以识别软件是否遭到了篡改。
另外,安卓操作系统中是无法安装没有数字签名的应用软件的。在签署数字签名时,为了识别应用开发者的身份,还要使用到“证书”技术。不过,这个证书只被用来识别应用开发者的身份信息。
公钥证书
之前学习公钥密码的时候提到过,如何判断自己手上的公钥到底是不是合法的呢?可以对公钥进行数字签名,这就是公钥证书了。
SSL/TLS
SSL/TLS在认证服务器身份呢是否合法时会使用服务器证书,它就是加上了数字签名的服务器公钥。同理,服务器为了对客户端(用户)进行认证也会使用客户端证书。
数字签名的局限性
用数字签名既可以识别出篡改和伪装,还可以防否认。然而,要正确使用数字签名有一个大前提。那就是用于验证签名的公钥必须属于真正的发送者,否则就会存在中间人攻击的风险。即便数字签名算法再强大,如果你得到的公钥是伪造的那也没用。
现在就存在一个死循环了:数字签名被用来识别消息篡改、伪装、以及否认,但是为此我们又必须从没有被伪装的发送者得到没有被篡改的公钥才行。
为了能够确认自己得到的公钥是否合法,我们需要使用证书。所谓证书,就是将公钥当作一条消息,由一个可信的第三方对其签名后所得到的公钥。
当然,这样的办法其实也只是把问题转移,因为对证书上是假的数字签名进行认证时又需要另一个公钥。那么,如何才能构筑一个可信的数字签名链条?又由谁来颁发可信的证书?
这就已经踏入了社会学的领域了,我们需要让公钥以及数字签名技术称为一种社会性的基础设施,即公钥基础设施(Public Key Infrastructure),简称PKI。关于证书和PKI,继续往下学习^^.