我有一个Web服务器,将OSGI捆绑软件作为自签名的jar文件。这些是在我的设备上使用OSGI API下载和安装的。我已在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
我还尝试了另一种方法,将新的.class文件复制到正确签名的jar中,并得到相同的错误。
我不确定对安全方案的实际验证需要什么输出。我得到的错误是否意味着java检测到错误的签名并因此拒绝了它?还是仅当我手动写入jar文件时7zip并未保持结构完整,而比我更好的黑客仍然可以轻易地篡改jar文件?
被篡改的jar文件上的 jarsigner -verify
给了我
java.lang.SecurityException: SHA-256 digest error
这更有意义,如果我“正确地”篡改了罐子,我可以期望吗?
答案 0 :(得分:1)
该异常告诉您jar文件无效。因此,它甚至都没有尝试验证签名。
7zip不适合创建/编辑jar文件。您应该使用Java jar工具。参见https://www.webucator.com/how-to/how-create-jar-file-java.cfm
答案 1 :(得分:0)
(已签名)JAR的要求之一是,清单是ZIP文件中的第一项。原因是清单包含清单清单“名称”部分中JAR中资源的摘要。
Name: foo/bar/Xyz.class
Digest-SHA-1: 2A345C6D7890F2A345C6D7890F2A345C6D7890F
Digest-MD5: 7890F2A345C6D789
这些摘要对于加载其他资源并进行验证是必需的。签名者文件(.SF)包含此 Name部分的摘要,也采用清单格式。然后,.DSA或.RSA文件包含此.SF文件的签名。
如果清单不是第一个清单,则您无法流式传输JAR,则始终必须将其复制到磁盘,然后从“文件”中将其打开,以便您具有随机访问权限。通过首先强制清单,JarInputStream可以在资源到达时加载它们并立即对其进行验证。不幸的是,Jar签名器工具不是基于标准的JDK加密库,并且在其他方面还很奇怪。出现其他错误的原因是,它很可能将JAR作为文件打开,因此可以随机访问Manifest,因此不必在意清单是否不在第一位。
该模型非常灵活,但也很难理解。它允许多个签名者,每个签名者可以部分地对分发包进行签名。 OSGi增加了一个额外的要求,即不使用部分签名。没有这个要求,我会遇到一些安全问题。
请注意,任何人都可以将资源添加到您的捆绑软件中,如果资源也没有添加到清单的“名称”部分中,则不会检测到。但是,清单中列出的任何资源都必须匹配给定的摘要。
答案 2 :(得分:0)
其他答案是正确的,因为我的jar文件通过使用7zip无效而不考虑文件顺序,因此,当我遇到问题的错误时,安全性不是我遇到的问题。他们没有直接回答我应该怎么做,所以我将展示如何使它起作用并接受自己的回答。
我使用jdk中的jar程序而不是7zip,使用已编辑的.class文件更新了签名的jar。
jar.exe -uvf <jarfile.jar> </path/to/classfile.class>
这导致来自Java的错误:
[stderr] java.lang.SecurityException: SHA-256 digest error for ****.class
[stderr] at sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:223)
对于与签名不同并与jarsigner -verify
匹配的类文件来说,这似乎是一个合理的错误