跳到主要内容
版本:V2.2.0

Java 集成

sslTrus 提供 sslTrusJarsigner Java Provider,可与 JDK 自带的 jarsigner 工具配合使用,通过远程代码签名服务完成 Java JAR 文件签名。

签名过程中,代码签名私钥始终保存在云端 HSM 中。本地负责生成待签名数据和签名结构,并通过 sslTrusJarsigner Provider 调用远程服务完成私钥签名。

除 JAR 签名外,sslTrusJarsigner 还提供 XMLDSig 签名能力,可用于 XML 数字签名场景。

准备工作

使用前请准备:

  • JDK 8 或更高版本。
  • sslTrusJarsigner-<version>.jar
  • Access Key。
  • Access Secret。
  • 证书编号(Cert Code)。
  • 待签名的 JAR 文件或 XML 文件。

本文示例中的 <version>、访问凭证、证书编号和文件路径均需要替换为实际值。

下载 sslTrusJarsigner

sslTrusJarsigner 发布页 下载最新发布包并解压。

发布包包含:

sslTrusJarsigner-<version>.jar
SHA-256 校验文件

建议在使用前根据 SHA-256 校验文件验证 sslTrusJarsigner-<version>.jar 的完整性。

检查运行环境

首先确认 Java 和 JDK 自带的 jarsigner 可以正常使用:

java -version
jarsigner -help

检查 sslTrusJarsigner 版本:

java -jar sslTrusJarsigner-<version>.jar --version

查看帮助:

java -jar sslTrusJarsigner-<version>.jar --help

如果 jarsigner 命令不存在,请确认当前安装的是完整 JDK,而不是仅包含 Java Runtime 的运行环境。

配置访问凭证

sslTrusJarsigner 通过环境变量读取远程代码签名服务的访问凭证和证书编号。

Linux 和 macOS

export SSLTRUS_JARSIGNER_ACCESS_KEY="YOUR_ACCESS_KEY"
export SSLTRUS_JARSIGNER_ACCESS_SECRET="YOUR_ACCESS_SECRET"
export SSLTRUS_JARSIGNER_CERT_CODE="YOUR_CERT_CODE"

Windows PowerShell

$env:SSLTRUS_JARSIGNER_ACCESS_KEY = "YOUR_ACCESS_KEY"
$env:SSLTRUS_JARSIGNER_ACCESS_SECRET = "YOUR_ACCESS_SECRET"
$env:SSLTRUS_JARSIGNER_CERT_CODE = "YOUR_CERT_CODE"

如果服务人员提供了专用服务地址,还需要设置 SSLTRUS_JARSIGNER_URL

Linux 和 macOS:

export SSLTRUS_JARSIGNER_URL="YOUR_SERVICE_URL"

Windows PowerShell:

$env:SSLTRUS_JARSIGNER_URL = "YOUR_SERVICE_URL"

如果没有提供专用服务地址,不需要设置该变量。

Access Secret 属于敏感凭证,不应写入源代码、公开配置文件或构建日志。自动化环境建议通过 CI/CD Secret 或其他凭证管理机制注入。

JAR 签名

sslTrusJarsigner 通过 Java Security Provider 机制与标准 jarsigner 工具集成。

下面的示例将:

app-unsigned.jar

签名后输出为:

app-signed.jar

JDK 9 或更高版本

Linux 和 macOS:

jarsigner \
-keystore NONE \
-storetype SSLTRUS \
-storepass SSLTRUS \
-providerPath "sslTrusJarsigner-<version>.jar" \
-providerClass com.racent.codesign.SSLTrusProvider \
-sigalg SHA256withRSA \
-tsa http://timestamp.sectigo.com \
-signedjar "app-signed.jar" \
"app-unsigned.jar" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell:

jarsigner `
-keystore NONE `
-storetype SSLTRUS `
-storepass SSLTRUS `
-providerPath "sslTrusJarsigner-<version>.jar" `
-providerClass com.racent.codesign.SSLTrusProvider `
-sigalg SHA256withRSA `
-tsa http://timestamp.sectigo.com `
-signedjar "app-signed.jar" `
"app-unsigned.jar" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

JDK 8

JDK 8 加载 Provider 的方式与 JDK 9 及更高版本不同。

首先确认:

JAVA_HOME

指向完整的 JDK 8 安装目录。

Linux 和 macOS:

jarsigner \
-J-cp \
-J"$JAVA_HOME/lib/tools.jar:sslTrusJarsigner-<version>.jar" \
-keystore NONE \
-storetype SSLTRUS \
-storepass SSLTRUS \
-providerClass com.racent.codesign.SSLTrusProvider \
-sigalg SHA256withRSA \
-tsa http://timestamp.sectigo.com \
-signedjar "app-signed.jar" \
"app-unsigned.jar" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell:

jarsigner `
-J-cp `
"-J$env:JAVA_HOME\lib\tools.jar;sslTrusJarsigner-<version>.jar" `
-keystore NONE `
-storetype SSLTRUS `
-storepass SSLTRUS `
-providerClass com.racent.codesign.SSLTrusProvider `
-sigalg SHA256withRSA `
-tsa http://timestamp.sectigo.com `
-signedjar "app-signed.jar" `
"app-unsigned.jar" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

使用时需要注意:

  • 命令最后的证书编号必须与 SSLTRUS_JARSIGNER_CERT_CODE 一致。
  • 建议使用 -signedjar 输出到新文件,避免覆盖原始 JAR。
  • 示例使用 SHA256withRSA 完成代码签名。
  • 不需要时间戳时,可以删除 -tsa 及其后的时间戳地址。

时间戳

建议对正式发布的 JAR 签名添加可信时间戳。

示例中使用:

http://timestamp.sectigo.com

对应参数:

-tsa http://timestamp.sectigo.com

时间戳用于证明签名发生的时间,不会将原始 JAR 文件上传到时间戳服务器。

如果需要使用其他时间戳服务,可以将 -tsa 后的地址替换为符合实际签名策略的 TSA 地址。

关于不同时间戳服务及生产环境选择,请参阅 参考资料

XML 签名

sslTrusJarsigner 还提供 XML 数字签名能力。

XML 文件可以通过 sign-xml 命令生成 XMLDSig Enveloped Signature。

签名过程中,本地负责生成 XMLDSig 所需的摘要和签名结构,实际 RSA 私钥签名由远程代码签名服务完成。

Linux 和 macOS

java -jar sslTrusJarsigner-<version>.jar \
sign-xml \
"input.xml" \
"signed.xml" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell

java -jar sslTrusJarsigner-<version>.jar `
sign-xml `
"input.xml" `
"signed.xml" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

默认输出的 KeyInfo 只包含叶子证书。如果接收方要求 XML 内携带完整证书链,可以在命令末尾加入 --full-chain 参数。

执行完成后:

input.xml

为原始 XML 文件,

signed.xml

为包含 XML 数字签名的输出文件。

代码签名私钥不会写入 XML 文件,也不会保存到本地计算机。

生成验证文件

签名完成后,可以生成用于验证签名的 JKS 文件。

Linux 和 macOS:

java -jar sslTrusJarsigner-<version>.jar \
generate-keystore \
"$SSLTRUS_JARSIGNER_CERT_CODE" \
"verify.jks" \
"SSLTRUS"

Windows PowerShell:

java -jar sslTrusJarsigner-<version>.jar `
generate-keystore `
"$env:SSLTRUS_JARSIGNER_CERT_CODE" `
"verify.jks" `
"SSLTRUS"

生成:

verify.jks

该文件仅用于签名验证,不能用于执行代码签名。

代码签名私钥仍然保存在远程 HSM 中,不会写入 verify.jks

验证 JAR 签名

使用生成的 verify.jks 验证签名:

jarsigner \
-verify \
-verbose \
-certs \
-keystore "verify.jks" \
-storetype JKS \
-storepass "SSLTRUS" \
"app-signed.jar"

如果只需要查看 JAR 中已有的签名信息,可以执行:

jarsigner -verify -verbose -certs "app-signed.jar"

验证签名只检查现有签名,不会重新调用远程私钥执行签名。

签名次数

Jarsigner 的签名次数按照实际成功完成的远程签名动作计算。

通常情况下:

操作签名次数
对一个 JAR 成功签名一次1 次
分别签名 3 个 JAR3 次
对同一个 JAR 再执行一次签名再增加 1 次
jarsigner -verify 验证签名0 次
生成 verify.jks0 次

因此,签名次数主要取决于实际执行了多少次成功的签名操作,而不是 Java 项目的源代码文件数量。

详细规则请参阅 参考资料

常见问题

缺少 Access Key、Access Secret 或证书编号

确认当前终端已经设置:

SSLTRUS_JARSIGNER_ACCESS_KEY
SSLTRUS_JARSIGNER_ACCESS_SECRET
SSLTRUS_JARSIGNER_CERT_CODE

设置环境变量后,需要在同一个终端会话中执行签名命令。

Invalid option: -providerPath

如果出现:

Invalid option: -providerPath

通常表示当前使用的是 JDK 8。

JDK 8 不使用 JDK 9 及更高版本示例中的 -providerPath 参数,请改用本文提供的 JDK 8 命令。

无法加载 SSLTrusProvider

如果提示无法加载:

com.racent.codesign.SSLTrusProvider

请检查:

  • sslTrusJarsigner-<version>.jar 路径是否正确。
  • 文件名中的版本号是否与实际文件一致。
  • JDK 8 环境中的 JAVA_HOME 是否指向完整 JDK。

找不到证书或 alias

请检查:

  • 证书编号是否正确。
  • 命令最后指定的证书编号是否与 SSLTRUS_JARSIGNER_CERT_CODE 一致。
  • 当前 Access Key 和 Access Secret 是否具有该证书的使用权限。

远程签名请求失败

请检查:

  • 当前网络是否能够访问远程代码签名服务。
  • 代理、防火墙和 DNS 配置是否正常。
  • Access Key 和 Access Secret 是否正确。
  • 证书编号是否正确。
  • 如果使用专用服务地址,SSLTRUS_JARSIGNER_URL 是否按照实际交付信息配置。

排查问题时可以保留完整错误信息,但在提交日志或错误截图前,应删除或脱敏 Access Secret 等敏感凭证。

时间戳失败

确认当前网络能够访问 -tsa 指定的时间戳服务器。

如果业务允许,可以暂时移除:

-tsa <URL>

再次执行签名,用于判断问题发生在远程代码签名还是时间戳请求阶段。

安全说明

Java 集成过程中需要注意:

  • Access Secret 应作为敏感凭证保存。
  • 不要将访问凭证提交到 Git 仓库。
  • 不要在日志中输出完整 Access Secret。
  • verify.jks 仅用于验证,不包含可用于远程签名的私钥。
  • 本地 sslTrusJarsigner Provider 不保存代码签名私钥。
  • 私钥签名操作始终由远程代码签名服务完成。
  • 自动化环境建议使用 CI/CD Secret 或专用凭证管理系统注入访问凭证。

相关集成方式

如果需要签名的不是 Java JAR 或 XML 文件,可以根据实际场景选择其他集成方式:

场景集成方式
直接通过命令行签名 EXE、DLL、MSI 等文件客户端工具
Microsoft SignTool、Visual Studio 等 Windows 工具Windows Provider
GitHub Actions、Electron Builder 等自动化构建CI/CD 与构建工具
自行开发远程签名客户端API 集成