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

我想使用jarsigner签署一个jar,然后使用一个Java应用程序validation它,该应用程序没有签名的jar作为其类路径的一部分(即只使用jar的文件系统位置)

现在我的问题是从jar中获取签名文件,有一个简单的方法吗?

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

或者这是可以更好地完成的事情吗?

谢谢

安全提供程序实现指南概述了validationJAR的过程。 虽然这些说明适用于JCA加密服务提供商进行自我validation,但它们应适用于您的问题。

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

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

例:

 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 signed = new HashSet(); for(Map.Entry 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 entries = new HashSet(); for(Enumeration 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 unsigned = new HashSet(entries); unsigned.removeAll(signed); // contains all the entries with a signature that are not present in the JAR Set missing = new HashSet(signed); missing.removeAll(entries); 

您可以使用entry.getCodeSigners()来获取JAR中特定条目的签名者。

确保使用verify = true打开JarFile并在调用entry.getCodeSigners()之前完全读取JAR条目。

这样的东西可以用来validation每个不是签名文件的条目:

 boolean verify = true; JarFile jar = new JarFile(signedFile, verify); // Need each entry so that future calls to entry.getCodeSigners will return anything Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); IOUtils.copy(jar.getInputStream(entry), new NullOutputStream()); } // Now check each entry that is not a signature file entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String fileName = entry.getName().toUpperCase(Locale.ENGLISH); if (!fileName.endsWith(".SF") && !fileName.endsWith(".DSA") && !fileName.endsWith(".EC") && !fileName.endsWith(".RSA")) { // Now get code signers, inspect certificates etc here... // entry.getCodeSigners(); } } 

您可以使用jarsigner应用程序执行此操作。 在processbuilder(或Runtime.exec)中,您可以使用这些参数运行命令

  ProcessBulider pb = new ProcessBuilder("/usr/bin/jarsigner", "-verify", "-certs", f.getAbsolutePath()); 

如果输出contians已validation,则jar被签名

 Process p = pb.start(); p.waitFor(); InputStream is = p.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine()) != null) { if(line.contains("verified"); ... 

当你有jarsigner代码的输出时,你可以做更复杂的事情。