如何以编程方式验证使用 jarsigner 签名的 jar

2022-09-01 17:28:19

我想使用jarsigner对jar进行签名,然后使用Java应用程序对其进行验证,该应用程序没有将签名的jar作为其类路径的一部分(即仅使用jar的文件系统位置)

现在我的问题是从jar中获取签名文件,有没有一种简单的方法来做到这一点?

我玩过 Inflater 和 Jar InputStreams,但没有运气。

还是可以以更好的方式完成这项工作?

谢谢


答案 1

您只需使用java.util..jar.JarFile打开JAR,并告诉它验证JAR文件。如果 JAR 已签名,则 JarFile 可以选择对其进行验证(默认情况下处于启用状态)。但是,JarFile 也会愉快地打开未签名的 JAR,因此您还必须检查文件是否已签名。您可以通过检查 JAR 的清单中的 *-Digest 属性来执行此操作:对具有此类属性属性的元素进行签名。

例:

JarFile jar = new JarFile(new File("path/to/your/jar-file"));

// This call will throw a java.lang.SecurityException if someone has tampered
// with the signature of _any_ element of the JAR file.
// Alas, it will proceed without a problem if the JAR file is not signed at all
InputStream is = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF"));
Manifest man = new Manifest(is);
is.close();

Set<String> signed = new HashSet();
for(Map.Entry<String, Attributes> entry: man.getEntries().entrySet()) {
    for(Object attrkey: entry.getValue().keySet()) {
        if (attrkey instanceof Attributes.Name && 
           ((Attributes.Name)attrkey).toString().indexOf("-Digest") != -1)
            signed.add(entry.getKey());
    }
}

Set<String> entries = new HashSet<String>();
for(Enumeration<JarEntry> entry = jar.entries(); entry.hasMoreElements(); ) {
    JarEntry je = entry.nextElement();
    if (!je.isDirectory())
        entries.add(je.getName());
}

// contains all entries in the Manifest that are not signed.
// Ususally, this contains:
//  * MANIFEST.MF itself
//  * *.SF files containing the signature of MANIFEST.MF
//  * *.DSA files containing public keys of the signer

Set<String> unsigned = new HashSet<String>(entries);
unsigned.removeAll(signed);

// contains all the entries with a signature that are not present in the JAR
Set<String> missing = new HashSet<String>(signed);
missing.removeAll(entries);

答案 2

安全提供程序实现指南概述了验证 JAR 的过程。尽管这些说明是供 JCA 加密服务提供程序自行验证的,但它们应该适用于您的问题。

具体来说,请查看示例代码“MyJCE.java”中的方法。verify(X509Certificate targetCert)


推荐