jarsigner 是 Java 开发工具包(JDK)中的一个命令行工具,用于对 Java 归档文件(JAR 文件)进行数字签名和验证。
数字签名是一种用于确认数据的来源和完整性的机制。使用私钥对数据进行签名,并使用公钥进行验证。当用户下载应用程序时,可以使用与应用程序打包时使用的公钥进行验证,以确认应用程序未被篡改且来自可信的源。
确保应用程序的完整性,通过校验数字签名,可以验证应用程序没有被篡改;能防止篡改和中间人攻击,数字签名提供了认证机制,防止不被授权的修改或分发应用程序;增加用户信任度,数字签名是建立与用户之间信任关系的重要方式。
同时,也增加了开发和部署的复杂性,因为使用 jarsigner 需要额外的步骤来生成和管理密钥库、创建签名以及进行时间戳等操作。
jarsigner 命令的基本语法如下:
(1)签名
jarsigner (-options) jar-file alias
(2)验证签名
jarsigner -verify (-options) jar-file (alias...)
其中,options 是可选参数,jar-file 是要签名的 JAR 文件,alias 指定了密钥库中用于签名的别名。
options 选项取值如下:
-keystore <url> 密钥库位置
-storepass <口令> 用于密钥库完整性的口令
-storetype <类型> 密钥库类型
-keypass <口令> 私有密钥的口令 (如果不同)
-certchain <文件> 替代证书链文件的名称
-sigfile <文件> .SF/.DSA 文件的名称
-signedjar <文件> 已签名的 JAR 文件的名称
-digestalg <算法> 摘要算法的名称
-sigalg <算法> 签名算法的名称
-verify 验证已签名的 JAR 文件
-verbose:suboptions 签名/验证时输出详细信息。子选项可以是 all, grouped 或 summary
-certs 输出详细信息和验证时显示证书
-tsa <url> 时间戳颁发机构的位置
-tsacert <别名> 时间戳颁发机构的公共密钥证书
-tsapolicyid <oid> 时间戳颁发机构的 TSAPolicyID
-tsadigestalg <算法> 时间戳请求中的摘要数据的算法
-altsigner <类> 替代的签名机制的类名
-altsignerpath <路径列表> 替代的签名机制的位置
-internalsf 在签名块内包含 .SF 文件
-sectionsonly 不计算整个清单的散列
-protected 密钥库具有受保护验证路径
-providerName <名称> 提供方名称
-providerClass <类> 加密服务提供方的名称
-providerArg <参数>... 主类文件和构造器参数
-strict 将警告视为错误
该示例使用 keystore.jks 密钥库中的 myKey 别名对 commons-io.jar 文件进行签名,命令如下:
jarsigner -keystore keystore.jks -storepass 123456 commons-io.jar myKey
上面命令将使用名为 keystore.jks 的密钥库中的别名为 myKey 的密钥对对名为 commons-io.jar 的 JAR 文件进行签名,密钥库的密码为 123456。
运行日志如下:
C:\Users\Administrator\Desktop> jarsigner -keystore keystore.jks -storepass 123456 commons-io.jar myKey jar 已签名。 警告: 未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期日期 (2034-06-29) 或以后的任何撤销日期之后, 用户可能无法验证此 jar。
上述的“警告”信息表明,当尝试对 JAR(Java归档)文件进行时间戳处理(如通过 JAR 签名)时,没有提供必要的 -tsa 或 -tsacert 参数。时间戳服务(TSA, Time Stamp Authority)用于为 JAR 文件中的签名提供时间戳,以确保签名在签名后的一段时间内仍然有效,即使签名者的证书已经过期。
在 Java 中,使用 jarsigner 工具进行 JAR 文件签名时,可以使用 -tsa 参数来指定 TSA 服务器的 URL。-tsacert 参数用于提供 TSA 证书的别名,这在某些情况下可能是必需的,例如当 TSA 使用自签名证书时。
你确定需要为 JAR 文件添加时间戳,你应该使用 -tsa 参数,并指定一个有效的 TSA 服务器 URL。例如:
jarsigner -keystore keystore.jks -storepass 123456 -keypass 123456 -tsa http://timestamp.comodoca.com/rfc3161 commons-io.jar myKey
运行日志如下:
C:\Users\Administrator\Desktop> jarsigner -keystore keystore.jks -storepass 123456 -keypass 123456 -tsa http://timestamp.comodoca.com/rfc3161 commons-io.jar myKey jar 已签名。
执行下面命令验证 commons-io.jar 文件的签名,例如:
jarsigner -verify -keystore keystore.jks commons-io.jar
运行日志如下:
C:\Users\Administrator\Desktop>jarsigner -verify -keystore keystore.jks commons-io.jar jar 已验证。
该示例将验证名为 commons-io.jar 的 JAR 文件的数字签名,使用名为 keystore.jks 的密钥库中的证书来验证签名。
下面命令将以详细模式显示名为 commons-io.jar 的 JAR 文件的签名信息,包括签名者和证书链等。
jarsigner -verify -verbose -certs commons-io.jar
运行日志如下:
C:\Users\Administrator\Desktop> jarsigner -verify -verbose -certs commons-io.jar s 17676 Tue Jul 02 11:00:24 CST 2024 META-INF/MANIFEST.MF [条目的签名日期为 24-7-2 上午11:21] X.509, CN=hxstrive.com, OU=IT, O=hxstrive, L=ChengDu, ST=SiChuan, C=CN [证书的有效期为24-7-1 下午5:06至34-6-29 下午5:06] [CertPath 未验证: Path does not chain with any of the trust anchors] 15983 Tue Jul 02 11:21:50 CST 2024 META-INF/MYKEY.SF 6317 Tue Jul 02 11:21:50 CST 2024 META-INF/MYKEY.RSA 0 Thu Apr 14 09:21:32 CST 2016 META-INF/ 0 Thu Apr 14 09:21:32 CST 2016 META-INF/maven/ 0 Thu Apr 14 09:21:32 CST 2016 META-INF/maven/commons-io/ 0 Thu Apr 14 09:21:32 CST 2016 META-INF/maven/commons-io/commons-io/ 0 Thu Apr 14 09:19:58 CST 2016 org/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/comparator/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/monitor/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/input/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/filefilter/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/serialization/ 0 Thu Apr 14 09:19:58 CST 2016 org/apache/commons/io/output/ sm 11359 Thu Apr 14 09:19:56 CST 2016 META-INF/LICENSE.txt [条目的签名日期为 24-7-2 上午11:21] X.509, CN=hxstrive.com, OU=IT, O=hxstrive, L=ChengDu, ST=SiChuan, C=CN [证书的有效期为24-7-1 下午5:06至34-6-29 下午5:06] [CertPath 未验证: Path does not chain with any of the trust anchors] sm 171 Thu Apr 14 09:19:56 CST 2016 META-INF/NOTICE.txt [条目的签名日期为 24-7-2 上午11:21] X.509, CN=hxstrive.com, OU=IT, O=hxstrive, L=ChengDu, ST=SiChuan, C=CN [证书的有效期为24-7-1 下午5:06至34-6-29 下午5:06] [CertPath 未验证: Path does not chain with any of the trust anchors] ... s = 已验证签名 m = 在清单中列出条目 k = 在密钥库中至少找到了一个证书 i = 在身份作用域内至少找到了一个证书 - 由 "CN=hxstrive.com, OU=IT, O=hxstrive, L=ChengDu, ST=SiChuan, C=CN" 签名 摘要算法: SHA-256 签名算法: SHA256withRSA, 2048 位密钥 由 "CN="Sectigo RSA Time Stamping Signer #4", O=Sectigo Limited, ST=Manchester, C=GB" 于 星期二 七月 02 03:21:50 UTC 2024 加时间戳 时间戳摘要算法: SHA-256 时间戳签名算法: SHA384withRSA, 4096 位密钥 jar 已验证。 警告: 此 jar 包含证书链未验证的条目。
注意:上述输出中,"CertPath 未验证: Path does not chain with any of the trust anchors" 错误消息通常意味着在尝试验证一个证书链时,该链中的证书没有能够链接到任何受信任的根证书颁发机构(CA)或信任锚点。换句话说,证书链是不完整的,或者证书本身没有被客户端或服务器信任的CA所签发。