0

我有一个将 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 文件?

jarsigner -verify在被篡改的 jar 文件上给了我 java.lang.SecurityException: SHA-256 digest error 更有意义的信息,如果我“正确”篡改了 jar,我可以期待吗?

4

3 回答 3

1

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

7zip 不适合创建/编辑 jar 文件。您应该使用 java jar 工具。见https://www.webucator.com/how-to/how-create-jar-file-java.cfm

于 2019-04-17T12:33:14.417 回答
1

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

我使用 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

于 2019-04-23T14:46:41.363 回答
0

(签名的)JAR 的一个要求是清单是 ZIP 文件中的第一个条目。原因是清单在清单的名称部分包含 JAR 中资源的摘要。

 Name: foo/bar/Xyz.class
 Digest-SHA-1: 2A345C6D7890F2A345C6D7890F2A345C6D7890F
 Digest-MD5: 7890F2A345C6D789

这些摘要是加载其他资源并验证它们所必需的。签名者文件 (.SF) 包含此名称部分的摘要,也是清单格式。.DSA 或 .RSA 文件然后包含此 .SF 文件的签名。

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

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

请注意,任何人都可以将资源添加到您的包中,如果没有将它们也添加到清单中的名称部分,则不会检测到这一点。但是,清单中列出的任何资源都必须与给定的摘要匹配。

于 2019-04-18T07:28:20.243 回答