keytool 是一个密钥和证书管理工具。允许用户管理自己的公钥 / 私钥对及相关证书,利用数字签名技术,用于自我认证、数据完整性检查和认证服务。它也允许用户存储与其通信的另一方的公钥(以证书形式)。
Keytool 将密钥和证书存储在密钥库 (keystore) 内。
keytool 目前处理 X.509 证书。 keytool 可导入和导出 v1 、 v2 和 v3 版的证书,能生成 v3 版证书。
本文档基于 jdk1.6 keytool 文档。
证书链
keytool 可创建和管理密钥仓库的“密钥”项,每个密钥项都含有私钥和相关证书“链”。链中的第一个证书含有与私钥对应的公钥。
当第一次产生密钥(参见 -genkeypair 命令)时,链中只含有一个元素,即自签名证书。自签名证书是一个这样的证书:其签发人(签名人)与主体(证书所认证的公钥所属的实体)相同。当调用 -genkeypair 命令来生成新的公钥 / 私钥对时,它同时也把公钥打包进自签名证书中。
之后,当证书签名请求 (CSR) (参见 -certreq 命令)被生成并送至认证机构 (CA) 后, CA 的答复将被导入(参见 -importcert ),证书链将取代自签名证书。在链的底部是认证主体公钥的 CA 所发放的证书(答复)。链中下一个证书是用于认证 CA 公钥的证书。
在许多情况下,这是个自签名证书(即来自认证其自身公钥的 CA 的证书)且是链中的最后一个证书。在其它情况下, CA 也许将返回证书链。这种情况下,链中底部的证书是相同的(由 CA 签名的证书,对密钥项的公钥进行认证),但链中第二个证书是由不同的 CA 所签名的,对您向其发送 CSR 的 CA 的公钥进行认证。然后,链中的下一个证书将是对第二个 CA 的公钥进行认证的证书,以此类推,直至到达自签名的“根”证书为止。因此,链中的每个证书(从第一个以后)都对链中前一个证书的签名人的公钥进行认证。
许多 CA 只返回所发放的证书,而不支持链,特别是当层次结构较简单时(无中介 CA )。这种情况下,必须用储存在密钥仓库中的可信任的证书信息来建立证书链。
另一种答复格式(由 PKCS#7 标准所定义)除了包含所签发的证书外,还支持证书链。两种答复格式都可由 keytool 处理。
顶层(根) CA 证书是自签名的。但是,对根公钥的信任并非来自根证书本身(任何人都可用特征名来产生自签名证书!譬如说用 VeriSign 根 CA 的特征名) , 而是来自报纸之类的其它来源。根 CA 的公钥是广为人知的。它被储存在证书中的唯一原因是因为这是大多数工具所能理解的格式,因此这种情况下的证书只是作为一种传输根 CA 的公钥用的“交通工具”。在将根 CA 证书加到您的密钥仓库中之前,应该先对它进行查看(用 -printcert 选项)并将所显示的指纹与已知的指纹(从报纸、根 CA 的网页等中获取)进行比较。
命令和选项
选项默认值
-alias 别名,默认为 "mykey"
-keyalg
"DSA" (when using -genkeypair)
"DES" (when using -genseckey)
-keysize
1024 (when using -genkeypair)
56 (when using -genseckey and -keyalg is "DES")
168 (when using -genseckey and -keyalg is "DESede")
-validity 证书有效天数,默认为 90
-keystore 密钥库位置,默认文件名为 .keystore ,存储在用户主目录下
-storetype 存储类型,默认值取自安全属性文件( java.security 文件,在 jre\lib\security 目录下)的 "keystore.type" 属性。
不同的提供者可定义不同的 keystore 实现方式,提供者需实现 "Service Provider Interface" (SPI) 。 Sun 提供的内建缺省实现名为” JKS ”,它利用专用密钥仓库类型(格式),将 keystore 实现为一个文件。
Keytool 仅支持基于文件的 keystore 实现。
-file 读时为标准输入 (stdin) ,写时为标准输出 (stdout)
-protected false
-sigalg 签名算法,在生成一个公钥 / 私钥对时,签名算法取决于底层的私钥算法:如果底层私钥算法是“ DSA ”,则 -sigalg 默认值为 "SHA1withDSA ” , 如果底层私钥算法是“ RSA ”,则 -sigalg 默认值为 "MD5withRSA ”,即与 -keyalg 相关。
支持的算法
keytool 允许用户指定任何注册了的加密服务提供者所提供的密钥对生成算法和签名算法。也就是说,各种命令中的 keyalg 和 sigalg 选项必须得到提供者实现的支持。
常用选项
-v 选项可出现在除 -help 外的所有命令中。如果出现该选项,表示处在“ verbose (详细)”模式下,更多的信息将被输出。
-Jjavaoption 选项也可出现任何命令中。如果出现该选项,则所指定的 javaoption 字符串将被直接传给 Java 解释器。 该选项不应含有任何空格。它有助于调整执行环境或内存使用。要获得可用的解释器选项的清单,可在命令行键入 java -h 或 java -X 。
-storetype 指定存储类型
- keystore Keystore 位置,当指定了一个尚不存在的 keystore 时, keystore 将被创建。
-storepass 存储库密码 ( 获取 keystore 信息所需的密码,用于保护其完整性 ) ,至少为 6 位字符
-providerName 加密服务提供者的名称
-providerClass 当服务提供者未在安全属性文件中列出时,用于指定加密服务提供程序的主类文件的名称。
-providerArg 与 -providerClass 结合使用,表示 provider_class_name 构造函数的可选字符串输入参数。
-protected 值为 True 或 false ,如果密码必须通过一个受保护的认证路径,如专用的 PIN reader ,这个值应被设为 true 。
命令
创建 keystore 及添加数据
1 、生成 key pair
-genkeypair [-v] [-protected]
[-alias < 别名 >]
[-keyalg <keyalg>] [-keysize < 密钥大小 >]
[-sigalg <sigalg>] [-dname <dname>]
[-validity < 有效天数 >] [-keypass < 密钥库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
生成 key pair( 公钥和私钥 ) ,将公钥包装到一个 X.509 v3 自签名证书内,作为单元素证书链被存储。此证书链和私钥存储在以别名标识的新 keystore 项内。
-Keyalg 指定生成 keypair 的算法。
-keysize 指定密钥长度。
-sigalg 指定签名算法,必须和 keyalg 兼容。
-dname 指定与 alias 关联的 X.500 特征名,用作自签名证书中的发行者和主体域。 例如: "CN= 名字与姓氏 ,OU= 组织单位名称 ,O= 组织名称 ,L= 城市或区域名称 ,ST= 州或省份名称 ,C= 单位的两字母国家代码 " 。
(CN 一般输入域名, OU 为部门名或分公司 )
-keypass 密钥库密码 ( 私钥的密码, alias 的主密码 ) ,至少为 6 个字符,用来保护私钥。
-validity 证书的有效天数
注:以前版本此命令名称为 -genkey 。
2 、生成密钥
-genseckey [-v] [-protected]
[-alias < 别名 >] [-keypass < 密钥库口令 >]
[-keyalg <keyalg>] [-keysize < 密钥大小 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
生成一个密钥,并将其存储在一个以别名标识的新的 KeyStore.SecretKeyEntry 项内。
-keyalg 指定生成密钥的算法
-keypass 保存密钥的密码,至少 6 位
3 、导入证书
-importcert [-v] [-noprompt] [-trustcacerts] [-protected]
[-alias < 别名 >]
[-file < 认证文件 >] [-keypass < 密钥库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
从文件中读取证书或证书链(后者在 PKCS#7 格式的回复中提供),并存储到以别名标识的 keystore 项中。如果未指定文件,将从 stdin 读取证书或 PKCS#7 回复。
keytool 能导入 X.509 v1 、 v2 、 v3 证书和由该类证书组成的 PKCS#7 格式的证书链。要导入的数据必须是二进制编码格式或 Internet RFC 1421 标准所定义的可打印的编码格式(也称 Base64 编码)。在后一种情况下,编码必须以“ -----BEGIN ”开头的字符串开始,以“ -----END ”开头的字符串来结束。
导入证书的两个原因:
1 ) 将其添加到受信任证书列表
2 ) 导入向 CA 提交证书签名请求(参见 -certreq 命令)后收到的来自该 CA 的证书回复。
-alias 选项的值表明要进行何种类型的导入:
1 )如果别名没有指向一个密钥项( key entry ), keytool 假定要增加一个受信任证书项。在这种情况下,别名不应该在 keystore 中存在。如果别名确实存在,那么 keytool 将输出一个错误,既然此别名已经有一个可信任证书,不能再导入证书。
2 )如果别名指向一个密钥项( key entry ), keytool 假定导入证书回复。
在以前版本中,此命令名称为 -import 。
导入新的可信任证书
在添加证书到 keystore 前, keytool 将尝试用 keystore 中已有的可信任证书来构造从该证书到自签名证书(属于根 CA )的信任链,以对证书进行校验。
如果指定了 -trustcacerts 选项,则要为信任链考虑其他证书,即名为 "cacerts" 的文件中的证书。( "cacerts" 在安全属性目录 jre\lib\security 下,是含有 CA 证书的系统密钥仓库,系统管理员可以使用 keytool 进行管理和配置,其存储类型为” jks ”,初始密码为” changeit ”。注意:此文件应仅包含受信任的 CA 证书)
如果 keytool 无法建立从要导入的证书到自签名证书(从 keystore 或 "cacerts" 文件)的信任路径,则打印出证书信息,提示用户验证证书,用户可将显示的证书指纹与来自其他可信信息来源的指纹进行比较,信息源可能是证书拥有者本人。在将证书作为可信任证书导入前,要确保证书是有效的。用户可以终止证书导入操作。然而,如果指定了 -noprompt 选项,则不会与用户进行交互。
导入证书回复
当导入证书回复时,该认证回复将用密钥仓库中可信任的证书来确认,也可使用在“ cacerts ” keystore 文件中配置的证书 ( 如果指定了 -trustcacerts 选项 ) 。
判定证书回复是否是可信的方法:
如果回复是一个 X.509 证书, keytool 尝试建立信任链,起始于证书回复,结束于自签名证书(属于根 CA )。此证书回复和用于验证证书回复的证书层次形成了 alias 的新证书链。如果不能建立信任链,则不能导入证书回复。
如果回复是 PKCS#7 格式的证书链,则该链首先被排序(用户证书在前,自签名根 CA 证书在后),然后 keytool 尝试将回复中的根 CA 证书与 keystore 或“ cacerts ” keystore 文件(如果指定了 -trustcacerts 选项)中的任何可信任证书进行匹配。如果不匹配,则打印根 CA 证书信息,提示用户验证证书。
如果证书回复中的公钥与别名存储的公钥匹配,在回复中的新证书链将取代老证书链。
在以前版本中,此命令名称为 -import 。
4 、导入 keystore
-importkeystore [-v]
[-srckeystore < 源密钥库 >] [-destkeystore < 目标密钥库 >]
[-srcstoretype < 源存储类型 >] [-deststoretype < 目标存储类型 >]
[-srcstorepass < 源存储库口令 >] [-deststorepass < 目标存储库口令 >]
[-srcprotected] [-destprotected]
[-srcprovidername < 源提供方名称 >]
[-destprovidername < 目标提供方名称 >]
[-srcalias < 源别名 > [-destalias < 目标别名 >]
[-srckeypass < 源密钥库口令 >] [-destkeypass < 目标密钥库口令 >]]
[-noprompt]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
将源 keystore 中的一项或全部项导入到目标 keystore 。
当指定 -srcalias 时,将此别名标识的项导入到目标 keystore 。如果未指定 -destalias ,将使用源别名作为目标别名。如果源项受密码保护, srckeypass 将用于恢复条目。如果未提供 srckeypass , keytool 将尝试使用 srcstorepass 。如果 srcstorepass 未提供或不正确,将提示用户输入密码。使用 destkeypass 保护目标项,如果未提供 destkeypass ,将使用源项的密码保护目标项。
如果在目标 keystore 中已经存在目标别名,将提示用户或者覆盖此项,或使用不同别名创建新项。
注意:如果提供了 -noprompt ,将不提示用户输入新的目标别名,现有项将自动被覆盖。最后,不能导入的项自动跳过,并产生警告输出。
导出数据
1 、生成 CSR
-certreq [-v] [-protected]
[-alias < 别名 >] [-sigalg <sigalg>]
[-file <csr_file>] [-keypass < 密钥库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
生成一个 PKCS # 10 格式的证书签名请求( CSR )。
生成 CSR 的目的是将其发给证书认证机构( CA )。 CA 将认证证书请求(通常是离线),然后返回一个证书或证书链,用来取代在 keystore 中已存在的证书链(最初包含自签名证书)。经 CA 认证的证书将更容易得到别人的信任。
使用与别名关联的私钥和 X.500 特征名 (dname) 来创建 PKCS#10 证书请求。因为在 keystore 中私钥被一个密码保护,因此为了访问私钥,必须提供适当的密码(即需提供 keypass )。
-sigalg 指定 csr 签名算法。
CSR 存储在 csr_file 文件中。如果没有指定文件,则输出到 stdout 。
使用 importcert 命令导入 CA 的响应。
2 、导出证书
-exportcert[-v] [-rfc] [-protected]
[-alias < 别名 >] [-file < 认证文件 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
从 keystore 中读取与别名关联的证书,存储到证书文件中。如未指定文件名,则输出到 stdout 。
默认输出证书的二进制编码,但如果指定 -rfc 选项,则以 internet RFC 1421 标准定义的可打印的编码格式输出。
在以前的版本中,此命令名称为 -export 。
显示数据
1 、显示 keystore 内容
-list [-v | -rfc] [-protected]
[-alias < 别名 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
打印(到 stdout )别名标识的 keystore 条目内容,如未指定别名则打印 keystore 的全部内容。
此命令默认打印证书的 MD5 指纹。如果指定 -v 选项,则以可读的格式输出,带有所有者、签发人、序列号等信息。如果指定 -rfc 选项,则以 internet RFC 1421 标准定义的可打印的编码格式输出。
不能同时指定 -v 和 -rfc 选项。
2 、打印证书
-printcert [-v] [-file < 认证文件 >]
读证书文件,以可读的格式打印其内容。如果未指定证书文件,则从 stdin 读取证书。
管理 keystore
1 、修改存储库口令
-storepasswd [-v] [-new < 新存储库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
2 、修改密钥库口令
-keypasswd [-v] [-alias < 别名 >]
[-keypass < 旧密钥库口令 >] [-new < 新密钥库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
修改指定别名的 private/secret key 密码。
3 、删除 keystore 项
-delete [-v] [-protected] -alias < 别名 >
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
从 keystore 中删除指定别名的项目。
4 、修改别名
-changealias [-v] [-protected] -alias < 别名 > -destalias < 目标别名 >
[-keypass < 密钥库口令 >]
[-keystore < 密钥库 >] [-storepass < 存储库口令 >]
[-storetype < 存储类型 >] [-providername < 名称 >]
[-providerclass < 提供方类名称 > [-providerarg < 参数 >]] ...
[-providerpath < 路径列表 >]
示例
创建 keystore ,生成 keypair
keytool -genkeypair -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US"
-alias mykey -keypass kpi135 -keystore C:\working\mykeystore
-storepass ab987c -validity 180
此命令在” C:\working ” 目录下创建了名为” mykeystore ”的存储库,并指定它的密码为” ab987c ”。使用默认的” DSA ”密钥生成算法创建密钥。使用 "SHA1withDSA" 签名算法创建自签名证书,证书中包含公钥和 distinguished name 信息。
也可使用如下的简短命令,这将使用选项的默认值,会提示用户输入其他必选项。
keytool –genkeypair
向证书认证机构请求签名的证书
如果证书是由认证机构( CA )签署的将更容易得到别人的信任。为了得到签名,首先应生成一个证书签名请求。
keytool -certreq -alias mykey -file MarkJ.csr
然后将文件” MarkJ.csr ”提交给 CA( 比如 VeriSign),CA 认证后,将返回他们认证的证书,认证您的公钥(在某些情况下,实际上将返回证书链,每一个都验证链中前一个证书的签名者的公钥)。
导入 CA 证书
需要使用证书链取代自签名证书,链中每个证书都验证前一个签名者的公钥,直到根 CA 。
在导入 CA 的证书回复前,需要 keystore 或 cacerts keystore 中存在一个或多个可信任证书。
1 )如果证书回复是一个证书链,仅需要证书链的顶层证书(” root ” CA 证书,验证 CA 的公钥)。
2 )如果证书回复是单一证书,你需要这个发行 CA 的证书,如果证书不是自签名的,还需要他的签名者的证书,等等,直到自签名的根 CA 证书。
cacerts keystore 文件中装有 5 个 VeriSign 根 CA 证书,因此可能不需要导入 VeriSign 证书作为你的 keystore 中的受信证书。但是如果你需要一个来自不同 CA 的签名证书,证书认证的 CA 的公钥也没有添加到 cacerts 中,你需要导入来自这个 CA 的证书作为受信证书。
来自 CA 的证书通常是自签名或被另一个 CA 签名(在这种情况下还需要证书验证 CA 的公钥)。假定 ABC 公司,是一个 CA ,你获得一个名为“ ABCCA.cer ”的文件,据称这是一个自签名证书,认证 CA 的公钥。
要非常小心,要确保证书是有效的才能将其作为可信任证书导入。首先要查看证书(使用 keytool – printcert 命令,或者不带 -noprompt 选项的 keytool -importcert 命令),确保显示的证书指纹符合预期值。你可以给发证书的人打电话,与他们给出的指纹比较。只有指纹相等时,才能保证证书没有在传输过程中被其他证书替换。
确认后,导入证书:
keytool -importcert -alias abc -file ABCCA.cer
导入 CA 证书回复
keytool -importcert -trustcacerts -file VSMarkJ.cer
导入 CA 证书回复,取代你的证书链中的自签名证书。
导出证书
keytool -exportcert -alias mykey -file MJ.cer
导入 keystore
全部导入
keytool –importkeystore -srckeystore key.jks -destkeystore NONE
-srcstoretype JKS -deststoretype PKCS11
-srcstorepass changeit -deststorepass topsecret
导入一项
keytool -importkeystore
-srckeystore key.jks -destkeystore NONE
-srcstoretype JKS -deststoretype PKCS11
-srcstorepass changeit -deststorepass topsecret
-srcalias myprivatekey -destalias myoldprivatekey
-srckeypass oldkeypass -destkeypass mynewkeypass
-noprompt