Java 签名jar篡改验证

Java 签名jar篡改验证,java,security,osgi,jar-signing,knopflerfish,Java,Security,Osgi,Jar Signing,Knopflerfish,我有一个Web服务器,它将OSGI捆绑包作为自签名jar文件提供服务。这些都是使用OSGiAPI在我的设备上下载和安装的。我在knopflerfish OSGI中启用了安全性,并用我的公钥将其指向密钥库。我想验证我下载的代码不能在MITM攻击或其他情况下被篡改 为了测试这一点,我尝试稍微更改并重新编译我以前签名和验证过的一个包,使用7zip解压旧的、已签名的jar和新编译的jar,并复制META-INF文件夹的内容,覆盖仍然未签名的MANIFEST.MF并提供.SF和.RSA文件。 当我试图下载

我有一个Web服务器,它将OSGI捆绑包作为自签名jar文件提供服务。这些都是使用OSGiAPI在我的设备上下载和安装的。我在knopflerfish OSGI中启用了安全性,并用我的公钥将其指向密钥库。我想验证我下载的代码不能在MITM攻击或其他情况下被篡改

为了测试这一点,我尝试稍微更改并重新编译我以前签名和验证过的一个包,使用7zip解压旧的、已签名的jar和新编译的jar,并复制META-INF文件夹的内容,覆盖仍然未签名的MANIFEST.MF并提供.SF和.RSA文件。 当我试图下载并安装这个jar文件时,我确实遇到了一个错误:

[stderr] org.osgi.framework.BundleException: Failed to install bundle: java.io.IOException: MANIFEST.MF must be first in archive when using signatures.
[stderr]        at org.knopflerfish.framework.Bundles.install0(Bundles.java:178)
[stderr]        at org.knopflerfish.framework.SecurePermissionOps$14.run(SecurePermissionOps.java:727)
[stderr]        at org.knopflerfish.framework.SecurePermissionOps$14.run(SecurePermissionOps.java:723)
[stderr]        at java.security.AccessController.doPrivileged(Native Method)
[stderr]        at org.knopflerfish.framework.SecurePermissionOps.callInstall0(SecurePermissionOps.java:722)
[stderr]        at org.knopflerfish.framework.Bundles.install(Bundles.java:118)
[stderr]        at org.knopflerfish.framework.BundleContextImpl.installBundle(BundleContextImpl.java:109)
[stderr]        at no.aventi.sam.Activator.handleEvent(Activator.java:190)
[stderr]        at org.knopflerfish.bundle.event.TrackedEventHandler.handleEventSubjectToFilter(TrackedEventHandler.java:71)
[stderr]        at org.knopflerfish.bundle.event.InternalAdminEvent.deliverToHandles(InternalAdminEvent.java:153)
[stderr]        at org.knopflerfish.bundle.event.InternalAdminEvent.deliver(InternalAdminEvent.java:114)
[stderr]        at org.knopflerfish.bundle.event.QueueHandler.run(QueueHandler.java:120)
[stderr] Caused by: java.io.IOException: MANIFEST.MF must be first in archive when using signatures.
[stderr]        at org.knopflerfish.framework.bundlestorage.file.Archive.downloadArchive(Archive.java:271)
[stderr]        at org.knopflerfish.framework.bundlestorage.file.BundleArchiveImpl.<init>(BundleArchiveImpl.java:133)

[stderr]        at org.knopflerfish.framework.bundlestorage.file.BundleStorageImpl.insertBundleJar(BundleStorageImpl.java:219)
[stderr]        at org.knopflerfish.framework.Bundles.install0(Bundles.java:161)
[stderr]        ... 11 more
[stderr]org.osgi.framework.BundleException:未能安装bundle:java.io.IOException:使用签名时,必须将MANIFEST.MF放在存档文件的第一位。
[stderr]位于org.knopflerfish.framework.Bundles.install0(Bundles.java:178)
[stderr]位于org.knopflerfish.framework.SecurePermissionOps$14.run(SecurePermissionOps.java:727)
[stderr]位于org.knopflerfish.framework.SecurePermissionOps$14.run(SecurePermissionOps.java:723)
[stderr]位于java.security.AccessController.doPrivileged(本机方法)
[stderr]位于org.knopflerfish.framework.SecurePermissionOps.callInstall0(SecurePermissionOps.java:722)
[stderr]位于org.knopflerfish.framework.Bundles.install(Bundles.java:118)
[stderr]位于org.knopflerfish.framework.BundleContextImpl.installBundle(BundleContextImpl.java:109)
[stderr]位于第aventi.sam.Activator.handleEvent号(Activator.java:190)
[stderr]位于org.knopflerfish.bundle.event.TrackedEventHandler.HandleEventsObjectToFilter(TrackedEventHandler.java:71)
[stderr]位于org.knopflerfish.bundle.event.InternalAdminEvent.deliverToHandles(InternalAdminEvent.java:153)
[stderr]位于org.knopflerfish.bundle.event.InternalAdminEvent.deliver(InternalAdminEvent.java:114)
[stderr]位于org.knopflerfish.bundle.event.QueueHandler.run(QueueHandler.java:120)
[stderr]由以下原因引起:java.io.IOException:MANIFEST.MF在使用签名时必须位于归档文件的第一位。
[stderr]位于org.knopflerfish.framework.bundlestreage.file.Archive.downloadArchive(Archive.java:271)
[stderr]位于org.knopflerfish.framework.bundlestreage.file.BundleArchiveImpl.(BundleArchiveImpl.java:133)
[stderr]位于org.knopflerfish.framework.bundlestrage.file.bundlestrageimpl.insertBundleJar(bundlestrageimpl.java:219)
[stderr]位于org.knopflerfish.framework.Bundles.install0(Bundles.java:161)
[stderr]。。。还有11个
我还尝试了另一种方法,将新的.class文件复制到正确签名的jar中,但得到了相同的错误

我不确定实际验证安全方案需要什么样的输出。我得到的错误是否意味着java检测到错误的签名并因此拒绝了它?或者这仅仅意味着,当我手动写入jar文件时,7zip并没有保持结构完整,比我更好的黑客仍然可以轻易篡改我的jar文件

jarsigner-验证被篡改的jar文件给我的
java.lang.SecurityException:SHA-256摘要错误

这就更有意义了,如果我“正确”篡改jar,我能期望这样吗?

异常告诉您jar文件无效。所以它甚至没有尝试验证签名


7zip不适合创建/编辑jar文件。您应该使用javajar工具。请参见(签名)JARs的要求之一是清单是ZIP文件中的第一个条目。原因是清单在清单的Name部分包含JAR中资源的摘要

 Name: foo/bar/Xyz.class
 Digest-SHA-1: 2A345C6D7890F2A345C6D7890F2A345C6D7890F
 Digest-MD5: 7890F2A345C6D789
这些摘要是加载其他资源并验证它们所必需的。签名者文件(.SF)也包含清单格式的此名称部分的摘要。然后,.DSA或.RSA文件包含此.SF文件的签名

如果清单不是第一个,您就无法流式传输JAR,您将始终必须将其复制到磁盘,然后从文件中打开它,以便进行随机访问。通过强制首先执行清单,JarInputStream可以在资源到达时加载资源并立即进行验证。不幸的是,jarsigner工具不是基于标准的JDK加密库,在其他方面有点奇怪。您得到另一个错误的原因是,它可能将JAR作为文件打开,因此可以随机访问清单,所以它不在乎清单不是第一个

该模型非常灵活,但也很难理解。它允许多个签名者对捆绑包进行部分签名。OSGi增加了不使用部分签名的额外要求。没有这个要求,我记得有一些安全问题


请注意,任何人都可以将资源添加到您的包中,如果未将资源添加到清单中的Name部分,则不会检测到此情况。但是,清单中列出的任何资源都必须与给定摘要相匹配

其他答案都是正确的,因为我的jar文件是通过使用7zip而无效的,而不考虑文件顺序,因此当我得到问题中的错误时,安全性不是我遇到的问题。他们没有直接回答我应该怎么做,所以我会展示我是如何让它工作的,并接受我自己的答案

我使用jdk中的jar程序,而不是使用7zip,用一个经过编辑的.class文件更新了签名的jar:

jar.exe -uvf <jarfile.jar> </path/to/classfile.class>

对于不同于签名的类文件来说,这似乎是一个合理的错误,并且与
jarsigner的错误相匹配-验证

这很有趣,攻击者是否可能在OSGI中执行此类添加的资源?例如,通过编辑清单中的Bundle Activator字段来指向添加的隐藏资源?或者清单在SF文件中被“消化”,因此不可能被篡改?我想我
[stderr] java.lang.SecurityException: SHA-256 digest error for ****.class
[stderr]         at sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:223)