如何以编程方式在Java中对jar文件进行签名?

如何以编程方式在Java中对jar文件进行签名?,java,jar,sign,Java,Jar,Sign,以前有人这样做过吗?我在google上找到的唯一参考资料是:它仍然使用sun.*类,这将导致问题 也发现了这一点,但不适用于java16:我正在使用(它显然调用下面的命令行工具)。应该可以通过编程方式调用它。tools.jar文件中的类是sun.security.tools.JarSigner,它有一个静态run(ava.lang.String[]strings)方法,该方法采用与JarSigner可执行文件相同的参数 所以你可以称之为: sun.security.tools.JarSigner

以前有人这样做过吗?我在google上找到的唯一参考资料是:它仍然使用sun.*类,这将导致问题


也发现了这一点,但不适用于java16:

我正在使用(它显然调用下面的命令行工具)。应该可以通过编程方式调用它。

tools.jar文件中的类是sun.security.tools.JarSigner,它有一个静态run(ava.lang.String[]strings)方法,该方法采用与JarSigner可执行文件相同的参数

所以你可以称之为:

sun.security.tools.JarSigner.run(new String[] {
    "-keystore", keystoreFile.getAbsolutePath(),
    "-storepass", keystorePassword,
    outFile.getAbsolutePath(),
    keystoreAlias 
});

您需要确保tools.jar位于类路径中以进行编译和执行。

为了解决Java 7u45中WebStart应用程序中安全限制的突然变化,我们创建了一个。它使用番石榴15和Bouncy Castle bcpkix模块。它应该在Java6和Java7上运行。它只适用于小文件。可以将其用于任何目的。

请注意,
sun.security.tools.JarSigner
类是作为命令行实用程序编写的,而不是从Java代码调用的。因此,错误处理非常突然:代码只需将错误消息打印到标准输出,然后调用
System.exit()

这意味着,如果您从Java代码中调用该类,并且在尝试对jar进行签名时出现错误,那么运行代码的JVM将简单地停止。根据您的情况,这可能很好,但如果您的代码长时间运行或充当服务,那么就不太好了


因此,根据clamp的评论,最好使用ProcessBuilder调用jarsigner工具。然后,您可以对生成的流程对象调用
waitFor()
,并检查
exitValue()
以查看该命令是否成功<如果操作失败,code>getInputStream()将允许您读取写入标准输出的任何错误消息。

以下是如何使用JDK 9及更高版本执行此操作:

import java.io.*;
import java.util.zip.*;
import java.security.*;
import jdk.security.jarsigner.*;

char[] password = ...;
String keyStorePath = ...;
KeyStore ks = KeyStore.getInstance(new File(keyStorePath), password);
KeyStore.ProtectionParameter protParam =
   new KeyStore.PasswordProtection(password);

KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
   ks.getEntry("codecheck", protParam);

JarSigner signer = new JarSigner.Builder(pkEntry)
   .build();
String inputFile = ...;
String outputFile = ...;
try (ZipFile in = new ZipFile(inputFile);
      FileOutputStream out = new FileOutputStream(outputFile)) {
   signer.sign(in, out);
}


您可以从java内部调用jar签名者进程。最好使用ProcessBuilder。@wuntee:我怀疑Ant-Tak会很容易做到这一点。