然而它太慢了

非对称加密算法有一个重大缺点——加密速度慢,或者说得更拽一些,编码率比较低。例如在上一篇里我给Clark传的那个1GB的小电影,进行非对称加密足足用了66小时。那个借条小一些吧,也用了将近2分钟。所以在实际使用非对称加密的时候,往往不直接对文件进行加密,而是使用摘要算法与非对称算法相结合(适用于数字签名)或对称加密和非对称加密相结合(适用于加密传输文件)的办法来解决或者说绕过非对称加密算法速度慢的问题。
 
摘要算法

摘要算法,又叫作Hash算法或散列算法,是一种将任意长度的输入浓缩成固定长度的字符串的算法,注意是“浓缩”而不是“压缩”,因为这个过程是不可逆的。它的特点是:
    1. 不同内容的文件生成的散列值一定不同;相同内容的文件生成的散列值一定相同。由于这个特性,摘要算法又被形象地称为文件的“数字指纹”。
    2. 不管文件多小(例如只有一个字节)或多大(例如几百GB),生成的散列值的长度都相同,而且一般都只有几十个字符。
这个神奇的算法被广泛应用于比较两个文件的内容是否相同——散列值相同,文件内容必然相同;散列值不同,文件内容必然不同。如果您用过BT或eMule,应该对散列值比较熟悉了,右图分别是BT和eMule的文件详细信息的截图。

细心的朋友可能已经注意到了,BT和eMule的散列值的长度不一样,这是因为它们所使用的摘要算法不同,目前比较流行的摘要算法主要有MD5和SHA-1,您可以在.Net的System.Security.Cryptography命名空间找到它们的身影。
另,由于本篇是只重理解和应用的白话文,所以上面对摘要算法的讨论并不十分全面严谨,喜欢看文言文的朋友可以看这篇《Hash 算法及其应用》。还有就是MD5和SHA-1算法已经从理论上被山东大学王小云教授及其研究小组破解(向中国的科学家致敬!),不过并不是这两个算法从此就不能用了。 



实际对文件作数字签名的方法

由于非对称加密的速度实在太慢了,所以在实际对文件作数字签名的时候,例如对上一篇中我用Word写给Clark的借条进行签名,总是先生成这个借条的散列值,然后用我的私钥对这个散列值进行非对称加密,然后把加密后的散列值(我们就叫它“散列值密文”吧)和借条一同发送到Clark那里。Clark在收到借条和散列值密文后,用从网上下载的我的公钥将散列值解密,然后Clark自己再生成一次借条的散列值,比对这两个散列值是否相同,如果相同,就叫作验证签名成功。由于散列值只有几十个字节,所以签名的速度还可以忍受。看下图会更直观一些。


思考题

虽然我们只是对借条的散列值进行了非对称加密,但是此过程仍然具有防篡改、防抵赖的作用,为什么?

 又太麻烦了

我们费了好大的劲终于解决了数字签名速度慢的问题。但是上面那个复杂的签名过程用户能接受吗?当然不能!所以我们必须要开发出一个数字签名的程序来简化签名过程,最好让数字签名看起来就跟传统的盖章差不多。这样的程序已经有了,叫作电子签章程序。 它是一个桌面程序,一般以Word或Excel插件的形式存在。下面就演示一下用电子签章程序对我的借条进行签名的过程。
1. 安装了电子签章程序后,Word和Excel中就会多出一个签名用的工具条。

















2. 写好借条,存盘。然后用鼠标点击“添加电子签章”按钮。然后在需要显示印章图片的位置上再按一次鼠标左键。
















3. 电子签章程序会弹出一个对话框,注意在这步一定要勾选“签章后锁定文件”复选框,至于为什么要这样,稍后再讲。然后点击确定按钮。
















4. 在上一步按确定按钮后,电子签章程序还会提示要求我输入存放私钥的USB-Key的使用密码,然后Word中就会出现一个印章了。这个印章图片是我提供给数字证书中心,在制作USB-Key的时候就烧录在USB-Key之中的。


















5. 之后我把借条发送给Clark。Clark想验证签名的话只要按“验证所有印章”就可以了。电子签章会弹出如左图所示的对话框。













是不是即直观又简单?那么诸如“散列值”、“公钥证书”这些东东都跑到哪里去了呢?它们都被电子签章程序插入到Word文档中的某个特定的地方了,如果你熟悉Word文档的结构,是不难找到它们的。

电子签章程序的Bug

电子签章程序本来可以支持两种用法:
    1. 在上面的第3步不勾选“签章后锁定文件”复选框,这样在进行了数字签名之后,仍然可以更改Word文档的内容。当然如果在进行了数字签名之后又更改了Word文档的内容,验证签名操作就会失败。这时需要再次进行签名操作。
    2. 在上面的第3步勾选“签章后锁定文件”复选框,这样在进行了签名操作后,Word文档的内容就再也无法更改了。
但是,电子签章程序有一个大Bug——在进行了签名操作后,如果只是更改了文字的颜色,验证签名操作仍然会成功。这就意味着,如果我在Word中写到“向公司借款2000元”,然后把“2000”的最后一个0的颜色改为白色,在领导看来就是“向公司借款200 元”。领导欣然签章,然后我再把那最后一个0的颜色改为黑色,就又变成了“向公司借款2000元”,而且验证签名居然会成功。这也是为什么我在上面的第3步要强调一定要勾选“签章后锁定文件”复选框了。我猜测造成这个Bug的原因很可能是因为电子签章程序仅仅对文档中的纯文本生成散列值,而不是对文本+全部格式信息一同生成散列值。大家在购买电子签章程序前一定要作这方面的测试。

数字信封

我们可以通过使用信息摘要技术解决数字签名的速度问题,那么数字加密的速度问题怎么解决呢?相信除了我和Clark以外,很少有人愿意为传送一个小电影而等待66个小时。其实这个问题也简单,我们可以用对称加密与非对称加密相结合的方式来解决这个问题。对称加密速度快,但是必须在传送密文的同时传送解密密钥;非对称加密速度慢,但是不需要传送解密密钥。把两个技术一起使用,各取优点,就OK了。方法是,先把小电影用对称加密算法加密,然后把解密密钥用非对称加密算法加密。再将小电影的密文与解密密钥的密文同时传送给Clark。Clark收到这两样东西后,先用自己的私钥将解密密钥的密文解密,得到解密密钥,再用解密密钥将小电影的密文解密,就得到了小电影的明文。Clark收到的这两样东西——小电影的密文和解密密钥的密文——加在一起就叫作数字信封。看下图会更直观一些。


数字证书

非对称加密的公钥和私钥的长度都很长,一般都在1024位以上。这么长且无规律的密码,用户是记不住的,所以只能保存在文件中啦。保存了公钥的文件就叫作数字证书。且慢,这个定义是十分错误的!为什么呢?想一想第1篇里的那个我给Clark发送小电影的例子。例子中我在网上下载了Clark的公钥(也就是数字证书),然后用它对小电影进行非对称加密,然后心想只有拥有Clark的私钥的Clark才能解密——Clark的老婆一定没辙啦。没想到螳螂捕蝉,黄雀在后,我下载Clark的公钥的那个网站是Clark的老婆制作的钓鱼网站!里面的公钥证书统统都是Clark的老婆的公钥!!结果呢,我的小电影用Clark的私钥解不开,反倒是只有用Clark老婆的私钥才能解开,用Clark的话来说,就是“无语了......”。
    所以聪明的你一定想到了,数字证书之所以可以称之为“证书”,就一定要有“防伪”功能。方法是,数字证书里不但要包含Clark的公钥,还要包含Clark的自然信息(姓名、单位等),并且最重要的,要有证书颁发部门对这些信息的数字签名(每个证书颁发部门也都有自己的数字证书——称之为根证书——和与之配对使用的私钥)。这样我就可以验证数字证书的真伪了。所以,让我们重新定义数字证书,数字证书是由一个权威机构发行的,至少包含一个公开密钥、证书持有人(或单位)的名称以及证书授权中心对这些信息的数字签名的文件。一般情况下证书中还包括密钥的有效时间,发证机关(证书授权中心)的名称,该证书的序列号等信息,证书的格式遵循ITUT X.509国际标准。

 
您可以使用IE的菜单“工具 | Internet 选项... -> 内容 -> 证书... -> 受信任的根证书颁发机构”来查看IE中已经安装的根证书。点击“导入...”按钮可以导入新的根证书。


















复制破解的解决方案——USB Key

我们已经知道, 非对称加密的密钥很长,一般都在1024位以上,所以只能保存在文件里。好,我把私钥文件保存在了硬盘上,却难保哪天这个文件不会被某个坏蛋拷贝走。然后,在这个“没有人知道你是一条狗”的网络世界里,他就变成了我——他可以冒充我写借条甚至向银行贷款;他可以冒充我跟别的公司签署上亿美元的合同;他甚至可以冒充我签署卖身契,300块钱就把我卖了——而我却懵然不知。直到有一天,我突然发现自己突然增加了几百万外债、公司把我Fire了、一个9岁的小女孩拿着卖身契等在我家门口声称我已经是她的奴隶......
所以千万不能把私钥保存在硬盘上。那么保存在U盘上,并且把U盘放在内裤的口袋里怎么样呢?好像好了一些,但是你在签名的时候还是得把U盘插在电脑上吧?可知道你的电脑中有多少木马程序正在用For循环扫描你的USB端口,就等着拷贝你的私钥?
我们需要的是无论如何也不可能被别人复制的私钥保存方案,USB Key应运而生。USB Key是一种USB设备,外形就跟U盘一样,只不过无法用它来存取文件。证书发行单位会使用特殊的设备将你的数字证书、私钥和电子签章程序所要使用的印章图片烧录到USB Key中。你无法使用资源管理器或木马程序取得USB Key中的私钥,当需要用私钥进行签名时,直接通过USB Key的驱动程序提供的API将明文传输到USB Key中,由USB Key中的加密芯片对明文进行加密,加密结果会以API函数的返回值的形式返回,这样就可以有效解决私钥被坏蛋复制的问题了。还有就是USB Key本身还有一个简短的使用密码,每次加密前使用者必须输入正确的使用密码方能使用,这样即使USB Key不慎丢失,也不用担心了。

USB Key的缺点

USB Key有一个不大不小的缺点——速度有点慢。例如我手里正在试用的这款USB Key,连续签10个像“1234”这样的数据需要约13秒。这意味着如果你的信息系统只提供一次一条数据的签名方式,那么这1秒钟的延迟用户根本感觉不到;但是也有很多领导喜欢一次批量签名100条数据,那么就需要用2分钟来完成这项工作。经我本人测试以及向数字证书认证单位技术人员确认,速度的瓶颈主要在于数据往返于信息系统程序与USB Key之间所消耗的时间较长。所以很难通过优化信息系统程序或使用具有更快芯片的USB Key的方法来提高速度。











本篇到此结束,下一篇将专门介绍在B/S信息系统中对数据库中的信息进行数字签名的一些问题和解决方法。并在最后给出一个十分实用的DEMO。
posted on 2007-09-19 14:18  1-2-3  阅读(16333)  评论(55编辑  收藏  举报