Keytool - 管理您的密钥库
介绍 Keytool
keytool - 管理密钥库(数据库)中的加密密钥、X.509 证书链和受信任证书
概要
keytool [commands]
命令
keytool
的命令包括以下内容
-certreq
: 生成证书请求-changealias
: 更改条目的别名-delete
: 删除条目-exportcert
: 导出证书-genkeypair
: 生成密钥对-genseckey
: 生成密钥-gencert
: 从证书请求生成证书-importcert
: 导入证书或证书链-importpass
: 导入密码-importkeystore
: 从另一个密钥库导入一个或所有条目-keypasswd
: 更改条目的密钥密码-list
: 列出密钥库中的条目-printcert
: 打印证书的内容-printcertreq
: 打印证书请求的内容-printcrl
: 打印证书吊销列表 (CRL) 文件的内容-storepasswd
: 更改密钥库的存储密码-showinfo
: 显示与安全相关的信息
有关这些命令及其选项的说明,请参阅 命令和选项。
描述
keytool
命令是一个密钥和证书管理实用程序。它使用户能够管理自己的公钥/私钥对以及相关的证书,以便在自身份验证(用户向其他用户和服务进行身份验证)或数据完整性和身份验证服务中使用,方法是使用数字签名。keytool
命令还使用户能够缓存其通信对等方的公钥(以证书的形式)。
证书是来自一个实体(个人、公司等)的数字签名声明,它表明另一个实体的公钥(以及其他一些信息)具有特定的值。当数据被数字签名时,可以验证签名以检查数据完整性和真实性。完整性意味着数据没有被修改或篡改,真实性意味着数据来自声称创建并签署数据的人员。
keytool
命令还使用户能够管理对称加密和解密(数据加密标准)中使用的密钥和密码。它还可以显示其他与安全相关的信息。
keytool
命令将密钥和证书存储在密钥库中。
keytool
命令使用 jdk.certpath.disabledAlgorithms
和 jdk.security.legacyAlgorithms
安全属性来确定哪些算法被认为是安全风险。当使用禁用或旧版算法时,它会发出警告。jdk.certpath.disabledAlgorithms
和 jdk.security.legacyAlgorithms
安全属性在 java.security
文件(位于 JDK 的 $JAVA_HOME/conf/security
目录中)中定义。
命令和选项说明
以下说明适用于 命令和选项 中的描述
所有命令和选项名称前面都有一个连字符 (
-
)。只能提供一个命令。
每个命令的选项可以按任何顺序提供。
选项有两种类型,一种是单值选项,应该只提供一次。如果多次提供单值选项,则使用最后一个选项的值。另一种类型是多值选项,可以多次提供,并且所有值都会被使用。目前支持的唯一多值选项是
-ext
选项,用于生成 X.509v3 证书扩展。所有未用斜体或括号 ({ }) 或方括号 ( ) 括起来的项目都必须按原样出现。
围绕选项的大括号表示当命令行上未指定选项时使用默认值。大括号也用于
-v
、-rfc
和-J
选项周围,这些选项只有在命令行上出现时才有意义。它们没有任何默认值。围绕选项的方括号表示当命令行上未指定选项时,系统会提示用户输入值。对于
-keypass
选项,如果您没有在命令行上指定该选项,那么keytool
命令首先尝试使用密钥库密码来恢复私钥/密钥。如果此尝试失败,那么keytool
命令会提示您输入私钥/密钥密码。斜体中的项目(选项值)表示必须提供的实际值。例如,以下是
-printcert
命令的格式
keytool -printcert {-file cert_file} {-v}
当您指定 -printcert
命令时,请用实际文件名替换 cert_file,如下所示:keytool -printcert -file VScert.cer
- 当选项值包含空格时,必须用引号将其括起来。
命令和选项
keytool
命令及其选项可以按其执行的任务进行分组。
-gencert
-genkeypair
-genseckey
-importcert
-importpass
-
-importkeystore
-
-certreq
-
-exportcert
-list
-printcert
-printcertreq
-printcrl
-storepasswd
-keypasswd
-delete
-changealias
-
-showinfo
用于创建或向密钥库添加数据的命令
-gencert
以下是 -gencert
命令的可用选项
{
-rfc
}: 以 RFC(请求意见书)样式输出{
-infile
infile}: 输入文件名{
-outfile
outfile}: 输出文件名{
-alias
alias}: 要处理的条目的别名{
-sigalg
sigalg}: 签名算法名称{
-dname
dname}: 识别名称{
-startdate
startdate}: 证书有效期开始日期和时间{
-ext
ext}*: X.509 扩展{
-validity
days}: 有效期天数-keypass
arg: 密钥密码{
-keystore
keystore}: 密钥库名称-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供程序(例如 SunPKCS11),并带有一个可选的配置参数。安全提供程序的值是在模块中定义的安全提供程序的名称。例如,
keytool -addprovider SunPKCS11 -providerarg some.cfg ...
注意
出于兼容性原因,即使 SunPKCS11 提供程序现在在模块中定义,也可以使用
-providerclass sun.security.pkcs11.SunPKCS11
加载它。这是 JDK 中唯一需要配置的模块,因此也是使用-providerclass
选项最广泛的模块。对于位于类路径上并通过反射加载的旧版安全提供程序,仍然应该使用-providerclass
。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。例如,如果
MyProvider
是通过反射加载的旧版提供程序,则keytool -providerclass com.example.MyProvider ...
{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -gencert
命令生成证书作为对证书请求文件(可以通过 keytool -certreq
命令创建)的响应。该命令从 infile 读取请求,或者如果省略,则从标准输入读取请求,使用别名的私钥对其进行签名,并将 X.509 证书输出到 outfile,或者如果省略,则输出到标准输出。当指定 -rfc
时,输出格式为 Base64 编码的 PEM;否则,将创建二进制 DER。
-sigalg
值指定用于签署证书的算法。startdate 参数是证书有效的开始时间和日期。days 参数告诉证书应被视为有效的日期数。
当提供 dname 时,它用作生成的证书的主题。否则,将使用证书请求中的主题。
-ext
值显示将嵌入到证书中的 X.509 扩展。有关 -ext
的语法,请阅读 常用命令选项。
-gencert
选项使您能够创建证书链。以下示例创建一个名为 e1
的证书,该证书在其证书链中包含三个证书。
以下命令创建四个名为 ca
、ca1
、ca2
和 e1
的密钥对
keytool -alias ca -dname CN=CA -genkeypair -keyalg rsa
keytool -alias ca1 -dname CN=CA -genkeypair -keyalg rsa
keytool -alias ca2 -dname CN=CA -genkeypair -keyalg rsa
keytool -alias e1 -dname CN=E1 -genkeypair -keyalg rsa
以下两个命令创建签署证书的链;ca
签署 ca1
,ca1
签署 ca2
,它们都是自签署的
keytool -alias ca1 -certreq |
keytool -alias ca -gencert -ext san=dns:ca1 |
keytool -alias ca1 -importcert
keytool -alias ca2 -certreq |
keytool -alias ca1 -gencert -ext san=dns:ca2 |
keytool -alias ca2 -importcert
以下命令创建证书 e1
并将其存储在 e1.cert
文件中,该文件由 ca2
签署。因此,e1
应该在其证书链中包含 ca
、ca1
和 ca2
keytool -alias e1 -certreq | keytool -alias ca2 -gencert > e1.cert
-genkeypair
以下是 -genkeypair
命令的可用选项
{
-alias
alias}: 要处理的条目的别名-keyalg
alg: 密钥算法名称{
-keysize
size}: 密钥位大小{
-groupname
name}: 组名。例如,椭圆曲线名称。{
-sigalg
alg}: 签名算法名称-dname
name: 识别名称{
-startdate
date}: 证书有效期开始日期和时间{
-ext
value}*: X.509 扩展{
-validity
days}: 有效期天数-keypass
arg: 密钥密码{
-keystore
keystore}: 密钥库名称-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg }: 通过完全限定的类名添加安全提供者,并带有可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -genkeypair
命令生成密钥对(公钥和关联的私钥)。将公钥封装在 X.509 v3 自签名证书中,该证书存储为单元素证书链。此证书链和私钥存储在新的密钥库条目中,该条目由其别名标识。
-keyalg
值指定用于生成密钥对的算法,-keysize
值指定要生成的每个密钥的大小。-sigalg
值指定用于签署自签名证书的算法。此算法必须与 -keyalg
值兼容。
-groupname
值指定要生成的密钥的命名组(例如,椭圆曲线的标准或预定义名称)。只能指定 -groupname
或 -keysize
中的一个。
-dname
值指定与 -alias
值关联的 X.500 识别名称,并用作自签名证书中的颁发者和主题字段。如果命令行中未提供识别名称,则会提示用户输入。
-keypass
的值是用于保护生成的密钥对的私钥的密码。如果未提供密码,则会提示用户输入。如果在提示符处按 Return 键,则密钥密码将设置为与密钥库密码相同的密码。-keypass
值必须至少包含六个字符。
-startdate
的值指定证书的颁发时间,也称为 X.509 证书有效期字段的“Not Before”值。
选项值可以以以下两种形式之一设置
(+-
nnnymdHMS
)+
yyyy/
mm/
dd HH:
MM:
SS
使用第一种形式,颁发时间将从当前时间偏移指定的值。该值是子值序列的串联。在每个子值内部,加号 (+) 表示向前偏移,减号 (-) 表示向后偏移。要偏移的时间是年、月、日、小时、分钟或秒的 nnn 个单位(分别由 y
、m
、d
、H
、M
或 S
的单个字符表示)。颁发时间的精确值是通过从左到右对每个子值使用 java.util.GregorianCalendar.add(int field, int amount)
方法计算的。例如,颁发时间可以通过以下方式指定
Calendar c = new GregorianCalendar();
c.add(Calendar.YEAR, -1);
c.add(Calendar.MONTH, 1);
c.add(Calendar.DATE, -1);
return c.getTime()
使用第二种形式,用户将颁发时间的精确值设置为两部分,年/月/日和小时:分钟:秒(使用本地时区)。用户可以只提供一部分,这意味着另一部分与当前日期(或时间)相同。用户必须提供格式定义中显示的精确位数(对于较短的位数,用 0 填充)。当提供日期和时间时,两部分之间有一个(且只有一个)空格字符。小时应始终以 24 小时制提供。
当未提供选项时,开始日期为当前时间。选项只能提供一次。
date 的值指定证书应被视为有效的日期数(从 -startdate
指定的日期开始,或者当未指定 -startdate
时为当前日期)。
-genseckey
以下是 -genseckey
命令的可用选项
{
-alias
alias}: 要处理的条目的别名-keypass
arg: 密钥密码-keyalg
alg: 密钥算法名称{
-keysize
size}: 密钥位大小{
-keystore
keystore}: 密钥库名称-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -genseckey
命令生成密钥,并将其存储在由 alias
标识的新的 KeyStore.SecretKeyEntry
中。
-keyalg
的值指定用于生成密钥的算法,-keysize
的值指定生成的密钥的大小。-keypass
的值是用于保护密钥的密码。如果未提供密码,则会提示用户输入。如果在提示符处按 Return 键,则密钥密码将设置为与 -keystore
相同的密码。-keypass
值必须包含至少六个字符。
-importcert
以下是 -importcert
命令的可用选项
{
-noprompt
}: 不提示{
-trustcacerts
}: 信任来自 cacerts 的证书{
-protected
}: 密码通过受保护的机制提供{
-alias
alias}: 要处理的条目的别名{
-file
file}: 输入文件名-keypass
arg: 密钥密码{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出
使用 -importcert
命令从 -file
file 读取证书或证书链(后者以 PKCS#7 格式的回复或 X.509 证书序列提供),并将其存储在由 -alias
标识的 keystore
条目中。如果未指定 -file
file,则证书或证书链将从 stdin
读取。
keytool
命令可以导入 X.509 v1、v2 和 v3 证书,以及由该类型证书组成的 PKCS#7 格式的证书链。要导入的数据必须以二进制编码格式或可打印编码格式(也称为 Base64 编码)提供,如 Internet RFC 1421 标准中定义的那样。在后一种情况下,编码必须以以 -----BEGIN
开头的字符串为界,并以以 -----END
开头的字符串为界。
您导入证书有两个原因:将其添加到受信任证书列表中,以及将从证书颁发机构 (CA) 收到的证书回复导入,作为向该 CA 提交证书签名请求 (CSR) 的结果。请参阅 生成证书请求的命令 中的 -certreq
命令。
导入类型由 -alias
选项的值指示。如果别名不指向密钥条目,则 keytool
命令假定您正在添加受信任证书条目。在这种情况下,别名不应已存在于密钥库中。如果别名确实存在,则 keytool
命令输出错误,因为该别名已存在受信任证书,并且不会导入证书。如果 -alias
指向密钥条目,则 keytool
命令假定您正在导入证书回复。
-importpass
以下是 -importpass
命令的可用选项
{
-alias
alias}: 要处理的条目的别名-keypass
arg: 密钥密码{
-keyalg
alg}: 密钥算法名称{
-keysize
size}: 密钥位大小{
-keystore
keystore}: 密钥库名称-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -importpass
命令导入密码并将其存储在由 -alias
标识的新的 KeyStore.SecretKeyEntry
中。密码可以通过标准输入流提供;否则会提示用户输入。-keypass
选项提供密码来保护导入的密码。如果未提供密码,则会提示用户输入。如果在提示符处按 Return 键,则密钥密码将设置为与 keystore
相同的密码。-keypass
值必须包含至少六个字符。
用于从另一个密钥库导入内容的命令
-importkeystore
以下是 -importkeystore
命令的可用选项
-srckeystore
keystore: 源密钥库名称{
-destkeystore
keystore}: 目标密钥库名称{
-srcstoretype
type}: 源密钥库类型{
-deststoretype
type}: 目标密钥库类型-srcstorepass
arg: 源密钥库密码-deststorepass
arg: 目标密钥库密码{
-srcprotected
}: 源密钥库密码受保护{
-destprotected
}: 目标密钥库密码受保护{
-srcprovidername
name}: 源密钥库提供者名称{
-destprovidername
name}: 目标密钥库提供者名称{
-srcalias
alias}: 源别名{
-destalias
alias}: 目标别名-srckeypass
arg: 源密钥密码-destkeypass
arg: 目标密钥密码{
-noprompt
}: 不提示{
-addprovider
name-providerarg
arg: 通过名称添加安全提供程序(例如 SunPKCS11),并提供可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并提供可选的配置参数{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出
注意
这是所有选项的第一行
-srckeystore _keystore_ -destkeystore _keystore_
使用 -importkeystore
命令将单个条目或所有条目从源密钥库导入到目标密钥库。
注意
如果在使用 keytool -importkeystore
命令时未指定 -destkeystore
,则使用 $HOME/.keystore
作为默认密钥库。
当提供 -srcalias
选项时,该命令会将别名标识的单个条目导入到目标密钥库。如果未使用 -destalias
提供目标别名,则 -srcalias
将用作目标别名。如果源条目受密码保护,则 -srckeypass
用于恢复条目。如果未提供 -srckeypass
,则 keytool
命令尝试使用 -srcstorepass
恢复条目。如果未提供 -srcstorepass
或不正确,则会提示用户输入密码。目标条目受 -destkeypass
保护。如果未提供 -destkeypass
,则目标条目受源条目密码保护。例如,大多数第三方工具要求 PKCS #12 密钥库中的 storepass
和 keypass
相同。要为这些工具创建 PKCS#12 密钥库,请始终指定与 -deststorepass
相同的 -destkeypass
。
如果未提供 -srcalias
选项,则源密钥库中的所有条目都将导入到目标密钥库。每个目标条目都以源条目中的别名存储。如果源条目受密码保护,则 -srcstorepass
用于恢复条目。如果未提供 -srcstorepass
或不正确,则会提示用户输入密码。如果源密钥库条目类型在目标密钥库中不受支持,或者在将条目存储到目标密钥库时发生错误,则会提示用户跳过条目并继续,或者退出。目标条目受源条目密码保护。
如果目标别名已存在于目标密钥库中,则会提示用户覆盖条目或在不同的别名下创建新条目。
如果提供了 -noprompt
选项,则不会提示用户输入新的目标别名。现有条目将使用目标别名覆盖。无法导入的条目将被跳过,并显示警告。
用于生成证书请求的命令
-certreq
以下是 -certreq
命令的可用选项
{
-alias
alias}: 要处理的条目的别名{
-sigalg
alg}: 签名算法名称{
-file
file}: 输出文件名-keypass
arg: 密钥密码{
-keystore
keystore}: 密钥库名称{
-dname
name}: 识别名称{
-ext
value}: X.509 扩展-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -certreq
命令使用 PKCS #10 格式生成证书签名请求 (CSR)。
CSR 旨在发送给 CA。CA 会对证书请求者进行身份验证(通常是离线),并返回证书或证书链以替换密钥库中现有的证书链(最初是自签名证书)。
与 alias 关联的私钥用于创建 PKCS #10 证书请求。要访问私钥,必须提供正确的密码。如果在命令行中未提供 -keypass
并且与用于保护密钥库完整性的密码不同,则会提示用户输入密码。如果提供了 -dname
,则它将用作 CSR 中的主题。否则,将使用与别名关联的 X.500 识别名称。
-sigalg
值指定用于签署 CSR 的算法。
CSR 存储在 -file
file 中。如果未指定文件,则 CSR 将输出到 -stdout
。
使用 -importcert
命令导入来自 CA 的响应。
用于导出数据的命令
-exportcert
以下是 -exportcert
命令的可用选项
{
-rfc
}: 以 RFC 样式输出{
-alias
alias}: 要处理的条目的别名{
-file
file}: 输出文件名{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg }: 通过完全限定的类名添加安全提供者,并带有可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -exportcert
命令从与 -alias
alias 关联的密钥库中读取证书,并将其存储在 -file
file 中。当未指定文件时,证书将输出到 stdout
。
默认情况下,证书以二进制编码输出。如果指定了 -rfc
选项,则输出将以 Internet RFC 1421 证书编码标准定义的可打印编码格式输出。
如果 -alias
指的是受信任的证书,则输出该证书。否则,-alias
指的是具有关联证书链的密钥条目。在这种情况下,将返回链中的第一个证书。此证书对 -alias
所指实体的公钥进行身份验证。
用于显示数据的命令
-list
以下是 -list
命令的可用选项
{
-rfc
}: 以 RFC 样式输出{
-alias
alias}: 要处理的条目的别名{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg }: 通过完全限定的类名添加安全提供者,并带有可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -list
命令将 -alias
标识的密钥库条目的内容打印到 stdout
。如果未指定 -alias
alias,则打印整个密钥库的内容。
默认情况下,此命令打印证书的 SHA-256 指纹。如果指定了 -v
选项,则证书将以人类可读的格式打印,其中包含其他信息,例如所有者、发行者、序列号和任何扩展。如果指定了 -rfc
选项,则证书内容将使用可打印编码格式打印,如 Internet RFC 1421 证书编码标准所定义。
注意
您不能在同一个命令中同时指定 -v
和 -rfc
。否则,将报告错误。
-printcert
以下是 -printcert
命令的可用选项
{
-rfc
}: 以 RFC 样式输出{
-file
cert_file}: 输入文件名{
-sslserver
server:
port}:: 安全套接字层 (SSL) 服务器主机和端口{
-jarfile
JAR_file}: 已签名的.jar
文件{
-keystore
keystore}: 密钥库名称{
-trustcacerts
}: 信任来自 cacerts 的证书-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-protected
}: 密码通过受保护的机制提供{
-v
}: 详细输出
使用 -printcert
命令从 -file
cert_file、位于 -sslserver
server:
port 的 SSL 服务器或 -jarfile
JAR_file 指定的已签名 JAR 文件中读取并打印证书。它以人类可读的格式打印其内容。当未指定端口时,将假定标准 HTTPS 端口 443。
注意
-sslserver
和 -file
选项不能在同一个命令中提供。否则,将报告错误。如果未指定任何选项,则证书将从 stdin
读取。
当指定 -rfc
时,keytool
命令以 Internet RFC 1421 证书编码标准定义的 PEM 模式打印证书。
如果证书是从文件或 stdin
读取的,则它可能是二进制编码的,也可能是可打印编码格式的,如 RFC 1421 证书编码标准所定义。
如果 SSL 服务器位于防火墙后面,则可以在命令行中指定 -J-Dhttps.proxyHost=proxyhost
和 -J-Dhttps.proxyPort=proxyport
选项以进行代理隧道。
注意
此命令可以独立于密钥库使用。如果证书是用户密钥库(由 -keystore
指定)或 cacerts
密钥库(如果指定了 -trustcacerts
)中的受信任证书,则此命令不会检查证书签名算法的弱点。
-printcertreq
以下是 -printcertreq
命令的可用选项
{
-file
file}: 输入文件名{
-v
}: 详细输出
使用 -printcertreq
命令打印 PKCS #10 格式证书请求的内容,该请求可以通过 keytool -certreq
命令生成。该命令从文件读取请求。如果没有文件,则从标准输入读取请求。
-printcrl
以下是 -printcrl
命令的可用选项
{
-file crl
}: 输入文件名{
-keystore
keystore}: 密钥库名称{
-trustcacerts
}: 信任来自 cacerts 的证书-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-protected
}: 密码通过受保护的机制提供{
-v
}: 详细输出
使用 -printcrl
命令从 -file crl
读取证书吊销列表 (CRL)。CRL 是由颁发它们的 CA 吊销的数字证书列表。CA 会生成 crl
文件。
注意
此命令可以独立于密钥库使用。此命令尝试使用用户密钥库(由 -keystore
指定)或 cacerts
密钥库(如果指定了 -trustcacerts
)中的证书验证 CRL,如果无法验证,将打印警告。
用于管理密钥库的命令
-storepasswd
以下是 -storepasswd
命令的可用选项
-new
arg: 新密码{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出
使用 -storepasswd
命令更改用于保护密钥库内容完整性的密码。新密码由 -new
arg 设置,必须包含至少六个字符。
-keypasswd
以下是 -keypasswd
命令的可用选项
{
-alias
alias}: 要处理的条目的别名-keypass
old_keypass: 密钥密码-new
new_keypass: 新密码{
-keystore
keystore}: 密钥库名称{
-storepass
arg}: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出
使用 -keypasswd
命令将 -alias
标识的私钥/密钥的密码从 -keypass
old_keypass 更改为 -new
new_keypass。密码值必须包含至少六个字符。
如果在命令行中未提供 -keypass
选项,并且 -keypass
密码与密钥库密码(-storepass
arg)不同,则会提示用户输入密码。
如果在命令行中未提供 -new
选项,则会提示用户输入密码。
-delete
以下是 -delete
命令的可用选项
-alias
alias: 要处理的条目的别名{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用 -delete
命令从密钥库中删除 -alias
alias 条目。当在命令行中未提供时,会提示用户输入 alias
。
-changealias
以下是 -changealias
命令的可用选项
{
-alias
alias}: 要处理的条目的别名-destalias
alias: 目标别名-keypass
arg: 密钥密码{
-keystore
keystore}: 密钥库名称{
-cacerts
}: 访问 cacerts 密钥库-storepass
arg: 密钥库密码{
-storetype
type}: 密钥库类型{
-providername
name}: 提供程序名称{
-addprovider
name-providerarg
arg}: 通过名称添加安全提供者(例如 SunPKCS11),并带有可选的配置参数。{
-providerclass
class-providerarg
arg}: 通过完全限定的类名添加安全提供程序,并带有一个可选的配置参数。{
-providerpath
list}: 提供程序类路径{
-v
}: 详细输出{
-protected
}: 通过受保护机制提供的密码
使用-changealias
命令将现有密钥库条目从-alias
别名移动到新的-destalias
别名。如果没有提供目标别名,则命令会提示您输入一个。如果原始条目受条目密码保护,则可以使用-keypass
选项提供密码。如果没有提供密钥密码,则首先尝试使用-storepass
(如果提供)。如果尝试失败,则会提示用户输入密码。
用于显示与安全相关信息的命令
-showinfo
以下是-showinfo
命令的可用选项
{
-tls
}: 显示 TLS 配置信息{
-v
}: 详细输出
使用-showinfo
命令显示各种与安全相关的的信息。-tls
选项显示 TLS 配置,例如已启用协议和密码套件的列表。
显示帮助信息的命令
您可以使用--help
显示keytool
命令列表或显示有关特定keytool
命令的帮助信息。
要显示
keytool
命令列表,请输入keytool --help
要显示有关特定
keytool
命令的帮助信息,请输入keytool -<command> --help
常用命令选项
-v
选项可以出现在除--help
之外的所有命令中。当出现-v
选项时,它表示详细模式,这意味着输出中提供了更多信息。
-J
选项参数可以出现在任何命令中。当使用-J
选项时,指定的选项字符串将直接传递给Java解释器。此选项不包含任何空格。它对于调整执行环境或内存使用量很有用。有关可能的解释器选项列表,请在命令行中输入java -h
或java -X
。
这些选项可以出现在对密钥库进行操作的所有命令中
-storetype
密钥库类型
此限定符指定要实例化的密钥库类型。
-keystore
密钥库
密钥库位置。
如果使用JKS 密钥库类型
并且密钥库文件尚不存在,则某些keytool
命令会导致创建新的密钥库文件。例如,如果调用keytool -genkeypair
并且未指定-keystore
选项,则默认密钥库文件名为.keystore
,如果它不存在,则在用户的 home 目录中创建。类似地,如果指定了-keystore ks_file
选项,但ks_file
不存在,则会创建它。有关JKS 密钥库类型
的更多信息,请参阅密钥库别名中的密钥库实现部分。
请注意,来自-keystore
选项的输入流将传递给KeyStore.load
方法。如果将NONE
指定为 URL,则将空流传递给KeyStore.load
方法。如果密钥库不是基于文件的,则应指定NONE
。例如,当密钥库驻留在硬件令牌设备上时。
-cacerts
cacerts
对cacerts密钥库进行操作。此选项等效于-keystore
cacerts路径 -storetype
cacerts类型。如果-keystore
或-storetype
选项与-cacerts
选项一起使用,则会报告错误。
-storepass
:env
| :file
参数
用于保护密钥库完整性的密码。
如果未指定修饰符env
或file
,则密码的值为参数,该参数必须包含至少六个字符。否则,密码将按如下方式检索
env
: 从名为参数的环境变量中检索密码。file
: 从名为参数的文件中检索密码。
注意:所有其他需要密码的选项,例如-keypass
、-srckeypass
、-destkeypass
、-srcstorepass
和-deststorepass
,都接受env
和file
修饰符。请记住用冒号(:)分隔密码选项和修饰符。
必须向访问密钥库内容的所有命令提供密码。对于此类命令,当命令行中未提供-storepass
选项时,会提示用户输入密码。
从密钥库中检索信息时,密码是可选的。如果未指定密码,则无法验证检索到的信息的完整性,并且会显示警告。
-providername
名称
用于在安全属性文件中列出时标识加密服务提供程序的名称。
-addprovider
名称
用于按名称添加安全提供程序(例如 SunPKCS11)。
-providerclass
类
用于指定加密服务提供程序的主类文件名称,当服务提供程序未在安全属性文件中列出时。
-providerpath
列表
用于指定提供程序类路径。
-providerarg
参数
与-addprovider
或-providerclass
选项一起使用,以表示类名称构造函数的可选字符串输入参数。
-protected=true
|false
当必须通过受保护的身份验证路径(例如专用 PIN 阅读器)指定密码时,将此值指定为true
。由于-importkeystore
命令涉及两个密钥库,因此为源密钥库和目标密钥库分别提供了以下两个选项:-srcprotected
和-destprotected
。
-ext
{名称{:critical
} {=
值}}
表示 X.509 证书扩展。该选项可以在-genkeypair
和-gencert
中使用,将扩展嵌入到生成的证书中,或者在-certreq
中使用,以显示证书请求中请求了哪些扩展。该选项可以出现多次。名称参数可以是支持的扩展名称(请参阅支持的命名扩展)或任意 OID 编号。值参数(如果提供)表示扩展的参数。当省略值时,扩展的默认值或扩展本身不需要参数。:critical
修饰符(如果提供)表示扩展的isCritical
属性为true
;否则为false
。您可以使用:c
代替:critical
。
-conf
文件
指定预配置选项文件。
预配置选项文件
预配置选项文件是 Java 属性文件,可以使用-conf
选项指定。每个属性代表使用“keytool.命令名称”作为属性名称的 keytool 命令的默认选项。名为“keytool.all”的特殊属性代表应用于所有命令的默认选项。属性值可以包含${prop}
,它将扩展到与其关联的系统属性。如果选项值包含内部空格,则应将其用引号(“或')括起来。所有属性名称必须为小写。
当keytool
使用预配置选项文件启动时,首先将“keytool.all”的值(如果存在)追加到keytool
命令行,然后是命令名称的值(如果存在),最后是命令行上现有的选项。对于单值选项,这允许特定命令的属性覆盖“keytool.all”的值,并且命令行上指定的值覆盖两者。对于多值选项,keytool
将使用所有选项。
例如,给定以下名为preconfig
的文件
# A tiny pre-configured options file
keytool.all = -keystore ${user.home}/ks
keytool.list = -v
keytool.genkeypair = -keyalg rsa
keytool -conf preconfig -list
与以下命令相同
keytool -keystore ~/ks -v -list
keytool -conf preconfig -genkeypair -alias me
与以下命令相同
keytool -keystore ~/ks -keyalg rsa -genkeypair -alias me
keytool -conf preconfig -genkeypair -alias you -keyalg ec
与以下命令相同
keytool -keystore ~/ks -keyalg rsa -genkeypair -alias you -keyalg ec
等效于以下命令
keytool -keystore ~/ks -genkeypair -alias you -keyalg ec
因为-keyalg
是单值选项,并且命令行上指定的ec
值覆盖了预配置选项文件。
选项值的示例
以下示例显示了各种选项值的默认值
-alias "mykey"
-keysize
2048
(当使用-genkeypair
并且-keyalg
为RSA
、DSA
或RSASSA-PSS
时) 256
(当使用-genkeypair
并且 -keyalg 为EC
时) 255
(当使用-genkeypair
并且 -keyalg 为EdDSA
时) 56
(当使用-genseckey
并且 -keyalg 为DES
时) 168
(当使用-genseckey
并且 -keyalg 为DESede
时)
-validity 90
-keystore
<用户 home 目录中名为 .keystore 的文件>
-destkeystore
<用户 home 目录中名为 .keystore 的文件>
-storetype
<安全属性文件中“keystore.type”属性的值,由 java.security.KeyStore 中的静态 getDefaultType 方法返回>
-file
stdin
(如果读取) stdout
(如果写入)
-protected false
在生成证书或证书请求时,默认签名算法(-sigalg
选项)将从底层私钥的算法派生,以提供适当的安全强度级别,如下所示
RSASSA-PSS 签名算法使用
MessageDigest
算法作为其哈希和 MGF1 算法。EdDSA 支持 2 个密钥大小:Ed25519 和 Ed448。当使用
-keyalg EdDSA
生成 EdDSA 密钥对时,用户可以指定-keysize 255
或-keysize 448
来生成 Ed25519 或 Ed448 密钥对。当未指定-keysize
时,将生成 Ed25519 密钥对。用户还可以直接指定-keyalg Ed25519
或-keyalg Ed448
来生成具有预期密钥大小的密钥对。
注意
为了提高开箱即用的安全性,默认密钥大小和签名算法名称会随着每个 JDK 版本的发布而定期更新为更强的值。如果与旧版 JDK 的互操作性很重要,请确保这些版本支持默认值。或者,您可以使用 -keysize
或 -sigalg
选项来覆盖默认值,但风险自负。
支持的命名扩展
keytool
命令支持以下命名扩展。名称不区分大小写。
BC
或 BasicContraints
值
完整形式为 ca:
{true
|false
},pathlen:
len 或 len,它是 ca:true,pathlen:
len 的简写。
当省略 len 时,结果值为 ca:true
。
KU
或 KeyUsage
值
usage(,
usage)*
usage 可以是以下之一
digitalSignature
nonRepudiation
(contentCommitment
)keyEncipherment
dataEncipherment
keyAgreement
keyCertSign
cRLSign
encipherOnly
decipherOnly
只要没有歧义,usage 参数可以用前几个字母缩写(例如,dig
代表 digitalSignature
)或使用驼峰式风格(例如,dS
代表 digitalSignature
或 cRLS
代表 cRLSign
)。usage 值区分大小写。
EKU
或 ExtendedKeyUsage
值
usage(,
usage)*
usage 可以是以下之一
anyExtendedKeyUsage
serverAuth
clientAuth
codeSigning
emailProtection
timeStamping
OCSPSigning
任何 OID 字符串
只要没有歧义,usage 参数可以用前几个字母缩写或使用驼峰式风格。usage 值区分大小写。
SAN
或 SubjectAlternativeName
值
type:
value(,
type:
value)*
type 可以是以下之一
EMAIL
URI
DNS
IP
OID
value 参数是 type 的字符串格式值。
IAN
或 IssuerAlternativeName
值
与 SAN
或 SubjectAlternativeName
相同。
SIA
或 SubjectInfoAccess
值
method:
location-type:
location-value(,
method:
location-type:
location-value)*
method 可以是以下之一
timeStamping
caRepository
任何 OID
location-type 和 location-value 参数可以是 SubjectAlternativeName
扩展支持的任何 type:
value。
AIA
或 AuthorityInfoAccess
值
与 SIA
或 SubjectInfoAccess
相同。
method 参数可以是以下之一
ocsp
caIssuers
任何 OID
当 name 为 OID 时,该值是扩展的 extnValue
的十六进制转储确定性编码规则 (DER) 编码,不包括 OCTET STRING 类型和长度字节。除了标准十六进制数字 (0-9, a-f, A-F) 之外,HEX 字符串中的任何其他字符都会被忽略。因此,01:02:03:04 和 01020304 被视为相同的值。当没有值时,扩展具有空值字段。
一个特殊的名称 honored
,仅在 -gencert
中使用,表示如何处理证书请求中包含的扩展。此名称的值是一个逗号分隔的列表,包括 all
(处理所有请求的扩展)、name{:``critical
|non-critical
}(处理命名的扩展,但使用不同的 isCritical
属性)和 -name
(与 all
一起使用,表示异常)。默认情况下不处理请求的扩展。
如果除了 -ext honored
选项之外,还提供了另一个命名或 OID -ext
选项,则此扩展将添加到已处理的扩展中。但是,如果此名称(或 OID)也出现在处理的值中,则其值和关键性将覆盖请求中的值。如果通过名称或 OID 多次提供相同类型的扩展,则仅使用最后一个扩展。
subjectKeyIdentifier
扩展始终创建。对于非自签名证书,将创建 authorityKeyIdentifier
。
注意
用户应该知道,某些扩展组合(和其他证书字段)可能不符合互联网标准。请参阅 证书符合性警告。
创建密钥库的任务示例
以下示例描述了创建密钥库以管理来自受信任实体的公钥/私钥对和证书的顺序操作。
生成密钥对
创建密钥库,然后生成密钥对。
您可以将命令输入为单行,例如以下内容
keytool -genkeypair -dname "cn=myname, ou=mygroup, o=mycompany, c=mycountry" -alias business -keyalg rsa -keypass `_password_` -keystore /working/mykeystore -storepass password -validity 180
该命令在工作目录中创建名为 mykeystore
的密钥库(前提是它不存在),并为其分配由 -keypass
指定的密码。它为其区分名称为 myname
、mygroup
、mycompany
以及两位国家代码为 mycountry
的实体生成公钥/私钥对。它使用 RSA 密钥生成算法来创建密钥;两者都是 2048 位。
该命令使用默认的 SHA256withRSA 签名算法来创建一个自签名证书,其中包含公钥和区分名称信息。该证书有效期为 180 天,并与密钥库条目中的私钥相关联,该条目由 -alias business
引用。私钥被分配由 -keypass
指定的密码。
当接受选项默认值时,该命令会大大缩短。在这种情况下,只需要 -keyalg
,并且默认值将用于具有默认值的未指定选项。系统会提示您输入任何必需的值。您可能会有以下内容
keytool -genkeypair -keyalg rsa
在这种情况下,将创建一个别名为 mykey
的密钥库条目,其中包含一个新生成的密钥对和一个有效期为 90 天的证书。此条目将放置在您主目录中的名为 .keystore
的密钥库中。.keystore
将在不存在的情况下创建。系统会提示您输入区分名称信息、密钥库密码和私钥密码。
注意
其余示例假设您对提示的回复与第一个 -genkeypair
命令中指定的值相同。例如,区分名称为 cn=
myname, ou=
mygroup, o=
mycompany, c=
mycountry)。
向 CA 请求签名证书
注意
生成密钥对创建了一个自签名证书;但是,当证书由 CA 签名时,它更有可能被其他人信任。
要获得 CA 签名,请完成以下过程
生成 CSR
keytool -certreq -file myname.csr
这将为由默认别名
mykey
标识的实体创建一个 CSR,并将请求放入名为myname.csr
的文件中。将
myname.csr
提交给 CA,例如 DigiCert。
CA 会验证您(通常是离线)作为请求者的身份,并返回一个由他们签名的证书,以验证您的公钥。在某些情况下,CA 会返回一个证书链,每个证书都会验证链中前一个证书的签署者的公钥。
导入 CA 的证书
要导入 CA 的证书,请完成以下过程
在您导入 CA 的证书回复之前,您需要在密钥库或
cacerts
密钥库文件中拥有一个或多个受信任的证书。请参阅 **命令** 中的-importcert
。如果证书回复是证书链,那么您需要链的顶层证书。验证 CA 公钥的根 CA 证书。
如果证书回复是单个证书,那么您需要颁发 CA 的证书(签署它的证书)。如果该证书不是自签名的,那么您需要其签署者的证书,依此类推,直到自签名的根 CA 证书。
The `cacerts` keystore ships with a set of root certificates issued by the CAs of [the Oracle Java Root Certificate program](http://www.oracle.com/technetwork/java/javase/javasecarootcertsprogram-1876540.html). If you request a signed certificate from a CA, and a certificate authenticating that CA's public key hasn't been added to `cacerts`, then you must import a certificate from that CA as a trusted certificate.
A certificate from a CA is usually self-signed or signed by another CA. If it is signed by another CA, you need a certificate that authenticates that CA's public key.
For example, you have obtained a _X_`.cer` file from a company that is a CA and the file is supposed to be a self-signed certificate that authenticates that CA's public key. Before you import it as a trusted certificate, you should ensure that the certificate is valid by:
1. Viewing it with the `keytool -printcert` command or the `keytool -importcert` command without using the `-noprompt` option. Make sure that the displayed certificate fingerprints match the expected fingerprints.
2. Calling the person who sent the certificate, and comparing the fingerprints that you see with the ones that they show or that a secure public key repository shows.
Only when the fingerprints are equal is it assured that the certificate wasn't replaced in transit with somebody else's certificate (such as an attacker's certificate). If such an attack takes place, and you didn't check the certificate before you imported it, then you would be trusting anything that the attacker signed.
用证书链替换自签名证书,其中链中的每个证书都验证链中前一个证书的签署者的公钥,直到根 CA。
如果您信任证书有效,那么您可以通过输入以下命令将其添加到密钥库中
keytool -importcert -alias` _alias_ `-file *X*`.cer\
此命令从 CA 证书文件中的数据在密钥库中创建一个受信任的证书条目,并将 alias 的值分配给该条目。
导入 CA 的证书回复
在您导入验证您提交证书签名请求的 CA 的公钥的证书后(或密钥库或 cacerts
密钥库文件中已存在此类证书),您可以导入证书回复并用证书链替换您的自签名证书。
证书链是以下之一
由 CA 返回,当 CA 回复是链时。
在 CA 回复是单个证书时构建。此证书链是通过使用证书回复和密钥库(您导入回复的密钥库)或
cacerts
密钥库文件中可用的受信任证书构建的。
例如,如果您将证书签名请求发送给 DigiCert,那么您可以通过输入以下命令导入他们的回复
注意
在此示例中,返回的证书名为 DCmyname.cer
。
keytool -importcert -trustcacerts -file DCmyname.ce
导出验证公钥的证书
注意
如果您使用 jarsigner
命令来签署 Java 归档 (JAR) 文件,那么使用该文件的客户端将希望验证您的签名。
客户端验证您的签名的一种方法是将您的公钥证书导入其密钥库作为受信任的条目。然后,您可以导出证书并将其提供给您的客户端。
例如
通过输入以下命令将您的证书复制到名为
myname.cer
的文件中注意
在此示例中,该条目的别名为
mykey
。keytool -exportcert -alias mykey -file myname.cer
有了证书和签名的 JAR 文件,客户端可以使用
jarsigner
命令来验证您的签名。
导入密钥库
使用importkeystore
命令将整个密钥库导入另一个密钥库。这将使用单个命令将源密钥库中的所有条目(包括密钥和证书)导入目标密钥库。您可以使用此命令从不同类型的密钥库导入条目。在导入过程中,目标密钥库中的所有新条目将具有相同的别名和保护密码(对于密钥和私钥)。如果keytool
命令无法从源密钥库中恢复私钥或密钥,则它会提示您输入密码。如果检测到别名重复,它会要求您输入一个新的别名,您可以指定一个新的别名,或者简单地允许keytool
命令覆盖现有的别名。
例如,将典型 JKS 类型密钥库key.jks
中的条目导入 PKCS #11 类型的基于硬件的密钥库,方法是输入以下命令
keytool -importkeystore -srckeystore key.jks -destkeystore NONE -srcstoretype JKS -deststoretype PKCS11 -srcstorepass `_password_` -deststorepass `_password_`
importkeystore
命令还可以用于将单个条目从源密钥库导入目标密钥库。在这种情况下,除了在前面的示例中使用的选项外,您还需要指定要导入的别名。使用-srcalias
选项指定,您还可以指定目标别名、密钥或私钥的保护密码以及您想要的目标保护密码,如下所示
keytool -importkeystore -srckeystore key.jks -destkeystore NONE -srcstoretype JKS \
-deststoretype PKCS11 -srcstorepass `_password_` -deststorepass `_password_` \
-srcalias myprivatekey -destalias myoldprivatekey -srckeypass `_password_` \
-destkeypass `_password_` -noprompt
为 SSL 服务器生成证书
以下是用于为三个实体生成密钥对和证书的keytool
命令
根 CA (
root
)中间 CA (
ca
)SSL 服务器 (
server
)
确保将所有证书存储在同一个密钥库中。
keytool -genkeypair -keystore root.jks -alias root -ext bc:c -keyalg rsa
keytool -genkeypair -keystore ca.jks -alias ca -ext bc:c -keyalg rsa
keytool -genkeypair -keystore server.jks -alias server -keyalg rsa
keytool -keystore root.jks -alias root -exportcert -rfc > root.pem
keytool -storepass password -keystore ca.jks -certreq -alias ca |
keytool -storepass password -keystore root.jks
-gencert -alias root -ext BC=0 -rfc > ca.pem
keytool -keystore ca.jks -importcert -alias ca -file ca.pem
keytool -storepass password -keystore server.jks -certreq -alias server |
keytool -storepass password -keystore ca.jks -gencert -alias ca
-ext ku:c=dig,kE -rfc > server.pem
cat root.pem ca.pem server.pem |
keytool -keystore server.jks -importcert -alias server
术语
密钥库
密钥库是用于存储加密密钥和证书的存储设施。
密钥库条目
密钥库可以有不同类型的条目。keytool
命令最适用的两种条目类型包括以下内容
密钥条目:每个条目都包含非常敏感的加密密钥信息,这些信息以受保护的格式存储,以防止未经授权的访问。通常,存储在此类条目中的密钥是密钥,或与对应公钥的证书链一起的私钥。请参阅证书链。keytool
命令可以处理这两种类型的条目,而jarsigner
工具只处理后一种类型的条目,即私钥及其关联的证书链。
受信任的证书条目:每个条目包含属于另一方的单个公钥证书。该条目被称为受信任的证书,因为密钥库所有者信任证书中的公钥属于证书主体(所有者)标识的身份。证书的颁发者通过签署证书来证明这一点。
密钥库别名
所有密钥库条目(密钥和受信任的证书条目)都通过唯一的别名进行访问。
当您使用-genseckey
命令生成密钥、使用-genkeypair
命令生成密钥对(公钥和私钥)或使用-importcert
命令将证书或证书链添加到受信任证书列表时,您会指定一个别名。后续的keytool
命令必须使用相同的别名来引用该实体。
例如,您可以使用别名duke
来生成新的公钥/私钥对,并将公钥封装到自签名证书中,方法是使用以下命令。请参阅证书链。
keytool -genkeypair -alias duke -keyalg rsa -keypass `_passwd_`
此示例指定了后续命令访问与别名duke
关联的私钥所需的初始passwd。如果您以后想更改 Duke 的私钥密码,请使用以下命令
keytool -keypasswd -alias duke -keypass `_passwd_` -new `_newpasswd_`
这将初始passwd
更改为newpasswd
。除非出于测试目的,或者您在安全系统上,否则不应在命令行或脚本中指定密码。如果您没有在命令行上指定所需的密码选项,则会提示您输入密码。
密钥库实现
java.security
包中提供的KeyStore
类提供定义明确的接口来访问和修改密钥库中的信息。可能存在多个不同的具体实现,其中每个实现都是针对特定类型的密钥库的实现。
目前,两个命令行工具(keytool
和jarsigner
)使用密钥库实现。由于KeyStore
类是public
的,因此用户可以编写使用它的其他安全应用程序。
在 JDK 9 及更高版本中,默认密钥库实现是PKCS12
。这是一个基于 RSA PKCS12 个人信息交换语法标准的跨平台密钥库。该标准主要用于存储或传输用户的私钥、证书和杂项机密。Oracle 提供了另一个内置实现。它将密钥库实现为一个具有专有密钥库类型(格式)的文件,名为JKS
。它使用其各自的密码保护每个私钥,并使用(可能不同的)密码保护整个密钥库的完整性。
密钥库实现是基于提供者的。更准确地说,KeyStore
提供的应用程序接口是根据服务提供者接口 (SPI) 实现的。也就是说,在java.security
包中还有一个对应的抽象KeystoreSpi
类,它定义了提供者必须实现的服务提供者接口方法。术语提供者是指提供可以由 Java 安全 API 访问的服务子集的具体实现的包或一组包。要提供密钥库实现,客户端必须实现提供者并提供KeystoreSpi
子类实现,如实现和集成提供者的步骤中所述。
应用程序可以使用KeyStore
类中提供的getInstance
工厂方法从不同的提供者选择不同类型的密钥库实现。密钥库类型定义了密钥库信息的存储和数据格式,以及用于保护密钥库中私钥/密钥和密钥库完整性的算法。不同类型的密钥库实现不兼容。
keytool
命令适用于任何基于文件的密钥库实现。它将传递给它的命令行中的密钥库位置视为文件名,并将其转换为FileInputStream
,从中加载密钥库信息。jarsigner
命令可以从任何可以使用 URL 指定的位置读取密钥库。
对于keytool
和jarsigner
,您可以在命令行中使用-storetype
选项指定密钥库类型。
如果您没有显式指定密钥库类型,则这些工具会根据安全属性文件中指定的keystore.type
属性的值选择密钥库实现。安全属性文件名为java.security
,位于安全属性目录中
- Linux 和 macOS:
java.home/lib/security
- Windows:
java.home\lib\security
每个工具都会获取keystore.type
值,然后检查所有当前安装的提供者,直到找到一个实现了该类型密钥库的提供者。然后,它使用该提供者的密钥库实现。KeyStore
类定义了一个名为getDefaultType
的静态方法,允许应用程序检索keystore.type
属性的值。以下代码行创建了安全属性文件中指定的默认密钥库类型的实例
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
默认密钥库类型是pkcs12
,这是一个基于 RSA PKCS12 个人信息交换语法标准的跨平台密钥库。这是由安全属性文件中的以下行指定的
keystore.type=pkcs12
要让这些工具使用除默认密钥库实现之外的密钥库实现,您可以更改该行以指定不同的密钥库类型。例如,如果您想使用 Oracle 的jks
密钥库实现,则将该行更改为以下内容
keystore.type=jks
注意
密钥库类型指定中的大小写无关紧要。例如,JKS
将被视为与jks
相同。
证书
证书(或公钥证书)是来自一个实体(颁发者)的数字签名声明,说明另一个实体(主体)的公钥和一些其他信息具有特定值。以下术语与证书相关
公钥:这些是与特定实体关联的数字,旨在让所有需要与该实体进行可信交互的人员都知道。公钥用于验证签名。
数字签名:如果某些数据被数字签名,则它将与实体的身份和证明该实体知道该数据的签名一起存储。通过使用实体的私钥签名,数据变得不可伪造。
身份:一种已知的地址实体的方式。在某些系统中,身份是公钥,而在其他系统中,它可以是任何东西,例如电子邮件地址到 X.509 区分名称。
签名:签名是使用实体的私钥对某些数据进行计算的。签名者,在证书的情况下也称为颁发者。
私钥:这些是数字,每个数字都应该只为拥有该私钥的特定实体所知(即,它应该保密)。私钥和公钥在所有公钥密码系统(也称为公钥密码系统)中成对存在。在典型的公钥密码系统(如 DSA)中,私钥对应于一个公钥。私钥用于计算签名。
实体:实体是指人、组织、程序、计算机、企业、银行或您在一定程度上信任的其他事物。
公钥密码需要访问用户的公钥。在大型网络环境中,无法保证通信实体之间建立了先前的关系,或者存在包含所有使用公钥的可信存储库。证书被发明出来作为解决这种公钥分发问题的方案。现在,证书颁发机构 (CA) 可以充当可信的第三方。CA 是企业等实体,它们被信任为其他实体签署(颁发)证书。假设 CA 只创建有效且可靠的证书,因为它们受法律协议约束。有许多公共证书颁发机构,例如 DigiCert、Comodo、Entrust 等。
您还可以使用 Microsoft 证书服务器或 Entrust CA 产品等产品为您的组织运行自己的证书颁发机构。使用keytool
命令,可以显示、导入和导出证书。还可以生成自签名证书。
keytool
命令目前处理 X.509 证书。
X.509 证书
X.509 标准定义了哪些信息可以放入证书中,并描述了如何将其写下来(数据格式)。证书中的所有数据都使用两个相关的标准进行编码,称为 ASN.1/DER。抽象语法符号 1 描述数据。确定性编码规则描述了一种存储和传输该数据的唯一方式。
除了签名之外,所有 X.509 证书都包含以下数据
版本:这标识了适用于此证书的 X.509 标准的哪个版本,这会影响可以在其中指定哪些信息。到目前为止,已定义了三个版本。
keytool
命令可以导入和导出 v1、v2 和 v3 证书。它生成 v3 证书。X.509 版本 1 自 1988 年起可用,已广泛部署,并且是最通用的版本。
X.509 版本 2 引入了主体和颁发者唯一标识符的概念,以处理随着时间的推移重复使用主体或颁发者名称的可能性。大多数证书配置文件文档强烈建议不要重复使用名称,并且证书不应使用唯一标识符。版本 2 证书没有得到广泛使用。
X.509 版本 3 是最新的版本(1996 年),它支持扩展的概念,任何人都可以定义扩展并将其包含在证书中。一些常见的扩展包括:KeyUsage(将密钥的使用限制在特定用途,例如 `signing-only`)和 AlternativeNames(允许将其他身份与该公钥相关联,例如 DNS 名称、电子邮件地址、IP 地址)。扩展可以标记为关键,以指示应检查和执行或使用该扩展。例如,如果证书具有标记为关键且设置为 `keyCertSign` 的 KeyUsage 扩展,那么当此证书在 SSL 通信期间呈现时,它应该被拒绝,因为证书扩展表明关联的私钥只能用于签名证书,而不能用于 SSL 使用。
序列号:创建证书的实体负责为其分配一个序列号,以将其与它发行的其他证书区分开来。此信息在多种情况下使用。例如,当证书被吊销时,其序列号会被放入证书吊销列表 (CRL) 中。
签名算法标识符:这标识了 CA 用于签署证书的算法。
颁发者名称:签署证书的实体的 X.500 可辨别名称。这通常是 CA。使用此证书意味着信任签署此证书的实体。在某些情况下,例如根 CA 或顶级 CA 证书,颁发者会签署自己的证书。
有效期:每个证书仅在有限的时间内有效。此时间段由开始日期和时间以及结束日期和时间描述,可以短至几秒钟,也可以长达近一个世纪。选择的有效期取决于许多因素,例如用于签署证书的私钥的强度,或者愿意为证书支付的金额。这是实体可以依赖公共值的预期时间段,前提是关联的私钥没有被泄露。
主体名称:证书标识的实体的名称。此名称使用 X.500 标准,因此它旨在在整个互联网上是唯一的。这是实体的 X.500 可辨别名称 (DN)。例如,
CN=Java Duke, OU=Java Software Division, O=Oracle Corporation, C=US
这些指的是主体的通用名称 (CN
)、组织单位 (OU
)、组织 (O
) 和国家/地区 (C
)。
- 主体公钥信息:这是被命名的实体的公钥,以及一个算法标识符,指定此密钥所属的公钥密码系统以及任何关联的密钥参数。
证书链
keytool
命令可以创建和管理密钥库密钥条目,每个条目都包含一个私钥和一个关联的证书链。链中的第一个证书包含与私钥相对应的公钥。
当密钥首次生成时,链最初包含单个元素,一个自签名证书。请参阅 **命令** 中的 -genkeypair。自签名证书是指颁发者(签名者)与主体相同的证书。主体是其公钥由证书进行身份验证的实体。每当调用 -genkeypair
命令来生成新的公钥/私钥对时,它还会将公钥包装到自签名证书中。
稍后,在使用 -certreq
命令生成证书签名请求 (CSR) 并将其发送到证书颁发机构 (CA) 后,来自 CA 的响应将使用 -importcert
导入,并且自签名证书将被证书链替换。链的底部是 CA 发行的证书(回复),用于验证主体的公钥。链中的下一个证书是验证 CA 公钥的证书。
在许多情况下,这是一个自签名证书,即来自 CA 的证书,用于验证其自身的公钥,也是链中的最后一个证书。在其他情况下,CA 可能会返回证书链。在这种情况下,链中的底部证书是相同的(由 CA 签署的证书,用于验证密钥条目的公钥),但链中的第二个证书是由不同的 CA 签署的证书,用于验证您向其发送 CSR 的 CA 的公钥。链中的下一个证书是验证第二个 CA 密钥的证书,依此类推,直到到达自签名根证书。链中的每个证书(第一个证书之后)都验证链中前一个证书的签名者的公钥。
许多 CA 仅返回已发行的证书,不包含任何支持链,尤其是在存在扁平层次结构(没有中间 CA)时。在这种情况下,必须从密钥库中已存储的受信任证书信息中建立证书链。
不同的回复格式(由 PKCS #7 标准定义)除了已发行的证书之外,还包含支持的证书链。keytool
命令可以处理这两种回复格式。
顶级(根)CA 证书是自签名的。但是,对根公钥的信任并非来自根证书本身,而是来自其他来源,例如报纸。这是因为任何人都可以生成一个自签名证书,其可辨别名称例如为 DigiCert 根 CA。根 CA 公钥是众所周知的。它存储在证书中的唯一原因是,这是大多数工具理解的格式,因此在这种情况下,证书仅用作传输根 CA 公钥的工具。在将根 CA 证书添加到密钥库之前,您应该使用 -printcert
选项查看它,并将显示的指纹与从报纸、根 CA 的网页等获得的众所周知的指纹进行比较。
cacerts
证书文件
名为 cacerts
的证书文件位于安全属性目录中
- Linux 和 macOS:
$JAVA_HOME/lib/security
- Windows:
$JAVA_HOME\lib\security
cacerts
文件表示一个系统范围的密钥库,其中包含 CA 证书。系统管理员可以使用 keytool
命令通过指定 jks
作为密钥库类型来配置和管理该文件。cacerts
密钥库文件附带一组默认的根 CA 证书。对于 Linux、OS X 和 Windows,您可以使用以下命令列出默认证书
keytool -list -cacerts
cacerts
密钥库文件的初始密码为 changeit
。系统管理员应在安装 SDK 后更改该密码以及该文件的默认访问权限。
注意
验证您的 cacerts
文件非常重要。因为您信任 cacerts
文件中的 CA 作为签署和向其他实体颁发证书的实体,所以您必须仔细管理 cacerts
文件。cacerts
文件应仅包含您信任的 CA 的证书。您有责任验证捆绑在 cacerts
文件中的受信任的根 CA 证书,并做出您自己的信任决定。
要从 cacerts
文件中删除不受信任的 CA 证书,请使用 keytool
命令的 -delete
选项。您可以在 JDK 的 $JAVA_HOME/lib/security
目录中找到 cacerts
文件。如果您没有权限编辑此文件,请联系您的系统管理员。
Internet RFC 1421 证书编码标准
证书通常使用 Internet RFC 1421 标准定义的可打印编码格式存储,而不是它们的二进制编码。这种证书格式,也称为 Base64 编码,使得通过电子邮件或其他机制将证书导出到其他应用程序变得容易。
-importcert
和 -printcert
命令读取的证书可以是这种格式或二进制编码。-exportcert
命令默认输出二进制编码的证书,但当指定 -rfc
选项时,它将改为输出可打印编码格式的证书。
-list
命令默认打印证书的 SHA-256 指纹。如果指定 -v
选项,则证书将以人类可读的格式打印。如果指定 -rfc
选项,则证书将以可打印编码格式输出。
在可打印编码格式中,编码的证书在开头和结尾用以下文本包围
-----BEGIN CERTIFICATE-----
encoded certificate goes here.
-----END CERTIFICATE-----
X.500 可辨别名称
X.500 可辨别名称用于标识实体,例如 X.509 证书的 subject
和 issuer
(签名者)字段命名的实体。keytool
命令支持以下子部分
commonName:一个人的通用名称,例如 Susan Jones。
organizationUnit:小型组织(例如部门或部门)名称。例如,采购。
localityName:地区(城市)名称,例如,帕洛阿尔托。
stateName:州或省名称,例如,加利福尼亚州。
country:两位字母的国家/地区代码,例如,CH。
当您将可辨别名称字符串作为 -dname
选项的值提供时,例如对于 -genkeypair
命令,该字符串必须采用以下格式
CN=cName, OU=orgUnit, O=org, L=city, S=state, C=countryCode
以下所有项目都代表实际值,前面的关键字是以下内容的缩写
CN=commonName
OU=organizationUnit
O=organizationName
L=localityName
S=stateName
C=country
一个可辨别名称字符串示例是
CN=Mark Smith, OU=Java, O=Oracle, L=Cupertino, S=California, C=US
使用此类字符串的示例命令是
keytool -genkeypair -dname "CN=Mark Smith, OU=Java, O=Oracle, L=Cupertino, S=California, C=US" -alias mark -keyalg rsa
关键字缩写的区分大小写。例如,CN、cn 和 Cn 都被视为相同。
顺序很重要;每个子组件必须按指定的顺序出现。但是,不必包含所有子组件。您可以使用子集,例如
CN=Smith, OU=Java, O=Oracle, C=US
如果可辨别名称字符串值包含逗号,那么当您在命令行上指定字符串时,逗号必须用反斜杠 (\) 字符转义,例如
cn=Jack, ou=Java\, Product Development, o=Oracle, c=US
在命令行上,永远不需要指定区分名称字符串。当命令需要区分名称,但命令行上没有提供时,会提示用户输入每个子组件。在这种情况下,不需要用反斜杠 (\) 对逗号进行转义。
警告
导入受信任证书警告
重要:在将证书导入为受信任证书之前,请务必仔细检查证书。
Windows 示例
首先使用 -printcert
命令或不带 -noprompt
选项的 -importcert
命令查看证书。确保显示的证书指纹与预期指纹匹配。例如,假设有人向您发送或通过电子邮件发送了一个证书,您将其放在名为 \tmp\cert
的文件中。在考虑将证书添加到受信任证书列表之前,您可以执行 -printcert
命令以查看其指纹,如下所示
keytool -printcert -file \tmp\cert
Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll
Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll
Serial Number: 59092b34
Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016
Certificate Fingerprints:
SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE
SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90:
17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4
Linux 示例
首先使用 -printcert
命令或不带 -noprompt
选项的 -importcert
命令查看证书。确保显示的证书指纹与预期指纹匹配。例如,假设有人向您发送或通过电子邮件发送了一个证书,您将其放在名为 /tmp/cert
的文件中。在考虑将证书添加到受信任证书列表之前,您可以执行 -printcert
命令以查看其指纹,如下所示
keytool -printcert -file /tmp/cert
Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll
Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll
Serial Number: 59092b34
Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016
Certificate Fingerprints:
SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE
SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90:
17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4
然后,致电或以其他方式联系发送证书的人员,并将您看到的指纹与他们显示的指纹进行比较。只有当指纹相同时,才能保证证书在传输过程中没有被替换为其他人的证书,例如攻击者的证书。如果发生了这种攻击,并且您在导入证书之前没有检查证书,那么您将信任攻击者签署的任何内容,例如包含恶意类文件的 JAR 文件。
注意
在导入证书之前,您不需要执行 -printcert
命令。这是因为在将证书添加到密钥库中的受信任证书列表之前,-importcert
命令会打印出证书信息并提示您进行验证。然后,您可以停止导入操作。但是,只有在不带 -noprompt
选项的情况下调用 -importcert
命令时,才能执行此操作。如果指定了 -noprompt
选项,则不会与用户进行交互。
密码警告
大多数对密钥库进行操作的命令都需要存储密码。某些命令需要私钥/密钥密码。密码可以在 -storepass
和 -keypass
选项的命令行中指定。但是,除非是为了测试,或者您是在安全系统上,否则不应在命令行或脚本中指定密码。当您没有在命令行上指定所需的密码选项时,系统会提示您输入密码。
证书符合性警告
Internet X.509 公钥基础设施证书和证书吊销列表 (CRL) 配置文件 定义了符合 X.509 证书的配置文件,其中包括证书字段和扩展名的有效值和值组合。
keytool
命令不会强制执行所有这些规则,因此它可以生成不符合标准的证书,例如用于内部测试目的的自签名证书。不符合标准的证书可能会被 JDK 或其他应用程序拒绝。用户应确保为 -dname
、-ext
等提供正确的选项。
导入新的受信任证书
在将证书添加到密钥库之前,keytool
命令会通过尝试使用密钥库中已有的受信任证书,从该证书到自签名证书(属于根 CA)构建信任链来验证证书。
如果指定了 -trustcacerts
选项,则会考虑其他证书用于信任链,即名为 cacerts
的文件中的证书。
如果 keytool
命令无法从要导入的证书建立到自签名证书(来自密钥库或 cacerts
文件)的信任路径,则会打印证书信息,并提示用户通过将显示的证书指纹与从其他(受信任)信息源(可能是证书所有者)获得的指纹进行比较来验证证书。在将证书导入为受信任证书之前,请务必仔细确保证书有效。然后,用户可以选择停止导入操作。如果指定了 -noprompt
选项,则不会与用户进行交互。
导入证书回复
当您导入证书回复时,证书回复会使用密钥库中的受信任证书进行验证,并且在指定 -trustcacerts
选项时,还会使用 cacerts
密钥库文件中配置的证书进行验证。
确定证书回复是否受信任的方法如下
如果回复是单个 X.509 证书,则
keytool
命令会尝试建立信任链,从证书回复开始,到自签名证书(属于根 CA)结束。证书回复和证书层次结构用于从新的证书别名链中对证书回复进行身份验证。如果无法建立信任链,则不会导入证书回复。在这种情况下,keytool
命令不会打印证书并提示用户进行验证,因为用户很难确定证书回复的真实性。如果回复是 PKCS #7 格式的证书链或一系列 X.509 证书,则链按用户证书优先,然后是零个或多个 CA 证书的顺序排列。如果链以自签名根 CA 证书结束,并且指定了
-trustcacerts
选项,则keytool
命令会尝试将其与密钥库或cacerts
密钥库文件中的任何受信任证书进行匹配。如果链没有以自签名根 CA 证书结束,并且指定了-trustcacerts
选项,则keytool
命令会尝试从密钥库或cacerts
密钥库文件中的受信任证书中找到一个并将其添加到链的末尾。如果未找到证书,并且未指定-noprompt
选项,则会打印链中最后一个证书的信息,并提示用户进行验证。
如果证书回复中的公钥与使用 alias
存储的用户公钥匹配,则会将旧的证书链替换为回复中的新的证书链。旧的链只能使用有效的 keypass
替换,因此会提供用于保护条目私钥的密码。如果未提供密码,并且私钥密码与密钥库密码不同,则会提示用户输入密码。
此命令在早期版本中名为 -import
。此旧名称在本版本中仍然受支持。新的名称 -importcert
是首选。
上次更新: 2021 年 9 月 14 日