Posted on 2009-12-03 23:17
深夜两点 阅读(1108)
评论(0) 编辑 收藏
(上一篇:计算机中的加密和认证http://www.blogjava.net/deepnighttwo/archive/2009/12/03 /304631.html)
A公司开发了一个软件,打成了一个jar包,然后发布出去liao。作为一个用户,如何来确认这个jar包确实是A公司发布的哪个?而且,如何确定这个jar包没有被别有用心的一小撮篡改过?这就需要Java中的签名来保证。
Java中的可执行代码就是class文件。直接使用class文件是很naive的。通常的做法是是对一个jar包中的所有class文件进行签名。过程可以分为如下步骤。
- 首先使用JDK自带的keytool工具生成一个keystore,命令如下: keytool -genkey -keystore keystore文件 -alias 别名。回车后还有一些信息需要填写。keystore里面包含了很多信息,包括公钥和私钥信息。当然可以使用keytool命令从keystore文件里面导出公钥和私钥。keytool命令还有很多参数,比如你可以指定使用的摘要算法等。(具体用法可以Google之)。
- 然后,第二步当然是找个CA给公钥签名。自娱自乐的用途就可以不用这一步了。
- 第三步是给jar包签名。JDK中提供了给jar包签名的工具,叫做jarsinger。命令各式如下:jarsigner -keystore keystore文件 jar文件 别名(就是生成keystore时用的那个别名)。回车后要输入密码,也跟生成keystore时候的密码一样就行了。
好,到这里就算签名结束了。命令执行完毕后,jar包会陡然多出几k来。这几k就是签名的内容。
Java(或者说是Java Runtime)是支持签名和认证的。也就是说一个jar包一旦被签名了,Java Runtime会对这个jar包进行验证。下面是验证签名的过程。
首先需要知道签名后jar包里面多出了什么。签名并不会改变jar包中已经有的内容,而是添加了一个.DSA(说明使用的是DSA算法)文件和一个.SF(signed file)文件,然后在.MF文件里面增加一些内容。验证的过程是这样的(我猜的。。。觉得不对可以去http://java.sun.com/javase/6/docs/technotes/guides/jar /jar.html,Sun公司的jar包规范,自己看自己猜),首先是DSA文件,它里面存储了公钥内容和对SF文件摘要的加密内容,所以,首先验证公钥(跟https里面的那个验证是一样的过程),验证完毕证书后,用公钥解密加密的内容,然后得到SF文件的摘要值,把这个值和实际 SF文件的摘要值比较,这样就可以保证SF文件没问题了。SF文件里面的内容包含了很多条目的签名值。首先是对MF文件的签名值,这就是验证MF文件了。而MF文件里面对每个class文件都有一段描述的内容,比如:
Name: common/class2.class
MD5-Digest: (base64 representation of MD5 digest)
SHA-Digest: (base64 representation of SHA digest
它代表这个class文件对应摘要算法的摘要值。这个条目在SF里面有一个对应的条目:
Name: common/class2.class
MD5-Digest: (base64 representation of MD5 digest)
注意,SF文件中的这个摘要值不是class文件的,而是MF文件里面对应条目的。也就是说,SF里面的签名值统统是用来验证MF文件或者MF文件中的条目的,而MF文件中的摘要值才是用来验证class文件的。真绕。。。
总之,最后一层层的验证后,整个jar包中的内容都被验证了。过程:CA的证书->自己的公钥->SF文件签名 ->MF文件签名和MF文件每个条目的签名->jar包中的每个文件(当然主要是clas文件。别的文件应该也会被验证的,至少properties文件会被签名认证)
验证完了之后,就可以保证jar包确实出自某公司之手,也确实没有被别有用心的一小撮人篡改过。如果你信任某公司,那就可以用这个jar包了。
同样,如果一个applet的jar包是签名了的,而且在启动applet的时候用户选择信任这个签名,那么这个applet就拥有了访问本机资源的权限,如果选择不信任,那么applet就不会被启动。如果一个applet没有被签名,那么applet可以启动,但是不会被允许访问本机资源(文件等)。
如果一个证书没有被CA的证书认证,比如说,对于我写的这个applet,它就是用我自己搞出来的没认证过的证书签了名的:http://appletfarm.appspot.com/juliaappletsigned.html
这时候Java会提示说:
“该应用程序的数字签名无法验证”,因为我没给过VeriSign年费。如果证书是验证过的,对话框就会是询问你是否信任“某公司”,这个意思就是说,此jar包确实是“某公司”搞出来的,信任那个公司就可以运行它了。