系列中的上一篇
当前教程
Jarsigner - 签署您的 JAR 文件

系列中的上一篇: Keytool - 管理您的密钥库

系列中的下一篇: Kinit - 获取和授予 Kerberos 票证

Jarsigner - 签署您的 JAR 文件

 

介绍 Jarsigner

jarsigner - 签署和验证 Java 归档 (JAR) 文件

 

概要

jarsigner _options_ _jar-file_ _alias_
jarsigner -verify _options_ _jar-file_ _alias_ ...

选项

命令行选项。请参阅 Jarsigner 的选项

-verify

-verify 选项可以在 JAR 文件名之后接受零个或多个密钥库别名。当指定 -verify 选项时,jarsigner 命令会检查用于验证 JAR 文件中每个已签署条目的证书是否与密钥库别名之一匹配。别名在 -keystore 指定的密钥库或默认密钥库中定义。

如果您还指定了 -strict 选项,并且 jarsigner 命令检测到严重警告,则会显示消息“jar 已验证,但存在签名错误”。

jar-file

要签署的 JAR 文件。

如果您还指定了 -strict 选项,并且 jarsigner 命令检测到严重警告,则会显示消息“jar 已签署,但存在签名错误”。

别名

别名在 -keystore 指定的密钥库或默认密钥库中定义。

 

描述

jarsigner 工具有两个用途

  • 签署 Java 归档 (JAR) 文件。

  • 验证已签署 JAR 文件的签名和完整性。

JAR 功能允许将类文件、图像、声音和其他数字数据打包到单个文件中,以便更快、更轻松地分发。名为 jar 的工具使开发人员能够生成 JAR 文件。(从技术上讲,任何 ZIP 文件也可以被视为 JAR 文件,尽管当由 jar 命令创建或由 jarsigner 命令处理时,JAR 文件还包含 META-INF/MANIFEST.MF 文件。)

数字签名是根据某些数据(要签署的数据)和实体(个人、公司等)的私钥计算的一串位。与手写签名类似,数字签名具有许多有用的特性

  • 可以使用与用于生成签名的私钥相对应的公钥进行计算来验证其真实性。

  • 只要私钥保密,它就无法伪造。

  • 它是签署数据的函数,因此不能声称是其他数据的签名。

  • 签署的数据不能更改。如果数据被更改,则签名将无法验证为真实。

要为文件生成实体的签名,实体必须首先拥有与其关联的公钥/私钥对,以及一个或多个用于验证其公钥的证书。证书是来自一个实体的数字签名声明,说明另一个实体的公钥具有特定值。

jarsigner 命令使用密钥库中的密钥和证书信息为 JAR 文件生成数字签名。密钥库是私钥及其关联的 X.509 证书链的数据库,这些证书验证相应的公钥。keytool 命令用于创建和管理密钥库。

jarsigner 命令使用实体的私钥生成签名。已签署的 JAR 文件包含(除其他事项外)密钥库中用于签署文件的私钥对应的公钥证书的副本。jarsigner 命令可以使用其内部的证书(在其签名块文件中)验证已签署 JAR 文件的数字签名。

jarsigner 命令可以生成包含时间戳的签名,使系统或部署人员能够检查 JAR 文件是否在签名证书仍然有效时签署的。

此外,API 允许应用程序获取时间戳信息。

目前,jarsigner 命令只能签署由 jar 命令创建的 JAR 文件或 zip 文件。JAR 文件与 zip 文件相同,只是它们还具有 META-INF/MANIFEST.MF 文件。当 jarsigner 命令签署 zip 文件时,会创建 META-INF/MANIFEST.MF 文件。

默认的 jarsigner 命令行为是签署 JAR 或 zip 文件。使用 -verify 选项验证已签署的 JAR 文件。

jarsigner 命令还尝试在签署或验证后验证签名者的证书。在验证期间,当指定 -revCheck 选项时,它会检查签名者证书链中每个证书的吊销状态。如果存在验证错误或任何其他问题,命令会生成警告消息。如果您指定 -strict 选项,则命令会将严重警告视为错误。请参阅 错误和警告

 

密钥库别名

所有密钥库实体都使用唯一的别名访问。

当您使用 jarsigner 命令签署 JAR 文件时,您必须指定包含生成签名所需的私钥的密钥库条目的别名。如果没有指定输出文件,它会将已签署的 JAR 文件覆盖原始 JAR 文件。

密钥库受密码保护,因此必须指定存储密码。当您未在命令行上指定它时,系统会提示您输入它。类似地,私钥在密钥库中受密码保护,因此必须指定私钥的密码,并且当您未在命令行上指定它并且它与存储密码不同时,系统会提示您输入密码。

 

密钥库位置

jarsigner 命令有一个 -keystore 选项,用于指定要使用的密钥库的 URL。密钥库默认存储在用户主目录中的名为 .keystore 的文件中,该目录由 user.home 系统属性确定。

Linux 和 macOS: user.home 默认情况下为用户的主目录。

-keystore 选项的输入流传递给 KeyStore.load 方法。如果将 NONE 指定为 URL,则将空流传递给 KeyStore.load 方法。当 KeyStore 类不是基于文件时,应指定 NONE,例如,当它驻留在硬件令牌设备上时。

 

密钥库实现

java.security 包中提供的 KeyStore 类提供了一些定义明确的接口来访问和修改密钥库中的信息。您可以拥有多个不同的具体实现,其中每个实现都针对特定类型的密钥库。

目前,有两个使用密钥库实现的命令行工具(keytooljarsigner)。

默认密钥库实现是 PKCS12。这是一个基于 RSA PKCS12 个人信息交换语法标准的跨平台密钥库。此标准主要用于存储或传输用户的私钥、证书和各种秘密。Oracle 提供了另一个内置实现。它将密钥库实现为具有名为 JKS 的专有密钥库类型(格式)的文件。它使用其各自的密码保护每个私钥,并使用(可能不同的)密码保护整个密钥库的完整性。

密钥库实现是基于提供者的,这意味着 KeyStore 类提供的应用程序接口是根据服务提供者接口 (SPI) 实现的。在 java.security 包中还有一个相应的抽象 KeystoreSpi 类,它定义了提供者必须实现的服务提供者接口方法。术语提供者指的是提供可以由 Java 安全 API 访问的一组服务的具体实现的包或一组包。要提供密钥库实现,客户端必须实现提供者并提供 KeystoreSpi 子类实现,如 如何在 Java 密码体系结构中实现提供者 中所述。

应用程序可以使用 KeyStore 类中的 getInstance 工厂方法从不同的提供者选择不同类型的密钥库实现。密钥库类型定义密钥库信息的存储和数据格式,以及用于保护密钥库中私钥和密钥库本身完整性的算法。不同类型的密钥库实现不兼容。

jarsigner 命令可以从可以使用 URL 指定的任何位置读取基于文件的密钥库。此外,这些命令可以读取非基于文件的密钥库,例如 Windows 上的 MSCAPI 和所有平台上的 PKCS11 提供的密钥库。

对于 jarsignerkeytool 命令,您可以在命令行上使用 -storetype 选项指定密钥库类型。

如果您没有显式指定密钥库类型,则这些工具会根据安全属性文件中指定的 keystore.type 属性的值选择密钥库实现。安全属性文件名为 java.security,它位于 JDK 安全属性目录 java.home/conf/security 中。

每个工具都会获取 keystore.type 值,然后检查所有已安装的提供者,直到找到一个实现该类型密钥库的提供者。然后,它使用该提供者中的密钥库实现。

KeyStore 类定义了一个名为 getDefaultType 的静态方法,允许应用程序检索 keystore.type 属性的值。以下代码行创建了安全属性文件中指定的默认密钥库类型的实例

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

默认密钥库类型是 pkcs12,它是一个基于 RSA PKCS12 个人信息交换语法标准的跨平台密钥库。这由安全属性文件中的以下行指定

keystore.type=pkcs12

密钥库类型指定中的大小写无关紧要。例如,JKSjks 相同。

要使这些工具使用除默认密钥库实现之外的密钥库实现,您可以更改该行以指定不同的密钥库类型。例如,如果您想使用 Oracle 的 jks 密钥库实现,则将该行更改为以下内容

keystore.type=jks

 

支持的算法

默认情况下,jarsigner 命令使用以下算法之一和块文件扩展名签署 JAR 文件,具体取决于私钥的类型和大小

  • 如果 RSASSA-PSS 密钥使用参数编码,则 jarsigner 将在签名中使用相同的参数。否则,jarsigner 将使用由密钥大小确定的参数,如上表所示。例如,一个 3072 位的 RSASSA-PSS 密钥将使用 RSASSA-PSS 作为签名算法,并使用 SHA-256 作为哈希和 MGF1 算法。

可以使用 -sigalg 选项覆盖这些默认签名算法。

jarsigner 命令使用 jdk.jar.disabledAlgorithmsjdk.security.legacyAlgorithms 安全属性来确定哪些算法被认为是安全风险。如果 JAR 文件使用任何被禁用的算法进行签名,则它将被视为未签名的 JAR 文件。如果 JAR 文件使用任何旧版算法进行签名,则它将被视为使用信息性警告进行签名,以告知用户旧版算法将在将来的更新中被禁用。有关详细的验证输出,请包含 -J-Djava.security.debug=jarjdk.jar.disabledAlgorithmsjdk.security.legacyAlgorithms 安全属性在 java.security 文件中定义(位于 JDK 的 $JAVA_HOME/conf/security 目录中)。

注意

为了提高开箱即用的安全性,默认密钥大小和签名算法名称会随着 JDK 的每个版本定期更新为更强大的值。如果与 JDK 的旧版本保持互操作性很重要,请确保这些默认值受这些版本支持,或者使用 -sigalg 选项来覆盖默认值,但风险自负。

 

已签名的 JAR 文件

当使用 jarsigner 命令对 JAR 文件进行签名时,输出的已签名 JAR 文件与输入的 JAR 文件完全相同,只是在 META-INF 目录中添加了两个文件:

  • 一个带有 .SF 扩展名的签名文件

  • 一个带有 .DSA.RSA.EC 扩展名的签名块文件

这两个文件的基文件名来自 -sigfile 选项的值。例如,当选项为 -sigfile MKSIGN 时,文件名为 MKSIGN.SFMKSIGN.RSA。在本文件中,我们假设签名者始终使用 RSA 密钥。

如果命令行中没有出现 -sigfile 选项,则 .SF 和签名块文件的基文件名是命令行中指定的别名的前 8 个字符,全部转换为大写。如果别名少于 8 个字符,则使用完整的别名。如果别名包含任何签名文件名中不允许的字符,则在形成文件名时,每个此类字符都将转换为下划线 (_) 字符。有效字符包括字母、数字、下划线和连字符。

 

签名文件

签名文件 (.SF 文件) 看起来类似于清单文件,清单文件始终包含在使用 jarsigner 命令对文件进行签名时生成的 JAR 文件中。对于 JAR 文件中包含的每个源文件,.SF 文件有两行,类似于清单文件,列出以下内容:

  • 文件名

  • 摘要算法名称 (SHA)

  • SHA 摘要值

注意

摘要算法名称 (SHA) 和 SHA 摘要值在同一行上。

在清单文件中,每个源文件的 SHA 摘要值是源文件中二进制数据的摘要(哈希)。在 .SF 文件中,指定源文件的摘要值是清单文件中源文件两行的哈希值。

默认情况下,签名文件包含一个标题,其中包含整个清单文件的哈希值。标题还包含清单标题的哈希值。标题的存在使验证优化成为可能。请参阅 JAR 文件验证

 

签名块文件

.SF 文件已签名,签名被放置在签名块文件中。此文件还包含在其中编码的证书或证书链,这些证书或证书链来自密钥库,用于验证与用于签名的私钥相对应的公钥。该文件具有扩展名 .DSA.RSA.EC,具体取决于使用的密钥算法。请参阅 支持的算法 中的表格。

 

签名时间戳

使用以下选项的 jarsigner 命令在对 JAR 文件进行签名时生成并存储签名时间戳:

  • -tsa url

  • -tsacert alias

  • -tsapolicyid policyid

  • -tsadigestalg algorithm

请参阅 jarsigner 的选项

 

JAR 文件验证

当签名有效且自签名生成以来 JAR 文件中包含的所有文件都没有更改时,将发生成功的 JAR 文件验证。JAR 文件验证涉及以下步骤:

  1. 验证 .SF 文件的签名。验证确保每个签名块文件中存储的签名是使用与公钥相对应的私钥生成的,该公钥的证书(或证书链)也出现在签名块文件中。它还确保签名是相应签名 (.SF) 文件的有效签名,因此 .SF 文件没有被篡改。

  2. 验证 .SF 文件中每个条目中列出的摘要与清单中的每个对应部分。.SF 文件默认包含一个标题,其中包含整个清单文件的哈希值。当标题存在时,验证可以检查标题中的哈希值是否与清单文件的哈希值匹配。如果匹配,则验证将继续执行下一步。如果没有匹配,则需要进行不太优化的验证,以确保 .SF 文件中每个源文件信息部分的哈希值等于清单文件中其对应部分的哈希值。请参阅签名文件。清单文件中存储在 .SF 文件标题中的哈希值可能不等于当前清单文件的哈希值的一个原因是,在生成签名和 .SF 文件后,一个或多个文件被添加到 JAR 文件中(使用 jar 工具)。当使用 jar 工具添加文件时,清单文件会通过为新文件添加部分而更改,但 .SF 文件不会更改。当自签名生成以来 JAR 文件中包含的所有文件都没有更改时,验证仍然被认为是成功的。当 .SF 文件非标题部分中的哈希值等于清单文件中对应部分的哈希值时,就会发生这种情况。

  3. 读取 JAR 文件中每个在 .SF 文件中具有条目的文件。在读取时,计算文件的摘要并将结果与清单部分中此文件的摘要进行比较。摘要应该相同,否则验证失败。如果在验证过程中发生任何严重的验证失败,则该过程将停止并抛出安全异常。jarsigner 命令会捕获并显示异常。

  4. 检查是否使用了被禁用的算法。请参阅 支持的算法

注意

您应该阅读任何额外的警告(如果您指定了 -strict 选项,则为错误),以及证书的内容(通过指定 -verbose-certs 选项),以确定是否可以信任签名。

 

JAR 文件的多个签名

可以通过多次在文件上运行 jarsigner 命令并在每次运行时指定不同人的别名,让多个人对 JAR 文件进行签名,如下所示:

jarsigner myBundle.jar susan
jarsigner myBundle.jar kevin

当 JAR 文件被多次签名时,结果 JAR 文件中会有多个 .SF 和签名块文件,每个签名对应一对。在前面的示例中,输出 JAR 文件包含以下名称的文件:

SUSAN.SF
SUSAN.RSA
KEVIN.SF
KEVIN.RSA

 

jarsigner 的选项

以下部分描述了 jarsigner 的选项。请注意以下标准:

  • 所有选项名称前都有一个连字符 (-)。

  • 选项可以按任何顺序提供。

  • 以斜体或带下划线显示的项目(选项值)表示必须提供的实际值。

  • -storepass-keypass-sigfile-sigalg-digestalg-signedjar 和与 TSA 相关的选项仅在对 JAR 文件进行签名时才相关;在验证已签名的 JAR 文件时,它们不相关。-keystore 选项与对 JAR 文件进行签名和验证相关。此外,在对 JAR 文件进行签名和验证时,会指定别名。

-keystore url

指定告诉密钥库位置的 URL。这默认为用户主目录中的 .keystore 文件,由 user.home 系统属性确定。

签名时需要密钥库。当默认密钥库不存在或您想要使用除默认密钥库之外的密钥库时,您必须显式指定密钥库。

验证时不需要密钥库,但如果指定了密钥库或默认密钥库存在并且还指定了-verbose选项,则会输出有关用于验证 JAR 文件的证书是否包含在该密钥库中的附加信息。

-keystore参数可以是文件名和路径规范,而不是 URL,在这种情况下,它与文件:URL 的处理方式相同,例如,以下等效:

  • -keystore filePathAndName

  • -keystore file:filePathAndName

如果在java.security安全属性文件(位于 JDK 的$JAVA_HOME/conf/security目录中)中配置了 Sun PKCS #11 提供程序,则keytooljarsigner工具可以通过指定以下选项在 PKCS #11 令牌上运行:

-keystore NONE -storetype PKCS11

例如,以下命令列出配置的 PKCS#11 令牌的内容:

keytool -keystore NONE -storetype PKCS11 -list
-storepass `:env` | `:file` _argument_

指定访问密钥库所需的密码。这仅在签署(而不是验证)JAR 文件时需要。在这种情况下,如果命令行中未提供-storepass选项,则会提示用户输入密码。如果未指定修饰符envfile,则密码的值为argument。否则,密码将按如下方式检索:

  • env:从名为argument的环境变量中检索密码。
  • file:从名为argument的文件中检索密码。

注意

除非出于测试目的或您在安全系统上,否则不应在命令行或脚本中指定密码。

-storetype storetype

指定要实例化的密钥库类型。默认密钥库类型是在安全属性文件中指定为keystore.type属性值的类型,该类型由java.security.KeyStore中的静态getDefaultType方法返回。

PKCS #11 令牌的 PIN 也可以使用-storepass选项指定。如果未指定,则keytooljarsigner命令会提示输入令牌 PIN。如果令牌具有受保护的身份验证路径(例如专用 PIN 板或生物识别读取器),则必须指定-protected选项,并且不能指定任何密码选项。

-keypass :env | :file argument -certchain file

指定用于保护命令行上指定的别名所指向的密钥库条目私钥的密码。使用jarsigner签署 JAR 文件时需要该密码。如果命令行上未提供密码,并且所需密码与存储密码不同,则会提示用户输入密码。如果未指定修饰符envfile,则密码的值为argument。否则,密码将按如下方式检索:

  • env:从名为argument的环境变量中检索密码。
  • file:从名为argument的文件中检索密码。

注意

除非出于测试目的或您在安全系统上,否则不应在命令行或脚本中指定密码。

-certchain file

指定在与命令行上指定的别名所指向的密钥库条目的私钥关联的证书链不完整时要使用的证书链。当密钥库位于没有足够容量来保存完整证书链的硬件令牌上时,可能会发生这种情况。该文件可以是一系列连接的 X.509 证书,也可以是一个单独的 PKCS#7 格式的数据块,无论是二进制编码格式还是可打印编码格式(也称为 Base64 编码),如Internet RFC 1421 证书编码标准中所定义。

-sigfile _file_

指定用于生成的.SF和签名块文件的基文件名。例如,如果文件是DUKESIGN,则生成的.SF和签名块文件分别命名为DUKESIGN.SFDUKESIGN.RSA,并放置在已签署的 JAR 文件的META-INF目录中。

文件中的字符必须来自集合a-zA-Z0-9_-。仅允许字母、数字、下划线和连字符字符。所有小写字母将转换为大写字母,用于.SF和签名块文件名。

如果命令行上没有出现-sigfile选项,则.SF和签名块文件的基文件名是命令行上指定的别名名称的前 8 个字符,全部转换为大写字母。如果别名名称少于 8 个字符,则使用完整的别名名称。如果别名名称包含任何在签名文件名中无效的字符,则将每个此类字符转换为下划线 (_) 字符以形成文件名。

-signedjar _file_

指定已签署的 JAR 文件的名称。

-digestalg _algorithm_

指定在对 JAR 文件的条目进行摘要时要使用的消息摘要算法的名称。

有关标准消息摘要算法名称的列表,请参见 Java 安全标准算法名称。

如果未指定此选项,则使用SHA256。必须有一个静态安装的提供程序提供指定算法的实现,或者用户必须使用-addprovider-providerClass选项指定一个提供程序;否则,命令将不会成功。

-sigalg _algorithm_

指定用于签署 JAR 文件的签名算法的名称。

此算法必须与用于签署 JAR 文件的私钥兼容。如果未指定此选项,则使用与私钥匹配的默认算法,如支持的算法部分所述。必须有一个静态安装的提供程序提供指定算法的实现,或者您必须使用-addprovider-providerClass选项指定一个提供程序;否则,命令将不会成功。

有关标准消息摘要算法名称的列表,请参见 Java 安全标准算法名称。

-verify

验证已签署的 JAR 文件。

-verbose:_suboptions_

当命令行上出现-verbose选项时,它表示jarsigner在使用子选项确定显示多少信息时,在签署或验证时使用详细模式。这会导致,这会导致jarsigner输出有关 JAR 签署或验证进度的额外信息。子选项可以是allgroupedsummary

如果还指定了-certs选项,则默认模式(或子选项all)会在处理每个条目时显示它,之后会显示 JAR 文件每个签署者的证书信息。

如果指定了-certs-verbose:grouped子选项,则具有相同签署者信息的条目将分组在一起,并与其证书信息一起显示。

如果指定了-certs-verbose:summary子选项,则具有相同签署者信息的条目将分组在一起,并与其证书信息一起显示。

有关每个条目的详细信息将被汇总并显示为一个条目(以及更多)。请参见验证已签署的 JAR 文件的示例带有证书信息的验证示例.

-certs

如果命令行上出现-certs选项,并且带有-verify-verbose选项,则输出将包含 JAR 文件每个签署者的证书信息。此信息包括用于认证签署者公钥的证书类型(存储在签名块文件中)的名称,以及如果证书是 X.509 证书(java.security.cert.X509Certificate的实例),则签署者的可分辨名称。

密钥库也会被检查。如果命令行上未指定密钥库值,则会检查默认密钥库文件(如果有)。如果签署者的公钥证书与密钥库中的条目匹配,则会显示该签署者密钥库条目的别名名称(在括号中)。

-revCheck

此选项在签署或验证 JAR 文件时启用证书的吊销检查。如果命令行上指定了-revCheck选项,则jarsigner命令会尝试建立网络连接以获取 OCSP 响应和 CRL。请注意,除非指定此选项,否则不会启用吊销检查。

-tsa url

如果命令行上出现-tsa http://example.tsa.url,则在签署 JAR 文件时会生成签名的的时间戳。URLhttp://example.tsa.url标识时间戳颁发机构 (TSA) 的位置,并覆盖使用-tsacert选项找到的任何 URL。-tsa选项不需要 TSA 公钥证书存在于密钥库中。

为了生成时间戳,jarsigner使用 RFC 3161 中定义的时间戳协议 (TSP) 与 TSA 通信。成功后,TSA 返回的时间戳令牌将与签名一起存储在签名块文件中。

-tsacert alias

当命令行上出现-tsacert alias时,在签署 JAR 文件时会生成签名的的时间戳。别名标识密钥库中有效的 TSA 公钥证书。检查该条目的证书以查找包含标识 TSA 位置的 URL 的主题信息访问扩展。

使用-tsacert选项时,TSA 公钥证书必须存在于密钥库中。

-tsapolicyid policyid

指定标识要发送到 TSA 服务器的策略 ID 的对象标识符 (OID)。如果未指定此选项,则不会发送任何策略 ID,TSA 服务器将选择默认策略 ID。

对象标识符由 X.696 定义,X.696 是 ITU 电信标准化部门 (ITU-T) 的标准。这些标识符通常是点分隔的非负数字集,例如1.2.3.4

-tsadigestalg algorithm

指定用于生成要发送到 TSA 服务器的消息摘要的摘要算法。如果未指定此选项,将使用 SHA-256。

请参见支持的算法.

有关标准消息摘要算法名称的列表,请参见 Java 安全标准算法名称。

-internalsf

过去,在签署 JAR 文件时生成的签名块文件包含生成的.SF文件(签名文件)的完整编码副本。此行为已更改。为了减小输出 JAR 文件的总体大小,默认情况下,签名块文件不再包含.SF文件的副本。如果命令行上出现-internalsf,则使用旧的行为。此选项对于测试很有用。在实践中,不要使用-internalsf选项,因为它会产生更高的开销。

-sectionsonly

如果命令行上出现-sectionsonly选项,则在签署 JAR 文件时生成的.SF文件(签名文件)不包含包含整个清单文件哈希值的标题。它仅包含与 JAR 文件中包含的每个单独源文件相关的信息和哈希值。请参见签名文件。默认情况下,此标题将作为优化添加。当标题存在时,无论何时验证 JAR 文件,验证都可以首先检查标题中的哈希值是否与整个清单文件的哈希值匹配。当匹配时,验证将继续进行到下一步。当不匹配时,有必要进行不太优化的验证,即.SF文件中每个源文件信息部分中的哈希值是否等于清单文件中其对应部分的哈希值。请参见JAR 文件验证.

-sectionsonly 选项主要用于测试。 除测试外,不应使用它,因为使用它会产生更高的开销。

-protected

值可以是 truefalse。 当必须通过受保护的身份验证路径(例如专用 PIN 阅读器)指定密码时,请指定 true

-providerName providerName

如果在 java.security 安全属性文件中配置了多个提供程序,则可以使用 -providerName 选项来定位特定的提供程序实例。 此选项的参数是提供程序的名称。 对于 Oracle PKCS #11 提供程序,providerName 的形式为 SunPKCS11-TokenName,其中 TokenName 是提供程序实例已配置的名称后缀,如配置属性表中所述。 例如,以下命令列出名称后缀为 SmartCardPKCS #11 密钥库提供程序实例的内容

jarsigner -keystore NONE -storetype PKCS11 -providerName SunPKCS11-SmartCard -list

-addprovider name -providerArg arg

按名称添加安全提供程序(例如 SunPKCS11)和可选的配置参数。 安全提供程序的值是在模块中定义的安全提供程序的名称。 与 -providerArg ConfigFilePath 选项一起使用时,keytooljarsigner 工具会动态安装提供程序并使用 ConfigFilePath 作为令牌配置文件的路径。 以下示例显示了在安全属性文件中未配置 Oracle PKCS #11 提供程序时列出 PKCS #11 密钥库的命令。

jarsigner -keystore NONE -storetype PKCS11 -addprovider SunPKCS11 -providerArg /mydir1/mydir2/token.config

-providerClass provider-class-name -providerArg arg

用于指定加密服务提供程序的主类文件名称,当服务提供程序未列在 java.security 安全属性文件中时。 按完全限定的类名添加安全提供程序和可选的配置参数。

注意

加载 PKCS11 的首选方法是使用模块。 请参阅 -addprovider

-J javaoption

将指定的 javaoption 字符串直接传递给 Java 解释器。 jarsigner 命令是解释器的包装器。 此选项不应包含任何空格。 它对于调整执行环境或内存使用量很有用。 有关可能的解释器选项列表,请在命令行中键入 java -hjava -X

-strict

在签名或验证过程中,命令可能会发出警告消息。 如果指定此选项,则工具的退出代码将反映此命令找到的严重警告消息。 请参阅 错误和警告

-conf url

指定预配置的选项文件。 阅读 keytool 文档 以了解详细信息。 支持的属性键是“jarsigner.all”(所有操作)、“jarsigner.sign”(签名)和“jarsigner.verify”(验证)。 jarsigner 参数(包括 JAR 文件名和别名)不能在此文件中设置。

 

已弃用的选项

从 JDK 9 开始,以下 jarsigner 选项已弃用,可能会在将来的 JDK 版本中删除。

-altsigner class

此选项指定替代签名机制。 完全限定的类名标识扩展 com.sun.jarsigner.ContentSigner 抽象类的类文件。 此类文件的路径由 -altsignerpath 选项定义。 如果使用 -altsigner 选项,则 jarsigner 命令将使用指定类提供的签名机制。 否则,jarsigner 命令将使用其默认签名机制。

例如,要使用名为 com.sun.sun.jarsigner.AuthSigner 的类提供的签名机制,请使用 jarsigner 选项 -altsigner com.sun.jarsigner.AuthSigner

-altsignerpath classpathlist

指定类文件及其依赖的任何 JAR 文件的路径。 类文件名由 -altsigner 选项指定。 如果类文件位于 JAR 文件中,则此选项指定该 JAR 文件的路径。

可以指定绝对路径或相对于当前目录的路径。 如果 classpathlist 包含多个路径或 JAR 文件,则应使用

  • 冒号 (:) 在 Linux 和 macOS 上

  • 分号 (;) 在 Windows 上

当类已在搜索路径中时,此选项不是必需的。

以下示例显示如何指定包含类文件的 JAR 文件的路径。 JAR 文件名已包含在内。

-altsignerpath /home/user/lib/authsigner.jar

以下示例显示如何指定包含类文件的 JAR 文件的路径。 JAR 文件名已省略。

-altsignerpath /home/user/classes/com/sun/tools/jarsigner/

 

错误和警告

在签名或验证过程中,jarsigner 命令可能会发出各种错误或警告。 如果出现故障,jarsigner 命令将退出并返回代码 1。 如果没有故障,但存在一个或多个严重警告,则当 -strict 选项**未**指定时,jarsigner 命令将退出并返回代码 0,或者当指定 -strict 时,将退出并返回警告代码的 OR 值。 如果只有信息性警告或根本没有警告,则命令始终退出并返回代码 0。 例如,如果用于签署条目的证书已过期并且具有不允许其签署文件的 KeyUsage 扩展,则当指定 -strict 选项时,jarsigner 命令将退出并返回代码 12 (=4+8)。

注意: 退出代码被重复使用,因为在 Linux 和 macOS 上,只有从 0 到 255 的值是合法的。 以下部分描述了 jarsigner 命令可能发出的错误和警告的名称、代码和描述。

 

故障

jarsigner 命令失败的原因包括(但不限于)命令行解析错误、无法找到用于签署 JAR 文件的密钥对或签署的 JAR 文件的验证失败。

failure

代码 1。 签名或验证失败。

 

严重警告

注意

如果指定 -strict 选项,则严重警告将被报告为错误。

jarsigner 命令发出严重警告的原因包括用于签署 JAR 文件的证书存在错误或签署的 JAR 文件存在其他问题。

hasExpiredCert 代码 4。 此 JAR 包含其签名者证书已过期的条目。

hasExpiredTsaCert 代码 4。 时间戳已过期。

notYetValidCert 代码 4。 此 JAR 包含其签名者证书尚未有效的条目。

chainNotValidated 代码 4。 此 JAR 包含其证书链未验证的条目。

tsaChainNotValidated 代码 64。 时间戳无效。

signerSelfSigned

代码 4。 此 JAR 包含其签名者证书为自签名的条目。

disabledAlg 代码 4。 使用的算法被认为是安全风险,已被禁用。

badKeyUsage 代码 8。 此 JAR 包含其签名者证书的 KeyUsage 扩展不允许代码签名的条目。

badExtendedKeyUsage 代码 8。 此 JAR 包含其签名者证书的 ExtendedKeyUsage 扩展不允许代码签名的条目。

badNetscapeCertType 代码 8。 此 JAR 包含其签名者证书的 NetscapeCertType 扩展不允许代码签名的条目。

hasUnsignedEntry 代码 16。 此 JAR 包含未签名的条目,这些条目未经过完整性检查。

notSignedByAlias 代码 32。 此 JAR 包含未由指定别名签名的已签名条目。

aliasNotInStore 代码 32。 此 JAR 包含未由此密钥库中的别名签名的已签名条目。

tsaChainNotValidated

代码 64。 此 JAR 包含其 TSA 证书链无效的条目。

 

信息性警告

信息性警告包括那些不是错误但被认为是不良做法的警告。 它们没有代码。

extraAttributesDetected 在签署或验证 JAR 文件时检测到 POSIX 文件权限和/或符号链接属性。 jarsigner 工具会将这些属性保留在新签署的文件中,但会警告说这些属性未签名且不受签名保护。

hasExpiringCert 此 JAR 包含其签名者证书将在六个月内过期的条目。

hasExpiringTsaCert 时间戳将在 YYYY-MM-DD 的一年内过期。

legacyAlg 使用的算法被认为是安全风险,但未被禁用。

noTimestamp 此 JAR 包含不包含时间戳的签名。 没有时间戳,用户可能无法在签名者证书过期日期 (YYYY-MM-DD) 或任何未来的吊销日期之后验证此 JAR 文件。

 

签署 JAR 文件的示例

使用以下命令签署 bundle.jar,使用密钥库别名为 jane 的用户的私钥,该密钥库名为 mystore,位于 working 目录中,并将签署的 JAR 文件命名为 sbundle.jar

jarsigner -keystore /working/mystore -storepass keystore\_password -keypass private\_key\_password signedjar sbundle.jar bundle.jar jane

在之前的命令中没有指定-sigfile,因此生成的.SF和签名块文件将放置在已签名的JAR文件中,并使用别名名称作为默认名称。它们分别命名为JANE.SFJANE.RSA

如果要提示输入密钥库密码和私钥密码,则可以将之前的命令缩短为以下命令

jarsigner -keystore /working/mystore -signedjar sbundle.jar bundle.jar jane

如果keystore是默认的keystore(您主目录中的.keystore),则无需指定keystore,如下所示

jarsigner -signedjar sbundle.jar bundle.jar jane

如果要让已签名的JAR文件覆盖输入JAR文件(bundle.jar),则无需指定-signedjar选项,如下所示

jarsigner bundle.jar jane

 

验证已签名JAR文件的示例

要验证已签名的JAR文件以确保签名有效且JAR文件未被篡改,请使用以下命令

jarsigner -verify ButtonDemo.jar

验证成功时,将显示jar verified。否则,将显示错误消息。使用-verbose选项可以获取更多信息。以下是使用-verbose选项的jarsigner示例

jarsigner -verify -verbose ButtonDemo.jar
    
    s       866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF
            825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF
           7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA
              0 Tue Sep 12 20:07:54 EDT 2017 META-INF/
              0 Tue Sep 12 20:07:16 EDT 2017 components/
              0 Tue Sep 12 20:07:16 EDT 2017 components/images/
    sm      523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class
    sm     3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class
    sm     2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp
    sm      172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif
    sm      235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif
    sm      172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif
    
      s = signature was verified
      m = entry is listed in manifest
      k = at least one certificate was found in keystore
    
    - Signed by "CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US"
        Digest algorithm: SHA-256
        Signature algorithm: SHA256withRSA, 2048-bit key
      Timestamped by "CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US" on Tue Sep 12 20:08:49 UTC 2017
        Timestamp digest algorithm: SHA-1
        Timestamp signature algorithm: SHA1withRSA, 2048-bit key
    
    jar verified.
    
    The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29.

 

带有证书信息的验证示例

如果使用-verify-verbose选项指定-certs选项,则输出将包含JAR文件每个签署者的证书信息。信息包括证书类型、签署者区分名称信息(当它是X.509证书时),以及在括号中,签署者的密钥库别名(当JAR文件中的公钥证书与密钥库条目中的证书匹配时),例如

    jarsigner -keystore $JAVA_HOME/lib/security/cacerts -verify -verbose -certs ButtonDemo.jar
    
    s k     866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF
    
          >>> Signer
          X.509, CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US
          [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM]
          X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US
          [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM]
          X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US (verisignclass3g5ca [jdk])
          [trusted certificate]
          >>> TSA
          X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US
          [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM]
          X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US
          [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM]
    
            825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF
           7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA
              0 Tue Sep 12 20:07:54 EDT 2017 META-INF/
              0 Tue Sep 12 20:07:16 EDT 2017 components/
              0 Tue Sep 12 20:07:16 EDT 2017 components/images/
    smk     523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class
    
          [entry was signed on 2017-09-12, 4:08 PM]
          >>> Signer
          X.509, CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US
          [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM]
          X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US
          [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM]
          X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US (verisignclass3g5ca [jdk])
          [trusted certificate]
          >>> TSA
          X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US
          [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM]
          X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US
          [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM]
    
    smk    3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class
    ...
    smk    2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp
    ...
    smk     172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif
    ...
    smk     235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif
    ...
    smk     172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif
    ...
    
      s = signature was verified
      m = entry is listed in manifest
      k = at least one certificate was found in keystore
    
    - Signed by "CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US"
        Digest algorithm: SHA-256
        Signature algorithm: SHA256withRSA, 2048-bit key
      Timestamped by "CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US" on Tue Sep 12 20:08:49 UTC 2017
        Timestamp digest algorithm: SHA-1
        Timestamp signature algorithm: SHA1withRSA, 2048-bit key
    
    jar verified.
    
    The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29.

如果签署者的证书不是X.509证书,则没有区分名称信息。在这种情况下,只显示证书类型和别名。例如,如果证书是PGP证书,别名为bob,则您将获得:PGP, (bob)


上次更新: 2021年9月14日


系列中的上一篇
当前教程
Jarsigner - 签署您的 JAR 文件

系列中的上一篇: Keytool - 管理您的密钥库

系列中的下一篇: Kinit - 获取和授予 Kerberos 票证