JavaJava学习笔记java

jar包签名机制

2015-10-30  本文已影响2096人  ad9c295c0689

jar包签名:

      我们通常会用钢笔和墨水在文件上签字,以标志该文件是我们写的,或至少是通过我们的授权。jar包签名的作用与其类似。签名的jar可以检测代码是否被篡改,还可以通过给有可信签名的jar赋予更多的操作权限。

       jar包签名采用公钥/密钥机制。密钥就类似用于文件上签字的钢笔。只有你自己有,而与秘钥相对应的公钥可以被其他人拥有。通过公钥对被秘钥加密的文件进行解密,来验证文件的安全性。但是即使jar包含有匹配的公钥/密钥,你还是需要验证公钥是否来自真实的文件加密者(一个人可以伪造某个机构,用自己的密钥对jar进行加密,然后把公钥放入jar,这样同样能进行解密)。

      如何验证公钥来源?

      这时证书机制就产生了。证书由业界可信组织提供。他对公钥及其所有者颁发证书进行证明。当某组织需要对jar进行签名时,同时应该将公钥和证书放入jar中,这样就组织了其他人冒充组织对jar进行签名的问题。详细过程可参考:数字签名与数字证书

      jar包签名可以防止恶意者冒充某个组织发布jar包,给想使用某个组织jar包得使用者带来不安全的问题。

      当jar包被签名时,一个签名文件会自动在META-INF文件夹中生成,该文件夹中同时还含有manifest文件,公钥文件。签名文件有.SF后缀。如下图:

签名jar包的结构

manifest文件内容:

manifest文件内容

签名文件xxx.SF文件内容:

签名文件内容

可以看到签名文件中还包含了manifest文件的摘要信息。

manifest中包含每个文件的摘要信息,然而签名文件中则包含的是manifest中每个摘要项的摘要。当jar签名被验证时,首先对jar中每个文件进行摘要计算,然后与manifest中已记录的摘要进行比较,来判断文件是否更改过。同时还要计算manifest文件的摘要,并与签名文件比较,以验证manifest文件是否被修改过。  

签名验证:

jvm在加载类文件时,会对相同包下类的包签名进行验证,如果两个类来自不同的jar文件,但是包名字相同,并且一个jar进行了签名,另一个jar未签名,则签名验证时会抛异常。

如下为jdk加载类时的源码:

类加载时包签名验证

了解以上知识,说一个工作中遇到的奇葩案例:

想用guava中的Collection中的Multimap,但是却抛出了莫名其妙的异常,如下:

异常日志

原来是guava和jetty都引用了javax.annotation包,但是在jetty中的jar进行了签名,而在guava中的jar没有进行签名,如最上边的贴图。所以加载类进行签名验证时出了问题。

解决方案:

将jetty依赖的javax.annotation升级到不签名的jar包

jetty-annotation依赖javax.annotation
上一篇 下一篇

猜你喜欢

热点阅读