为何要制作数字签名,请参见我以前的文章 http://dkfdtf.blogbus.com/logs/10896854.html,我最近的一个项目也需要实现自验证功能,狐狸天堂上的金威先生也恰好有这个需要,所以索性将实现的核心代码公布出来,希望有深入研究的网友可以给予指正。
如何制作数字签名
需要的工具:makecert.exe, signtool.exe。这两工具网上大把,自己搜一下下载即可。如果安装了 vs2005 则本机上已有。
1. 制作一份用于代码自签名的证书
makecert -r -pe -ss My -b 01/01/2009 -e 01/01/2015 -n "CN=xxx;E=test@163.com" yyy.cer
其中 xxx 是你的证书标识,一般用你的公司名称;yyy.cer 是你要生成的证书文件名
注意!!! 证书只要制作一次即可,以后都用它来签名文件。如果你制作多次,每次生成的颁发机构密钥都会不同,但标识却一样,所以签名文件时会有些小麻烦。
2. 给可执行文件签名,假设要签名的文件名为 test.exe
Signtool sign /v /s My /n xxx /t http://timestamp.verisign.com/scripts/timestamp.dll test.exe
注意这里的 xxx 要与第一步的 xxx 完全相同
如果你像上一步中提到的那样,生成了多份同一标识的证书,则这条命令会执行失败。因为它不知道你要选择哪一份证书来签名。你有两种方法来解决它:
a) 在命令窗口中执行 certmgr.msc,然后在“个人”/“证书”中删除它们,重新执行第一步,这次记住只做一次。
b) 如果你不想删除它们,你可以在执行 Signtool 中加多一个选项 /a,让它自己随便挑一个;或者,用 /sha1 xxxxxxxxxxxxxxxxx 从显示找到的密钥中自己选一个。
好了,制作就这么简单,现在你的 test.exe 已经带有自签名的数字证书了。
如何安装你的证书
你右击一下 test.exe 文件,查看它的属性,是不是看到有“数字签名”的选项卡了?可是,如果你查看这个数字签名的“详细信息”,你会发现下图那样的一把叉!
其实不奇怪,你的证书没有被 MS 认可,它不信任你的证书。不过没关系,这只是缺省情况,现在开始安装证书,让 Windows 信任咱的证书。
继续点击“查看证书”按钮,然后点“安装证书”,在随后的安装向导中选“将所有证书放入下列存储”,点“浏览”按钮,在出现的下拉列表框中选“受信任的根证书颁发机构”,下面一路 next 直至完成。注意:这之间会有一个警告框弹出来,要你确认证书的安全性,你当然要选“是”啦!这个对话框是无法禁止出现的,因为 MS 不认识你的证书,自然只能交给用户自己来决定它是否安全。如果有一个选项可以不显示这个警告框,则所有黑客/病毒软件都可以悄无声息的安装它们自己的证书来骗取 Windows 的信任了。不过我们编程的时候还是有办法来自动确认这个按钮的,只是快速的闪现一下还是无法避免。
关闭所有的对话框,重新查看一下属性中数字签名,哪个讨厌的叉叉是否已经没有啦?!
如果你用其他16进制编辑器把将这个文件随便改一个字节的内容,你会发现那个红叉叉又出现了!这说明数字签名的验证机制起作用了。
如何编程实现
我们最终的目的是要在我们自己的程序中检查代码是否被人为或病毒非法修改了,用上面手工验证的方法是没有作用的。所以有了下面的代码,它没有使用 Crypto API,而是利用了 MS 已将这些 API 封装好的一个 COM 控件 CAPICOM。如果你没有这个控件,可以到 这里去下载它最新的安装包,其实你只需要其中的 capicom.dll 这一个文件。不过你应该已有这个控件,否则前面运行 signtool 时就会提示错误,因为它也是用的这个 COM 控件来完成签名操作的。
下面是实现安装和验证的示例代码,你可以根据需要做成一个函数来完成你的签名验证和证书安装。此示例代码已在 XP/2003/Vista 中验证通过。
虽然也花了一些时间,想抛开这个 COM 控件而直接用 Crypto API 来实现,也参照 MSDN 中的 C 示例代码用 vfp 实现了,但最后发现仍有一些严重的问题。主要问题是验证签名时,有效的签名没有问题,但碰到无效签名的文件时,第一次验证可以得到正确结果,但再次调用时就会认为是没有签名的代码,而不是无效签名的代码。看来 MS 写示例文档的人对验证还是有所保留的。如果哪位有深入研究的网友知道原因,请不吝赐教,万分感谢!
如何自动确认安装时的警告框
如果将证书安装的 CAPICOM_CURRENT_USER_STORE 存储容器中,用户会看到一个“安全性警告”框,需要用户来确认(安装到 CAPICOM_LOCAL_MACHINE_STORE 不会出现该警告框)。如果你不希望因用户选择“取消”操作而导致证书安装失败,则你有两种选择:
1. 将证书安装到 CAPICOM_LOCAL_MACHINE_STORE 容器中。但 MS 在 MSDN 中的所有示例都是将证书安装到“个人”或 CAPICOM_CURRENT_USER_STORE 容器中。所以安装到 LOCAL_MACHINE_STORE 中是否会有不良影响我不知道。试验结果是安装到这里,证书也同样可以通过许可验证;而 Vista 下的标准用户,也只能安装到这里才能读取得到此证书,安装到 CURRENT_USER_STORE 容器中不可行。
2. 编程来自动确认。这里有一个问题,在警告框弹出的同时,Crypt API 也禁用了当前线程的消息队列,所以简单的用计时器来探测弹出窗口是不行的,因为 WM_TIMER 消息也被禁止了,遗憾的是 vfp 也不支持多线程,所以无法另开一线程来监视这个窗口,只能用另外运行一独立进程的方法来探测并关闭这个警告框。上面的示例中已加入这一部分的处理代码,并用横线标出。生成这个 exe 的项目文件在文章的最后提供了下载,其中已有这个 autocfm.exe,不过它是 vfp9sp2 版本编译的,如果你用的运行时库不是 sp2 版本,应该重新编译一次。我一般会将这个文件编译到主 exe 中,运行时临时释放出来,使用后再删除。
autocfm 项目文件下载(下载后去掉 jpg 后缀)