第一篇:数字签名及安全电子邮件
数字签名及安全电子邮件
一、背景知识
使用个人证书,在电子邮件中至少有以下功能。
保密性:你可以使用收件人的数字证书对电子邮件进行加密。这样,只有收件人的私钥才能解密这封邮件,即使第三方截获邮件,由于没有收件人的私钥,也无法阅读该邮件。当然,要发送加密电子邮件,必须先拥有对方的数字证书。
认证身份:你可以使用你本人的数字证书对电子邮件进行数字签名,这样,收件人通过验证签名就可以确定你的身份,而不是他人冒充的。
完整性:如果验证数字签名有效,收件人不仅可以认证你的身份,还可以确信收到的邮件在传递的过程中没有被篡改。
不可否认性:数字签名要使用你本人数字证书中的私钥,而私钥仅你个人所有,所以,你不能对发送过的签名邮件进行否认。
1、电子邮件的重要性
由于越来越多的人通过电子邮件发送机密信息,因此确保电子邮件中发送的文档不是伪造的变得日趋重要。同时保证所发送的邮件不被除收件人以外的其他人截取和偷阅也同样重要。
通过使用 Outlook Express 和 Foxmail,可以在电子事务中证明身份,就象兑付支票时要出示有效证件一样。也可以使用数字证书来加密邮件以保护邮件的保密性。数字证书结合了 S/MIME 规范来确保电子邮件的安全。
2、对电子邮件进行数字签名 对电子邮件进行数字签名,能够确保电子邮件中发送的文档不是伪造的,即收件人能够确信该邮件来自于其声称的发件人,同时邮件从发件人的机器传达到接收人的机器没有经过任何改动。
当发件人在待发邮件中添加数字签名时,发件人就在邮件中加入了数字签名和自己的数字证书。邮件的接收方接收到该邮件后,首先判断发件人的证书是否有效(该证书是否是可信任的CA签发的,该证书是否在有效期内,该证书是否已经被撤销),如果证书有效,从发件人的证书中提取公钥信息,来验证邮件的数字签名是否有效。
3、对电子邮件进行加密 对电子邮件进行加密(使用接收人的数字证书中的公钥进行加密)可以保证所发送的邮件不被除收件人以外的其他人截取和偷阅。
当发件人对邮件进行加密时,使用接收人的数字证书中的公钥对邮件进行加密。邮件的接收方接收到该邮件后,使用自己的私钥对邮件进行解密,可以得到邮件的明文。因为使用公钥加密的数据,只有对应的私钥才可以解密,而对一封加密邮件来说,只有接收人才具有对应的私钥,也就是只有接收人才可以对邮件解密得到邮件的明文。其他任何人截获了该邮件都是无法识别的乱码。有效的保证了邮件内容的保密性。
4、电子邮件证书使用的简易性 如果接收到有问题的安全邮件,例如邮件已被篡改或发件人的数字证书已过期,则在被允许阅读邮件内容前,会看到一条安全警告,它详细说明了问题所在。根据警告中的信息,接收人可以决定是否查看邮件。
以上所述的签名和加密邮件的过程都是由邮件客户端程序(如Microsoft Outlook,Foxmail、Netscape Messager等)来完成。对于邮件的发送人来说,就是在邮件发送之前,简单的点击“签名”和“加密”按钮就可以了;对于邮件的接收人来说,邮件接收到后,邮件客户端程序更能够自动对签名邮件进行验证,对加密邮件进行解密,并将验证和解密结果显示给邮件的接收人,不需要任何人工操作,非常方便。
5、安全电子邮件的工作方式
安全电子邮件的工作方式有两种:
第一种情况是采用个人或单位证书发送安全电子邮件。如吉林省数字证书认证中心、广东省数字证书认证中心等就颁发个人证书或单位证书,然后你可以选择用这两种证书发送安全的电子邮件。
第二种方式是直接给电子信箱的所有人或单位的电子信箱地址颁发数字证书,如江西省数字证书认证中心、安徽省数字认证中心等就颁发专门的邮件证书。
由于以上两种方式的原理基本一样,考虑到网上的免费资源,我们以第一种方式为主加以说明。
当然,在第一种方式中使用单位证书发送安全邮件的原理基本一样,由于网上单位证书的免费资源很少,因此,我们重点以个人证书为例。另外,要发送安全电子邮件,必须使用一些电子邮件客户端软件,如Outlook Express、Foxmail等,打开网页收发邮件是不能进行数字签名的,我们这里以Outlook Express 5.0为例,说明安全电子邮件的发送过程。
二、实验目的及要求
1、掌握用Outlook Express发送数字签名电子邮件的方法。
2、掌握用Outlook Express发送加密电子邮件的方法。
三、实验准备
1、上网计算机,IE5.0以上,Outlook Express 5.0以上。
2、已经申请好个人数字证书(本实验以在广东省数字证书认证中心申请的个人免费证书为例)。
四、实验过程
1、修改电子邮件帐号属性,绑定证书
(1)在Outlook Express5.0单击“工具”菜单中的“帐号”,选取邮件选项卡中的用于发送安全电子邮件的邮件帐号,然后单击“属性”,选择安全标签,在签名证书标识项后,点击选择按钮,如图9.1所示。
图9.1 安全属性
(2)选择数字证书,如图9.2、图9.3所示。
图9.2 选择签名证书
图9.3 已经设置好签名证书
3)如果希望对方能给你发送加密电子邮件,则点击加密首选项,再选择你的证书及算法,如图9.4所示。
图9.4 已经设置好签名和加密数字证书
2、发送数字签名电子邮件
(1)打开Outlook Express,点击新邮件,输入对方的邮件地址,并点击“签名”按钮,然后点击发送,如图9.5所示。
图9.5 撰写数字签名邮件
(2)对方用Outlook Express收到你的邮件后,首先显示图9.6所示提示。
图9.6 收到数字签名邮件
(3)点击继续,打开邮件,如图9.7所示。
图9.7 打开签名邮件
3、发送加密电子邮件
(1)当用户拥有了对方的数字证书,并添加到通讯薄中就可以向对方发送加密的电子邮件了,如图9.8所示。
图9.8 通讯簿中查看对方数字证书
(2)打开Outlook Express,点击新邮件,输入对方的邮件地址,并点击“加密”按钮,如图9.9所示。
图9.9 发送加密电子邮件
(3)对方用Outlook Express收到邮件后首先显示图9.10所示的提示。
图9.10收到加密电子邮件
(4)点击继续,打开邮件,如图9.11所示。
图9.11 打开加密电子邮件
(5)如果你没有对方的数字证书,是不能发送加密邮件的,如图9.11、图9.12所示。
图9.11 无对方证书发送加密邮件
图9.12 系统提示出错
(6)当然,也可以发送同时加密和签名的电子邮件,如图9.13、图9.14、图9.15所示。
图9.13 同时发送签名和加密邮件
图9.14 收到签名和加密邮件
图9.15 打开签名和加密邮件
至此,我们已经完成了安全电子邮件的全部操作,即如何发送加密的和签名的电子邮件,需要指出的是,有许多免费邮箱是在网页下收发邮件的,在此情况下一般不能使用数字证书。
五、练习与思考
1、加密邮件与签名邮件有什么区别?
2、随着中华人民共和国电子签名法的颁布实施,你认为签名电子邮件具有法律效力吗?
3、为什么发送加密邮件需要对方的数字证书?其加密原理是什么?
4、能用他人的证书发送签名邮件吗?为什么?
5、请用FOXMAIL设置签名及加密邮件,比较与Outlook express的异同。
第二篇:PDF数字签名
制做PDF文件电子签名的方法
1、在一张白纸上写一个您最得意的签名,并扫描或用数码像机将签名转为图片文件;
2、用photoshop打开上面做好的签名图片文件,裁切成刚好能容纳您签名的大小,并 去掉图片的背景颜色(方法详见后附),将处理好的图片另存为.GIF 图片格式文件待用;
3、打开Adobe Acrobat 9 Pro(本制做方法适用于Adobe Acrobat 9 Pro 版本,其它 版本请做相应调整),任意新建一个PDF文件;
4、点击Adobe Acrobat 9 Pro 工具栏中的“签名”—“放置签名”,并用鼠标在新建的 那个PDF文件中画一个长方形的签名区(名字相签多大就画多大);
5、在随后弹出的窗口中选择“我要立即创建新的数字签名”,并点“下一步”;
6、在下一个窗口选择“新建PKCS#12数字身份证文件”,并点“下一步”;
7、在弹出的新窗口中输入“姓名”、“部门”,“单位名称”,“电子邮件地址”(以上这些 都只能输英文或拼音,不支持汉字);然后选择国家并点“下一步”;
8、在接下来弹出的窗口中选择电子签名文件制做好后要存放的文件夹,输入并确认您 以后签名时验证身份要用的密码;最后点击“完成”
9、在“签名文档”窗口中的“签名为:”档中选择“新建ID”,在“外观(A):”栏选择 “创建新外观„”;
10、弹出的“配置签名外观”窗口中的标题栏输入这类签名的标识,例:“无日期签名” 等等;在“配置图形”--“显示:”中选择“导入的图形(I)”并点击“文件(F)„”;从“选择图片”窗口的“浏览(B)„”中找到第2步制做好的图片文件并点“确定”返回;这时您就可以“配置签名外观”窗口的“预览”栏中看见您手写的签名了;您也会看到,除了您的签名外,它后面还跟着一些其它信息;这些信息是通过“配置文本”-“显示:”后面的选择项来控制的,您可以根据您的签名需要选择;
11、至此,点“确定”后,您的电子签名就算制做完成了,以后在签名时,只需重复第 4步并输入密码就OK了!
12、如果需要在签名时同时输入签名“原因”,就需要在“配置签名外观”窗口的“配 置文本”选项中勾选上“原因”,点击“确定”完成电子签名制做后,再在“编辑”菜单栏选择“首选项”—“种类”—“安全性”—“高级首选项”—“创建”标签中勾选“签名时显示原因”。这样,以后签名时就可以输入您的签名“意见”(原因)了;
13、如果您对刚才制做的这个签名不满意,可以在Adobe Acrobat 9 Pro 工具栏中的“高 级”—“安全性设置”,中删除这个数字身份证;如果你想对制做好的签名做一个备份,以后电脑系统重装后可以直接导入使用,您也可以在这个窗口中将您制做好的“数字身份证”导出保存。
14、对于您不满意的签名外观,可以在“编辑”菜单栏选择“首选项”—“种类”—“安 全性”—“外观”栏中进行“编缉”或“删除”;也可以在此处应用“新建”按钮直
名人堂:众名人带你感受他们的驱动人生马云任志强李嘉诚柳传志史玉柱
接创建一个新的签名外观。
15、修改签名密码:运行Adobe Acrobat 9 Pro,依次点击菜单栏中的“高级”—“安 全性设置”—“数字身份证文件”,再点击右侧最上面一行中的“更改口令”就可更改您签名时要输入的密码了!
第三篇:白话数字签名
白话数字签名
由于数字签名基于非对称加密技术,所以我们需要先啰嗦一下对称加密和非对称加密技术。
对称加密
何谓加密?加密是一种“把数据搞乱掉”的技术。加密技术涉及到4种东东:
明文:可以被人或程序识别的数据。例如一个文本文件、一段歌词、一个Word文档、一首MP3、一个图片文件、一段视频等等。
加密算法:将数据搞乱掉的方法。
密钥(密码):一个你在进行加密操作时给出的字符串,让加密算法不但把明文“搞乱掉”,而且要乱得“与众不同”。这样即使别人搞到了解密算法,如果没有当初加密时所使用的密码,一样无法进行解密操作。
密文:明文被加密算法和密钥加密后的结果。它看上去就是一堆乱码,没有人或程序能知道它到底表示什么信息。
作为加密的一个实例,我将使用由我杜撰的“景氏替换加密算法”演示一下加密过程。明文:good good study, day day up.密钥:google
景氏替换加密算法:将明文中的所有的字母“d”替换成密钥。
密文:将“good good study, day day up.”中的所有字母“d”替换成“google”,就得到密文“googoogle googoogle stugoogley,googleay googleay up.”。这个密文乱得还可以吧?一般人看了肯定不知道它是什么意思。
那么什么是解密呢?解密就是把密文再变回明文的过程。
例如“景氏替换解密算法”就是:将密文中所有与密钥相同的字符串替换成“d”。密文:googoogle googoogle stugoogley,googleay googleay up.密钥:google
景氏替换解密算法:将密文中所有与密钥相同的字符串替换成“d”。
明文:将“googoogle googoogle stugoogley,googleay googleay up.”中的所有“google”替换成“d”,就得到了明文“good good study, day day up.”。
您肯定已经注意到了,我们在进行加密和解密时使用的密钥必须是相同的,例如在上例中,加密和解密都必须使用相同的密钥“google”。所以像“景氏替换加密算法”这种就被称为对称加密算法。目前最为流行的对称加密算法是DES和AES,此外,对称加密算法还有IDEA、FEAL、LOKI、Lucifer、RC2、RC4、RC5、Blow fish、GOST、CAST、SAFER、SEAL等。WinRAR的文件加密功能就是使用的AES加密算法。
非对称加密
非对称加密算法是一类与众不同的加密算法,它的密钥不是1个,而是2个(一对),我们先姑且称它们为密钥K1和密钥K2。非对称加密算法的特点是,如果用密钥K1进行加密,则有且仅有密钥K2能进行解密;反之,如果使用密钥K2进行了加密,则有且仅有密钥K1能进行解密。注意“有且仅有”的意思——如果用密钥K1进行了加密,是不能用密钥K1
进行解密的;同样,如果用密钥K2进行了加密,也无法用密钥K2进行解密。这是一个非常重要的特性,至于如何在实际中运用这个特性,请看下文。
我想给Clark传送一个AV小电影,又怕被他的老婆发现......话说俺得了一个很不错的AV小电影,想通过网络传送给Clark,可是又怕被他的老婆发现(因为Clark的老婆是一个超级黑客,她可以使用sniffer技术截获任何通过网线传送给Clark的数据。别跟我说用VPN,它超出了本文讨论的范围),怎么办呢?对了,我们需要一个“将数据搞乱掉”的技术——加密技术。我先使用WinRAR对小电影进行压缩,然后加上密码“TswcbyyqjsjhfL”(还记得么?WinRAR的文件加密功能使用的是叫作AES的对称加密算法)。接着,将这个加密后的文件通过QQ传送给Clark。然后,兴冲冲地拨打Clark的手机: “喂?Clark么?好久不见,呵呵......我给你发了个好东东呦,在QQ上,收到没?......密码是TswcbyyqjsjhfL,对,就是天生我才必有用,千金散尽还复来的首字母,第一个和最后一个字母要大写呦......”
可是,Clark,我是真的不知道你的老婆大人刚刚就在你的身边呀!而且你也知道,我打电话从来都是喜欢很大声的......呜呜呜......在Clark跪了一夜的搓衣板之后,我们都明白:如果是已经保存在自己硬盘上的文件,使用对称加密技术进行加密是没有问题的;如果是两个人通过网络传输文件,使用对称加密就很危险——因为在传送密文的同时,还必须传送解密密钥。我们需要一个与众不同的加密算法,一个不需要传递解密密钥的加密算法。非对称加密正好可以满足我们的需要。基本思路是这样的:首先,生成一对满足非对称加密要求的密钥对(密钥K1和密钥K2)。然后,将密钥K1公布在网上,任何人都可以下载它,我们称这个已经公开的密钥K1为公钥;密钥K2自己留着,不让任何人知道,我们称这个只有自己知道的密钥K2为私钥。当我想给Clark传送小电影时,我可以用Clark的公钥对小电影进行加密,之后这个密文就连我也无法解密了。这个世界上只有一个人能将密文解密,这个人就是拥有私钥的Clark。
后来......后来,Clark痛定思痛,决定申请一个数字证书。流程是这样的:首先,登录当地的数字证书认证中心网站,填表->出示个人有效证件原件和复印件->缴费->等待数字证书认证中心制作数字证书->领取数字证书。如果您的公司需要申请大量的数字证书,还可以与认证中心的销售人员商量,先领取免费的试用版的数字证书供技术人员试用。
后来的后来,我又得到了一本电子版的不良漫画,当然,我又想到了Clark。我先在数字证书认证中心下载了Clark的公钥证书(就是一个含有公钥信息的文件),使用非对称加密算法对不良漫画进行加密,再将密文通过QQ传送给Clark。然后,我兴冲冲地拨打Clark的手机: “喂?Clark么?好久不见,呵呵......我给你发了个好东东呦,在QQ上,收到没?......已经用你的公钥加密了。用你的私钥解密就行了^_^”
Clark兴冲冲地插入他的私钥(忘了说了,私钥并不是一个文件,而是一个USB设备,外形就跟U盘一样,至于为什么要这样,下一篇再说),解密,然后开始看漫画,完全没察觉他的老婆大人就在身后......Clark,俺这个月手头有点紧......唉,这个月买了太多的书,到月底揭不开锅了。正巧在QQ上遇到了Clark:
1-2-3:“Clark,我需要200两纹银,能否借给我?”
Clark:“没问题。我这就给你转账。请给我一张借条。”
1-2-3:“太谢谢了,我这就用Word写一个借条给你。”
然后,我新建一个Word文档,写好借条,存盘。然后,然后怎么办呢?我不能直接把借条发送给Clark,原因有:
1.我无法保证Clark不会在收到借条后将“纹银200两”改为“纹银2000两”。
2.如果我赖账,Clark无法证明这个借条就是我写的。
3.普通的Word文档不能作为打官司的证据。
好在我早就申请了数字证书。我先用我的私钥对借条进行加密,然后将加密后的密文用QQ发送给Clark。Clark收到了借条的密文后,在数字证书认证中心的网站上下载我的公钥,然后使用我的公钥将密文解密,发现确实写的是“借纹银200两”,Clark就可以把银子放心的借给我了,我也不会担心Clark会篡改我的借条,原因是:
1.由于我发给Clark的是密文,Clark无法进行修改。Clark倒是可以修改解密后的借条,但是Clark没有我的私钥,没法模仿我对借条进行加密。这就叫防篡改。
2.由于用我的私钥进行加密的借条,有且只有我的公钥可以解密。反过来讲,能用我的公钥解密的借条,一定是使用我的私钥加密的,而只有我才拥有我的私钥,这样Clark就可以证明这个借条就是我写的。这就叫防抵赖。
3.如果我一直赖着不还钱,Clark把我告上了法庭,这个用我的私钥加密过的Word文档就可以当作程堂证供。因为我国已经出台了《中华人民共和国电子签名法》,使数字签名具有了法律效力。
您一定已经注意到了,这个使用我的私钥进行了加密的借条,具有了防篡改、防抵赖的特性,并且可以作为程堂证供,就跟我对这个借条进行了“签名”的效果是一样的。对了,“使用我的私钥对借条进行加密”的过程就叫做数字签名。(由于数字签名算法的速度比较慢,所以在实际对文件签名的过程比上面提到的方法稍稍复杂一些,这个在下一篇再讲)。
我是1-2-3,我真的是1-2-3,我是真的1-2-
3正如您已经知道的,Clark的老婆是一名超级黑客——就是传说中能用计算机作任何事的人。这不,不久前她就轻松入侵了QQ数据库,下载了Clark的所有好友的ID和密码以及聊天记录。然后,时不时地伪装成Clark的好友跟Clark聊天,搞得Clark最近总是神经兮兮、疑神疑鬼的。这不,昨天我在QQ上遇到了Clark:
1-2-3:“Clark,最近还好吧?我又搞到一个好东东呦,要不要?”
Clark:“48475bbt556”
Clark并不是疯掉了,那个“48475bbt556”也不是我跟Clark之间的什么通关暗语。这个“48475bbt556”就是Clark在键盘上胡乱敲上去的,不过,我却知道Clark是什么意思。我立刻把“48475bbt556”粘贴到Word里,然后用我的私钥对这个Word文档加密,再将这个Word文档发送给Clark。Clark在那边用我的公钥将Word文档解密,打开,发现里面写的就是“48475bbt556”,就知道QQ这边的确就是真正的我本人了。因为拥有我的私钥的人在这个世界上就只有我一人而已,Clark的老婆大人就是再神通广大也模仿不了,这就是数字签名的验证功能。
顺便提一句,不但人可以申请数字证书,设备(例如Web服务器)也可以申请数字证书(叫作设备证书)。利用数字签名的验证功能,就可以验证服务器的身份了,这可是防钓鱼的终极解决方案呦。
第四篇:数字签名课程设计
数字签名的目的和意义
RSA公开密钥加密算法自20世纪70年代提出以来,已经得到了广泛认可和应用。发展至今,电子安全领域的各方面已经形成了较为完备的国际规范。RSA作为最重要的公开密钥算法,在各领域的应用数不胜数。RSA在硬件方面,以技术成熟的IC应用于各种消费类电子产品。
RSA在软件方面的应用,主要集中在Internet上。加密连接、数字签名和数字证书的核心算法广泛使用RSA。日常应用中,有比较著名的工具包Open SSL(SSL,Security Socket Layer,是一个安全传输协议,在Internet上进行数据保护和身份确认。Open SSL是一个开放源代码的实现了SSL及相关加密技术的软件包,由加拿大的Eric Yang等发起编写的。Open SSL应用RSA实现签名和密钥交换,已经在各种操作系统得到非常广泛的应用。另外,家喻户晓的IE浏览器,自然也实现了SSL协议,集成了使用RSA技术的加密功能,结合MD5和SHA1,主要用于数字证书和数字签名,对于习惯于使用网上购物和网上银行的用户来说,几乎天天都在使用RSA技术。
RSA更出现在要求高度安全稳定的企业级商务应用中。在当今的企业级商务应用中,不得不提及使用最广泛的平台j2ee。事实上,在j2se的标准库中,就为安全和加密服务提供了两组API:JCA和JCE。JCA(Java Cryptography Architecture)提供基本的加密框架,如证书、数字签名、报文摘要和密钥对产生器; JCA由几个实现了基本的加密技术功能的类和接口组成,其中最主要的是java.security包,此软件包包含的是一组核心的类和接口,Java中数字签名的方法就集中在此软件包中。JCE(Java Cryptography Extension)在JCA的基础上作了扩展,JCE也是由几个软件包组成,其中最主要的是javax.crypto包,此软件包提供了JCE加密技术操作API。javax.crypto中的Cipher类用于具体的加密和解密。在上述软件包的实现中,集成了应用RSA算法的各种数据加密规范(RSA算法应用规范介绍参见: http://www.xiexiebang.com/rsalabs/node.asp?id=2146,这些API内部支持的算法不仅仅只有RSA,但是RSA是数字签名和证书中最常用的),用户程序可以直接使用java标准库中提供的API进行数字签名和证书的各种操作。
2.数字签名算法的基本框架 1.密钥的产生
①选择两个保密的大素数P和q。②计算N=p q,≯(N)=(p-1)(g-1),其中≯(N)是N的欧拉函数值。③选择一个整数e,满足l ⑤以(e, n)为公钥,(d ,N)为密钥,销毁p,q,≯(N)。2.加密 加密时首先将明文比特串进行分组,使得每个分组对应得串在数值上小于N,即分组的二进制长度小于l092N。然后,对每个明文分组M,作加密运算: C=E k(M)=M e mod N 3.解密 对密文分组的解密运算为: M=D k(C)=C d mod N 由定理1和定理2可以证明解密运算能恢复明文M 并非所有的公开密钥系统,均可同时达到秘密性与数字签名功能。一般而言,一公开密钥系统若作为密码系统,则无法作为数字签名,反之亦然。只有很少数 的系统可同时作为密码系统和数字签名,如本文讨论的RSA系统。RSA签名算 法如下: 设N=p q,且p和q是两个大素数,e和d满足e d≡l(mod ≯(N))。公开密钥:N,e 私有密钥:d 签名过程:发送方使用自己的私钥d对明文m进行数字签名变换: y=x d mod N:并将加密后的消息和签名y发送给接收方; 验证过程:接收方使用发送方的公钥e对收到的消息y进行数字签名验证变换x’=ye mod N,并使用发送方的密钥解密恢复消息x,比较x’与x,如果x’=x则证实发送方的身份合法。 这样,用户A若想用RSA签名方案对消息x签名,他只需公开他的公钥N和e,由于签名算法是保密的,因此A是唯一能产生签名的人,任何要验证用户A 签名的用户只需查到A的公钥即可验证签名。对于实现签名和公钥加密的组合,常用方法是:假定通信双方为A和B。对于明文x,A计算他的签名y=x d mod N,然后利用B的公开加密函数EB对信息对(x, y)加密得到Z,将密文Z传送给B,当B收到密文Z后,他首先用他的解密函数DB来解密得到(x,y)=DB(Z)= DB(EB(x,y)),然后利用A的验证算法来检查x’=x=y e mod N是否成立。 3.主要模块的算法以及关键代码 ①.文件选择模块的主要算法及关键代码 CfileDialog dlg(TRUE,NULL,“.签名的文件”,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);if(dlg.DoModal()==IDOK){ m_file_sign=dlg.GetPathName();} else m_file_sign=“";UpdateData(FALSE);②.保存公钥的文件路径的主要算法及关键代码 CFileDialog dlg(FALSE,NULL,”.公钥“,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);if(dlg.DoModal()==IDOK){ m_pkey_sign=dlg.GetPathName();} else m_pkey_sign=”“;UpdateData(FALSE);③.保存签名后的文件的路径主要算法及关键代码 CFileDialog dlg(FALSE,NULL,”.签名后的文件“,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);if(dlg.DoModal()==IDOK){ m_signed_sign=dlg.GetPathName();} else m_signed_sign=”“;UpdateData(FALSE);④.数字签名的主要算法及关键代码 HCRYPTPROV hProv;//秘钥容器句柄 BYTE *pbBuffer;//被签名的数据 HCRYPTHASH hHash;HCRYPTKEY hKey;BYTE *pbKeyBlob; //签名者得公钥数据 BYTE *pbSignature; //数字签名 DWORD dwSigLen;DWORD dwBlobLen;DWORD dwBufferLen;LPTSTR szDescription = ”“; CFile m_pubkey_file,m_sign_file,m_signdatafile;if(m_pkey_sign==”“||!m_pubkey_file.Open(m_pkey_sign,CFile::modeCreate|CFile::modeReadWrite)){ MessageBox(”请选择正确的保存公钥的文件路径“);return;} if(m_file_sign==”“||!m_signdatafile.Open(m_file_sign,CFile::modeReadWrite)){ MessageBox(”请选择正确的文件路径“);return;} if(m_signed_sign==”“||!m_sign_file.Open(m_signed_sign,CFile::modeCreate|CFile::modeReadWrite)){ MessageBox(”请选择正确保存数字签名的文件路径“);return;} UpdateData(TRUE);m_state_sign=”“;//获取缺省的秘钥容器 if(CryptAcquireContext(&hProv,NULL,NULL,m_prov_sign,0)){ m_state_sign+=”已获取CSP上下文,秘钥生成算法:“+GetProvType(m_prov_sign)+”n“;} else //密钥容器不存在创建之 { if(CryptAcquireContext(&hProv,NULL,NULL,m_prov_sign,CRYPT_NEWKEYSET)) m_state_sign+=”已创建一个新的密钥容器,秘钥生成算法:“+GetProvType(m_prov_sign)+”n“; else { m_state_sign+=MyHandleError(”在获取CSP时发生错误,程序停止.“);UpdateData(FALSE);return;} } // 从密钥容器中取数字签名用的密钥 if(CryptGetUserKey(hProv,AT_SIGNATURE,&hKey)) m_state_sign+=”签名密钥已经获取.n“;else { if(GetLastError()== NTE_NO_KEY)//密钥容器里不存在signature key pair创建之 { if(CryptGenKey(hProv,//CSP句柄 AT_SIGNATURE, //创建的密钥对类型为signature key pair 0, //key类型,这里用默认值 &hKey)) //创建成功返回新创建的密钥对的句柄 m_state_sign+=”创建一个秘钥对n“; else { m_state_sign+=MyHandleError(”在创建签名密钥对时发生错误,程序停止.n“);UpdateData(FALSE);return;} } else { m_state_sign+=MyHandleError(”在获取签名密钥时发生错误,程序停止.“);UpdateData(FALSE);return; } } // 因为接收消息者要验证数字签名,所以要导出公钥给接收者。 if(CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,NULL,&dwBlobLen))//得到公钥的大小 m_state_sign+=”已获取公钥的大小,“;else { m_state_sign+=MyHandleError(”计算公钥大小时发生错误,程序停止.“);UpdateData(FALSE);return;} // 为存储公钥的缓冲区分配内存。 if((pbKeyBlob =(BYTE*)malloc(dwBlobLen))) m_state_sign+=”已为公钥分配内存n“;else { m_state_sign+=MyHandleError(”为公钥分配内存时出现异常,退出.n“);UpdateData(FALSE);return;} // 真正导出公钥数据 if(CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,pbKeyBlob,//公钥 这个数据可以存入文件,发送给接收者。一般被存入数字证书 &dwBlobLen)){ m_pubkey_file.Write(pbKeyBlob,dwBlobLen); m_state_sign+=”已导出公钥,存储在“+m_pubkey_file.GetFilePath()+”n“;} else { m_state_sign+=MyHandleError(”导出公钥时发生错误,退出“);UpdateData(FALSE);return;} // 创建hash对象 if(CryptCreateHash(hProv,m_hash_sign,//CALG_MD5,0,0,&hHash)){ m_state_sign+=”已创建hash对象,加密算法“+GetHashType(m_hash_sign)+”nn“;} else { m_state_sign+=MyHandleError(”在创建hash对象时发生错误,退出“);UpdateData(FALSE);return;} //把签名的数据读入内存 //分配空间 if((pbBuffer=(BYTE *)malloc(m_signdatafile.GetLength()))) m_state_sign+=”已经为数据“+m_signdatafile.GetFilePath()+”分配空间nn“;else { m_state_sign+=MyHandleError(”为数据分配内存时发生异常,退出“);UpdateData(FALSE);return;} if(m_signdatafile.Read(pbBuffer,m_signdatafile.GetLength()))//把数据读入内存 m_state_sign+=”数据已经读入内存!“;else {m_state_sign+=MyHandleError(”数据读入内存发生错误,退出“);UpdateData(FALSE);return;} dwBufferLen = m_signdatafile.GetLength();// 对数据进行hash运算 if(CryptHashData(hHash,pbBuffer,dwBufferLen,0)) m_state_sign+=”已对数据进行hash运算n“;else { m_state_sign+=MyHandleError(”在对数据进行hash运算时发生错误,退出.“);UpdateData(FALSE);return;} // 使用signature key pair的私钥对hash数据签名 dwSigLen= 0;if(CryptSignHash(hHash,AT_SIGNATURE,szDescription,0,NULL,&dwSigLen))//得到数字签名大小 m_state_sign+=”已获取数字签名的大小,“;else { m_state_sign+=MyHandleError(”计算数字签名大小时发生错误,退出.“);UpdateData(FALSE);return;} // 为数字签名缓冲区分配内存 if((pbSignature =(BYTE *)malloc(dwSigLen))) m_state_sign+=”已为数字签名分配缓冲n“;else { m_state_sign+=MyHandleError(”为数字签名分配内存时异常,退出.“);UpdateData(FALSE);return;} // 得到数字签名 if(CryptSignHash(hHash,AT_SIGNATURE,szDescription,0,pbSignature, //这里将返回数字签名,同被签名的数据一起发送给接收方 &dwSigLen)) { m_sign_file.Write(pbSignature,dwSigLen); m_state_sign+=”已导出数字签名,存储在“+m_sign_file.GetFilePath()+”nn“;} else { m_state_sign+=MyHandleError(”导出数字签名时发生异常,退出.“);UpdateData(FALSE);return;} // 销毁hash对象.if(hHash){ CryptDestroyHash(hHash); m_state_sign+=”销毁hash对象nn“;} m_state_sign+=”数字签名成功nn“;//关闭文件 m_pubkey_file.Close(),m_sign_file.Close(),m_signdatafile.Close(MessageBox(”数字签名成功!“,”“,MB_OK);UpdateData(FALSE);⑤.数字签名认证的主要算法及关键代码 HCRYPTPROV hProv;HCRYPTKEY hPubKey;BYTE *pbKeyBlob;DWORD dwBlobLen;HCRYPTHASH hHash;BYTE *pbSignature; //数字签名 DWORD dwSigLen;LPTSTR szDescription = ”“;UpdateData(TRUE);m_state_veri=”“;// 获得CSP句柄,密钥容器名为登陆用户名 if(CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0)){ m_state_veri+=”已获取CSP,秘钥生成算法:);“+GetProvType(m_prov_veri)+”n“;} else //密钥容器不存在创建之 { if(CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET)) m_state_veri+=”已创建一个新的密钥容器秘钥生成算法:“+GetProvType(m_prov_veri)+”n“; else { m_state_veri+=MyHandleError2(”在获取密钥容器时发生错误,退出n“);UpdateData(FALSE);return;} } CFile signdatafile,yuanwenfile,pubkeyfile;if(m_pkey_veri==”“||!pubkeyfile.Open(m_pkey_veri,CFile::modeReadWrite)){ MessageBox(”请选择正确的公钥文件!“);return;} if(m_file_veri==”“||!yuanwenfile.Open(m_file_veri,CFile::modeReadWrite)){ MessageBox(”请选择正确的原文件!“);return;} if(m_signed_veri==”“||!signdatafile.Open(m_signed_veri,CFile::modeReadWrite)){ MessageBox(”请选择正确的签名文件!“);return;} dwBlobLen=pubkeyfile.GetLength();pbKeyBlob=(BYTE *)malloc(dwBlobLen);pubkeyfile.Read(pbKeyBlob,dwBlobLen);if(CryptImportKey(hProv,pbKeyBlob,dwBlobLen,0,0,&hPubKey)) m_state_veri+=”公钥已经成功导入!nn“;else { m_state_veri+=MyHandleError2(”公钥导出出错.n“);UpdateData(FALSE);return;} // 创建哈希对象 if(CryptCreateHash(hProv,m_hash_veri,//CALG_MD5,0,0,&hHash)) m_state_veri+=”已经获取hash对象,hash算法“+GetHashType(m_hash_veri)+”nn“;else { m_state_veri+=MyHandleError2(”创建hash对象时出错,退出“);UpdateData(FALSE);return;} // 跟生成时一样对数据进行hash运算 BYTE *pbBuffer;pbBuffer=(BYTE *)malloc(yuanwenfile.GetLength());yuanwenfile.Read(pbBuffer,yuanwenfile.GetLength());DWORD dwBufferLen = yuanwenfile.GetLength();pbSignature=(BYTE *)malloc(signdatafile.GetLength());signdatafile.Read(pbSignature,signdatafile.GetLength());dwSigLen = signdatafile.GetLength();if(CryptHashData(hHash,pbBuffer,dwBufferLen,0)) m_state_veri+=”对数据hash运算成功!nn“;else { m_state_veri+=MyHandleError2(”对数据进行hash运算出错,退出“);UpdateData(FALSE);return;} // 验证数字签名 if(CryptVerifySignature(hHash,pbSignature, //数字签名数据 dwSigLen,hPubKey, //签名者的公钥 szDescription,0)) { MessageBox(”恭喜:是正确的数字签名!“); m_state_veri+=”恭喜:是正确的数字签名!“;} else { MessageBox(”错误:签名是错误的n“); m_state_veri+=”错误:签名是错误的n请检查参数是否设置正确,若正确则请联系发送方";} UpdateData(FALSE);//------ // Free memory to be used to store signature.if(pbSignature)free(pbSignature);if(pbKeyBlob)free(pbKeyBlob);// Destroy the hash object.if(hHash) CryptDestroyHash(hHash);// Release the provider handle.if(hProv) CryptReleaseContext(hProv, 0);signdatafile.Close(),yuanwenfile.Close(),pubkeyfile.Close();4.RSA数字签名算法运行情况: 4.1 主界面初始化 4.2 签名界面 4.3 设置密钥 4.4 选择签名文件 4.5 选择保存公钥位置 4.6 选择选择签名后保存位置 4.6 进行数字签名结果 4.7 进行数字签名认证 4.8 进行数字签名认证结果 5.总结与展望: 通过本次对RSA算法的学习,明白了该算法加密解密的原理,以及他的安全性问题和缺点,通过这几周的实验,在学习中累计经验解决问题,让我对RSA算法有了较通透的理解,受益匪浅。随着Internet的发展,实现电子商务是未来的潮流和趋势,基于Internet开放环境下的信息安全将越来越受到重视,而RSA算法在身份认证,数字签名,信息加密等方面得到非常广泛的应用,对它作深入的了解是很有必要的。虽然RSA算法可靠性较高,但是还是有一些缺陷,就是运算量太大,速度太慢,适合加密比较短的明文。RSA方法既可用于保密,也可用于签名和认证,目前已经广泛应用与各种产品,平台等软件上。许多流行的操作系统上如微软,Apple,Sun和Novell都是在其产品上融入RSA。在硬件上,如安全电话,以太网和智能卡都使用了RSA技术。而且几乎所有Internet安全协议如S/MIME,SSL和S/WAN都引入了RSA加密方法。ISO9796标准把RSA列为一种兼容的加密算法。可以预见,在不远的几年内,RSA的 应用将来会越来越广泛。 数字签名与哈希函数 懂得一点公钥密码基础知识的人都知道,发信息的人用自己的私钥对所发信息进行加密(Encryption),接收信息者用发信者的公钥来解密(Decryption),就可以保证信息的真实性、完整性与不可否认性。(注:这里提到的加密、解密是指密码运算,其目的并非信息保密。)那么,我们也可以笼统地说,以上方法就已经达到了数字签名的目的。因为首先,私钥是发信者唯一持有的,别的任何人不可能制造出这份密文来,所以可以相信这份密文以及对应的明文不是伪造的(当然,发信者身份的确定还要通过数字证书来保证);出于同样原因,发信者也不能抵赖、否认自己曾经发过这份信息;另外,信息在传输当中不可能被篡改,因为如果有人试图篡改,密文就解不出来。这样,用私钥加密,公钥解密的技术方法就可以代替传统签名、盖章,保证了信息的真实性、完整性与不可否认性。 但是,这样做在实际使用中却存在一个问题:要发的信息可能很长,非对称密码又比较复杂,运算量大,而为了保证安全,私钥通常保存在USB Key或IC卡中,加密运算也是在Key或卡中进行。一般来说,小小的USB Key或IC卡中的微处理器都做得比较简单而处理能力较弱,这样,加密所用的时间就会很长而导致无法实用。 另外,即使对于网站服务器而言,虽然它的处理能力很强,但服务器要同时处理许许多多签名加密的事情,也同样存在着加密耗时长系统效率低的问题。 有没有解决这个问题的办法呢?有的,常用的方法是使用哈希函数。 什么是哈希函数 哈希(Hash)函数在中文中有很多译名,有些人根据Hash的英文原意译为“散列函数”或“杂凑函数”,有些人干脆把它音译为“哈希函数”,还有些人根据Hash函数的功能译为“压缩函数”、“消息摘要函数”、“指纹函数”、“单向散列函数”等等。 1、Hash算法是把任意长度的输入数据经过算法压缩,输出一个尺寸小了很多的固定长度的数据,即哈希值。哈希值也称为输入数据的数字指纹(Digital Fingerprint)或消息摘要(Message Digest)等。Hash函数具备以下的性质: 2、给定输入数据,很容易计算出它的哈希值; 3、反过来,给定哈希值,倒推出输入数据则很难,计算上不可行。这就是哈希函数的单向性,在技术上称为抗原像攻击性; 4、给定哈希值,想要找出能够产生同样的哈希值的两个不同的输入数据,(这种情况称为碰撞,Collision),这很难,计算上不可行,在技术上称为抗碰撞攻击性; 5、哈希值不表达任何关于输入数据的信息。 哈希函数在实际中有多种应用,在信息安全领域中更受到重视。从哈希函数的特性,我们不难想象,我们可以在某些场合下,让哈希值来“代表”信息本身。例如,检验哈希值是否发生改变,借以判断信息本身是否发生了改变。` 怎样构建数字签名 好了,有了Hash函数,我们可以来构建真正实用的数字签名了。 发信者在发信前使用哈希算法求出待发信息的数字摘要,然后用私钥对这个数字摘要,而不是待发信息本身,进行加密而形成一段信息,这段信息称为数字签名。发信时将这个数字签名信息附在待发信息后面,一起发送过去。收信者收到信息后,一方面用发信者的公钥对数字签名解密,得到一个摘要H;另一方面把收到的信息本身用哈希算法求出另一个摘要H’,再把H与H’相比较,看看两者是否相同。根据哈希函数的特性,我们可以让简短的摘要来“代表”信息本身,如果两个摘要H与H’完全符合,证明信息是完整的;如果不符合,就说明信息被人篡改了。 数字签名也可以用在非通信,即离线的场合,同样具有以上功能与特性。 由于摘要一般只有128位或160位比特,比信息本身要短许多倍,USB Key或IC卡中的微处理器对摘要进行加密就变得很容易,数字签名的过程一般在一秒钟内即可完成。 哈希函数的安全性 哈希函数的安全性直接关系到数字签名的安全性,如果哈希函数被攻破,数字签名的有效性就会受到质疑。 目前,已经发明的Hash函数有多种,如Snefru、N-Hash、LOKI、AR、GOST、MD、SHA等。它们在数学上实现的方法各有不同,安全性也各有不同。目前比较常用的Hash函数是MD5与SHA-1。MD5哈希函数以512位来处理输入数据,每一分组又划分为16个32位的子分组。算法的输出由4个32位分组组成,将它们级联起来,形成一个128位的固定长度的哈希值,即输入数据的摘要。SHA-1哈希函数在MD4的基础上增加了数学运算的复杂程度,即SHA=MD4+扩展转换+附加轮+更好的雪崩效应(哈希值中,为0的比特与为1的比特,其总数应该大致相等;输入数据中一个比特的变化,将导致哈希值中一半以上的比特变化,这就叫做雪崩效应)。SHA能够产生160位的哈希值。对SHA还没有已知的密码攻击,并且由于它产生的哈希值位数长于MD5,所以它能更有效地抵抗穷举攻击(包括生日攻击)。 但是,任何一种算法都有其漏洞与局限性。任何一个哈希函数都会存在碰撞——即在一些特定情况下,两个不同的文件或信息会指向同一个数字摘要。在一般情况下,类似碰撞只能尽可能地减少,而不能完全避免。从理论上讲,没有攻不破的密码。随着密码科学的发展,也许会找到攻破某一种密码算法的途径。 评价Hash算法的一个最好方法是看敌手找到一对碰撞消息所花的代价有多高。一般地,假设攻击者知道Hash算法,攻击者的主要攻击目标是找到一对或更多对碰撞消息。目前已有一些攻击Hash算法与计算碰撞消息的方法。在这些方法中,有些是一般的方法,可用于攻击任何类型的Hash算法,比如“生日攻击”;而另一些是特殊的方法,只能用于攻击某些特殊的Hash算法,比如适合于攻击具有分组链结构Hash算法的“中间相遇攻击”,适用于攻击基于模运算的Hash函数的“修正分组攻击”。坚固的哈希函数可通过设计有效的碰撞处理机制,或增加数字摘要的位数来增加复杂度,以减少碰撞出现的概率,2004年8月17日,在美国召开的国际密码学会议(Crypto’ 2004)上,一些国家的密码学者作了破译Hash函数的新进展的报告,其中我国山东大学的王小云教授做了破译MD5、HAVAL-128、MD4、与RIPE MD算法的报告。 到2005年2月,据王小云教授的研究报告,他们已经研究出了搜索SHA-1碰撞的一系列新技术。他们的分析表明,SHA-1的碰撞能在小于2^69次Hash操作中找到。对完整的80轮SHA-1的攻击,这是第一次在小于2^80次Hash操作这个理论界限的情况下找到碰撞。根据他们的估计,对于缩减到70轮的SHA-1能够用现在的超级计算机找出“实碰撞”。他们的研究方法,能自然地运用到SHA-0与缩减轮数的SHA-1的破译分析上。 2005年3月6日,Arjen Lenstra,王小云,Benne de Weger 宣布,他们构造出一对基于MD5 Hash函数的X.509证书,产生了相同的签名。他们提出了一种构造X.509证书的方法,在他们所构造出的证书对中,由于使用了MD5算法,签名部分产生了碰撞。因此,当证书发布者使用MD5作为Hash函数时,发布者就会在证书中产生相同的签名,导致PKI的基础原理遭到可信性破坏。这意味着,从单独某个证书无法确定是否存在另一个不同证书有着相同的签名。由于第二个相同签名证书存在的可能性,证书发布机构无法验证私钥的“拥有证明”,即无法验证证书中的签名。因此,使用“基于MD5函数”公钥证书的任何一方都无法确保所谓的证书拥有者是否真实拥有相应的私钥。 他们也想构造一对基于SHA-1的X.509证书,产生相同的签名。然而,他们还做不到这一点。因为产生SHA-1碰撞还需要相当长一段时间的研究。 专家指出:A.Lenstra与王小云等人声称已经成功地构造了两张符合X.509证书数据结构,拥有同样签名而内容却不同的证书,但该构造方法对证书的部分域要有特殊安排,签名算法RSA的密钥也是按照特殊规律生成的,要用来攻击某个实际应用的电子签名系统仍需时日。而对于SHA-1算法,说其从理论上被破解都还为时过早,只能说其破解工作取得了重大突破,破解所需要运算次数已从原来设计时估算的2^80次降低为2^69次,这比穷举法快了2048倍,但2^69次运算需要6000年左右的时间,在实际计算上仍然是不可行的。 除了运算方面的瓶颈外,哈希函数的不可逆性决定了攻击者无法轻易得手,没有人可以保证通过这个发现的每个碰撞都是“可用”的碰撞。在漫长的运算后,你得到的也许包含一些有价值的信息,也许就是理论上存在的单纯碰撞,运算瓶颈与信息匮乏都会使黑客们的种种努力成为徒劳……据业内人士估计,在当前的技术条件下,2^50或2^ 60次运算量的范围内的攻击方法才会为我们带来麻烦,即引发实际意义上的攻击行为。在新研究成果发布前的一段时间内,SHA-1 算法只能被称作不完美,但还是安全的。基于PKI技术进行电子签名的最终用户,目前还不用担心自己的签名被伪造或遭遇签名人抵赖。 另外,安全专家强调:一种算法被破译,与整个企业的安全系统被攻破,是两个不同的概念。因为随着攻击技术与能力的提高,算法也会“水涨船高”,向前发展进步。王教授所取得的成就提醒密码学家研究新的算法,提醒有关标准化机构要提前修改算法标准,也提醒有关CA与电子签名产品开发商支持新的算法。当然,有些完全基于摘要算法的密押系统与电子货币系统,还需要尽早考虑替换方案。 美国国家技术与标准局(NIST)曾经发表如下评论:“研究结果说明SHA-1的安全性暂时没有问题,但随着技术的发展,技术与标准局计划在2010年之前逐步淘汰SHA-1,换用其他更长更安全的算法(如:SHA-224, SHA-256, SHA-384与SHA-512)来代替。”第五篇:数字签名及哈希函数