Java平台安全:密钥库与证书管理全解析
1. 密钥库类型与实现
在Java平台中,可以使用
KeyStore
类的
getInstance
方法,从不同的提供者处选择各种类型的密钥库实现。密钥库类型决定了其存储和数据格式,以及用于保护私钥和确保密钥库完整性的算法。以下是关于密钥库类型的一些要点:
-
类型不区分大小写
:例如,”jks”和”JKS”被视为相同的类型。
-
默认实现
:SDK默认的密钥库实现使用名为JKS的专有类型。
-
不同类型的兼容性
:不同类型的密钥库实现在实现细节(如格式)上不一定兼容。
对于
keytool
和
jarsigner
工具,可以在命令行通过
-storetype
选项指定密钥库类型。若未明确指定,工具会根据
keystore.type
安全属性的值选择密钥库实现。例如,若有一个提供名为
pkcs12
密钥库类型实现的提供者包,可以在安全属性文件中添加以下行来指定该类型:
keystore.type=pkcs12
每个工具获取
keystore.type
的值后,会检查所有提供者,直到找到实现该类型密钥库的提供者,并使用其
KeyStore
实现。
KeyStore
类定义了一个静态方法
getDefaultType
,可让程序获取
keystore.type
属性的值。以下代码创建一个处理默认密钥库类型的
KeyStore
实例:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
2. keytool工具概述
keytool
是一个实用工具,用于创建X.509证书链以验证相应的公钥,还能管理来自可信实体的证书。它可以显示、导入和导出存储为文件的X.509 v1、v2和v3证书,并生成新的自签名v1证书。尽管底层证书包支持X.509 v3格式,但由于处理各种扩展和选项的命令行复杂性,
keytool
通常只生成X.509 v1格式的证书。
keytool
允许用户指定任何由已注册或配置的加密服务提供者提供的密钥对生成和签名算法。默认的密钥对生成算法是数字签名算法(DSA),DSA密钥的大小必须在512到1024位之间,且必须是64的倍数,任何算法的默认密钥大小为1024位。签名算法由底层私钥的算法决定,例如,若底层私钥为DSA类型,默认签名算法为
SHA1withDSA
;若为RSA类型,默认签名算法为
MD5withRSA
。
所有
keytool
选项名前都带有减号(-),选项可以按任意顺序排列。具体命令和命令选项的详细解释可参考在线SDK文档。
3. 生成密钥对
可以使用以下命令为指定实体生成密钥对(公钥和关联的私钥),并将生成的密钥条目分配别名:
keytool -genkey -dname "CN=Gary Ellison, OU=Java Software, O=Sun, L=Santa Clara, S=CA, C=US" -alias mark
注意:该命令必须在一行中输入。当
keytool
生成密钥对时,会在密钥库中创建一个密钥条目,并使用私钥和包含与私钥关联的公钥的证书填充该条目。该证书是自签名的,即使用证书中公钥对应的私钥为证书生成签名。
4. 证书签名请求和证书链
当
keytool
首次生成公/私钥对时,生成的密钥条目最初包含私钥和单个自签名证书。若证书由认证机构(CA)签名,则更有可能被他人信任。要获得这样的签名,首先需要通过
-certreq
命令生成证书签名请求(CSR),例如:
keytool -certreq -alias joe -file JoeJ.csr
此命令为别名为
joe
的实体创建一个CSR,并将请求放入名为
JoeJ.csr
的文件中。将该文件提交给CA(如VeriSign, Inc.),CA通常会离线验证请求者身份,然后返回一个或多个证书的回复。
收到CA的证书回复后,应导入该回复,自签名证书将被证书链替换。若回复包含多个证书(证书链),链的一端是终端实体证书,该证书与发送给CA的证书基本相同,但返回的证书已由CA签名,从而将证书的主题与被认证的公钥绑定。链中的下一个证书绑定CA的公钥,通常这是一个自签名证书,也是链中的最后一个证书。在其他情况下,CA可能会返回更长的证书链。
许多CA只返回颁发的证书,没有支持链,尤其是在层次结构扁平(即没有中间CA)的情况下。在这种情况下,必须建立替换原始自签名证书的证书链。
5. 导入证书
可以使用
-import
命令导入证书,指定包含要导入的证书的文件名。以下是一个示例导入命令:
keytool -import -alias joe -file jcertfile.cer
此命令导入
jcertfile.cer
文件中的证书,并将其存储在别名为
joe
的密钥库条目中。可以导入单个证书作为可信证书,也可以导入作为向CA提交CSR结果而收到的证书回复。导入的内容由
-alias
选项的值指示。若别名存在于数据库中且标识一个包含私钥的条目,则假定正在导入证书回复。在这种情况下,
keytool
实用工具会检查证书回复中的公钥是否与别名存储的公钥匹配。若别名标识一个现有的可信证书条目,则不会导入新证书。否则,将创建一个具有指定别名的新可信证书条目,并与新导入的可信证书关联。
在将证书作为可信证书条目导入密钥库之前,应确保其真实性。例如,可以执行
-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 Sep 25 18:01:13 PDT 2002 until Wed Dec 24 17:01:13 PST 2002
Certificate Fingerprints:
MD5: 11:81:AD:92:C8:E5:0E:A2:01:2E:D4:7A:D7:5F:07:6F
SHA1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE
实际上,在将证书导入密钥库的可信证书列表之前,
keytool
会打印出证书信息并提示验证。可以通过将显示的证书指纹与从另一个可信信息源获得的指纹进行比较来完成验证,然后选择接受该证书为可信证书或中止导入操作。
导入证书回复时,会使用密钥库中的可信证书以及(可选)
cacerts
文件中配置的证书(若在
-import
命令中指定了
-trustcacerts
选项)来验证证书回复。以下是包含
-trustcacerts
选项的示例导入命令:
keytool -import -trustcacerts -alias joe -file jcertfile.cer
6. cacerts证书文件
cacerts
证书文件位于安全属性目录中:
- 在Solaris和Linux系统中:
<java.home>/lib/security
- 在Win32系统中:
<java.home>\lib\security
其中,
<java.home>
指的是Java 2运行时环境的安装目录。
cacerts
文件代表一个包含CA证书的系统范围的密钥库。系统管理员可以使用
keytool
管理该文件,指定JKS作为密钥库类型。
cacerts
密钥库文件附带了几个最受信任的CA证书,包括VeriSign和Thawte的证书。该文件的初始密码是
changeit
,系统管理员应在安装SDK时更改该密码和文件的默认访问权限。
7. 导出证书
要将证书导出到文件,可以使用
-export
命令,例如:
keytool -export -alias jane -file janecertfile.cer
此命令将别名
jane
的证书导出到
janecertfile.cer
文件。默认情况下,该命令输出二进制编码的证书,但如果使用
rfc
选项,则会输出Base64编码的证书。
8. 打印密钥库内容
要打印密钥库条目的内容,可以使用
-list
命令,例如:
keytool -list -alias joe
若未指定别名,则会打印整个密钥库的内容。该命令默认打印证书的MD5指纹。若指定
-verbose
选项,则会以人类可读的格式打印证书。
9. 帮助命令
以下命令可输出帮助信息:
keytool
keytool -help
10. keytool选项的默认值
keytool
实用工具具有以下内置默认值:
| 选项 | 默认值 |
| ---- | ---- |
|
-alias
|
mykey
|
|
-keyalg
|
DSA
|
|
-keysize
|
1024
|
|
-validity
|
90
|
|
-keystore
| 用户主目录中名为
.keystore
的文件 |
|
-file
| 读取时为
stdin
,写入时为
stdout
|
11. keytool使用示例
以下是创建和管理包含公/私钥对以及来自可信实体证书的密钥库的示例:
keytool -genkey -dname "cn=Mark Smith, ou=Accounting, o=Sun, c=US" -alias business -keypass kpi135 -keystore /working/mykeystore -storepass ab987c -validity 180
此命令在
/working
目录中创建
mykeystore
密钥库(若不存在),并为其分配密码
ab987c
。它为DN为
cn=Mark Smith, ou=Accounting, o=Sun, c=US
的实体生成公/私钥对,使用默认的DSA密钥生成算法创建1024位长的密钥。该命令使用默认的
SHA1withDSA
签名算法创建自签名证书,证书包含公钥和DN信息,有效期为180天。证书与别名为
business
的密钥库条目中的私钥关联,私钥分配密码
kpi135
。
若接受更多选项的默认值,命令可以显著缩短,因为会提示输入未指定且无默认值的任何必需值。例如,可以简单地输入:
keytool -genkey
这样会使用或创建用户主目录中名为
.keystore
的密钥库(若不存在),并创建一个别名
mykey
的条目,包含新生成的密钥对和有效期为90天的证书。
到目前为止,生成的只是自签名证书。若希望证书更受他人信任,可以生成CSR并提交给CA。例如:
keytool -certreq -file MarkS.csr
此命令为默认别名
mykey
标识的实体创建CSR,并将请求放入
MarkS.csr
文件中。将该文件提交给CA,CA会验证请求者身份并返回签名的证书,在某些情况下会返回证书链。
在导入CA的证书回复之前,可能需要在密钥库或
cacerts
密钥库中准备一个或多个可信证书。确定所需证书的方法如下:
-
证书回复为证书链
:只需要链的顶级证书,即验证该CA公钥的最受信任的CA证书。
-
证书回复为单个证书
:需要颁发该证书的CA的证书;若颁发证书不是自签名的,还需要其签名者的证书,以此类推,直到最受信任的CA的自签名证书。
默认的JRE中的
cacerts
文件附带了许多VeriSign和Thawte根CA证书,因此通常不需要将这些证书作为可信证书导入。但如果请求来自不同CA的签名证书,且密钥库中不包含验证该CA公钥的证书,则需要从该CA导入可信证书。例如,假设公司ABC是一个CA,获得了一个包含ABC自签名证书的文件
ABCCA.cer
,在将其作为可信证书导入之前,应仔细确保证书的有效性,可以执行以下命令查看其指纹:
keytool -printcert -file ABCCA.cer
若信任该证书有效,可以使用以下命令将其添加到密钥库:
keytool -import -alias abc -file ABCCA.cer
此命令在密钥库中创建一个可信证书条目,使用
ABCCA.cer
文件中的数据,并为该条目分配别名
abc
。
一旦导入了验证向其提交CSR的CA公钥的证书,或者该证书已存在于密钥库或
cacerts
文件中,就可以导入证书回复,从而用证书链替换自签名证书。例如,假设将CSR发送给VeriSign,返回的证书名为
VSMarkS.cer
,可以使用以下命令导入回复:
keytool -import -trustcacerts -file VSMarkS.cer
-trustcacerts
选项表示导入命令在搜索验证VeriSign公钥的证书时可以搜索
cacerts
文件。
假设使用
jarsigner
工具对JAR文件进行了签名,想要使用该文件的客户端需要验证签名。一种方法是先将公钥证书作为“可信”条目导入其密钥库。可以使用以下命令将证书复制到
MS.cer
文件并提供给客户端:
keytool -export -alias mykey -file MS.cer
客户端使用该证书和签名的JAR文件,就可以使用
jarsigner
工具验证签名。
如果DN发生更改(例如,换了部门或搬到了另一个城市),可以在更新DN的同时继续使用相同的公/私钥。例如,假设名为Susan Miller,最初使用别名
sMiller
和DN
"cn=Susan Miller, ou=Finance Department, o=BlueSoft, c=us"
创建了密钥条目。若后来从财务部门转到了会计部门,可以按以下步骤更新DN:
1. 复制或克隆密钥条目:
keytool -keyclone -alias sMiller -dest sMillerNew
此命令会提示输入
storepass
密码以及初始和目标私钥密码,因为这些密码未在命令行中提供。
通过以上步骤,就可以全面管理Java平台中的密钥库和证书,确保系统的安全性和数据的完整性。在实际应用中,应根据具体需求和安全要求,合理使用
keytool
工具的各项功能。
Java平台安全:密钥库与证书管理全解析
11. keytool使用示例(续)
在上述示例中,我们已经了解了如何创建和管理密钥库、生成密钥对、处理证书签名请求以及导入和导出证书等操作。接下来,我们将进一步深入探讨一些实际场景和相关注意事项。
11.1 多证书链处理
当从CA收到的证书回复是一个证书链时,
keytool
会自动处理该链并构建信任关系。假设我们收到的证书链包含多个中间CA证书和最终的终端实体证书。在导入证书链时,
keytool
会验证每个证书的签名,并尝试建立从终端实体证书到最受信任的CA证书的信任链。
keytool -import -trustcacerts -file chain.cer
在这个例子中,
chain.cer
文件包含了完整的证书链。
-trustcacerts
选项允许
keytool
在
cacerts
文件中查找可信的CA证书,以帮助建立信任链。如果在
cacerts
文件或本地密钥库中找到了与链中某个CA证书匹配的可信证书,
keytool
会自动验证证书链的完整性。
11.2 证书更新与替换
随着时间的推移,证书可能会过期或需要更新。当证书过期时,我们需要重新生成证书签名请求并从CA获取新的证书。假设我们之前使用别名
mykey
生成了一个证书,现在该证书即将过期,我们可以按照以下步骤更新证书:
- 生成新的证书签名请求:
keytool -certreq -alias mykey -file newRequest.csr
-
将
newRequest.csr文件提交给CA,获取新的证书回复。 -
导入新的证书回复:
keytool -import -trustcacerts -alias mykey -file newCert.cer
通过这些步骤,我们可以用新的证书替换旧的证书,确保系统的安全性。
11.3 密钥库备份与恢复
为了防止数据丢失,定期备份密钥库是非常重要的。可以简单地复制密钥库文件到安全的位置进行备份。例如,假设我们的密钥库文件是
/working/mykeystore
,可以使用以下命令进行备份:
cp /working/mykeystore /backup/mykeystore_backup
在需要恢复密钥库时,只需将备份文件复制回原来的位置即可:
cp /backup/mykeystore_backup /working/mykeystore
需要注意的是,在恢复密钥库时,要确保使用正确的密码访问密钥库。
12. 密钥库和证书管理的最佳实践
在实际应用中,遵循一些最佳实践可以提高系统的安全性和可靠性。以下是一些建议:
12.1 定期更新证书
证书有有效期限制,过期的证书可能会导致系统出现安全问题。因此,应定期检查证书的有效期,并在证书即将过期时及时更新。可以设置提醒机制,确保不会错过证书更新的时间。
12.2 保护密钥库密码
密钥库密码是访问密钥库的重要凭证,应妥善保管。避免使用简单的密码,并定期更换密码。同时,不要将密码明文存储在代码或配置文件中,可以使用加密方式存储密码。
12.3 验证证书真实性
在导入证书之前,一定要验证证书的真实性。可以通过比较证书指纹、检查证书的颁发机构等方式进行验证。不要轻易信任来源不明的证书,以免遭受中间人攻击。
12.4 合理使用
cacerts
文件
cacerts
文件包含了系统信任的CA证书,应谨慎管理该文件。不要随意添加或删除其中的证书,以免影响系统的信任关系。如果需要使用自定义的CA证书,可以将其导入到本地密钥库中。
13. 总结
Java平台中的密钥库和证书管理是确保系统安全的重要组成部分。通过
keytool
工具,我们可以方便地创建和管理密钥库、生成密钥对、处理证书签名请求、导入和导出证书等。在实际应用中,我们需要根据具体需求和安全要求,合理使用
keytool
的各项功能,并遵循最佳实践,以确保系统的安全性和可靠性。
以下是一个简单的流程图,总结了使用
keytool
进行密钥库和证书管理的主要流程:
graph LR
A[创建密钥库和生成密钥对] --> B[生成证书签名请求]
B --> C[提交请求到CA]
C --> D[接收CA证书回复]
D --> E[导入证书回复]
E --> F[导出证书]
F --> G[客户端验证签名]
A --> H[更新DN]
H --> I[复制或克隆密钥条目]
在这个流程图中,我们可以看到从创建密钥库到最终客户端验证签名的整个过程。同时,也展示了如何处理DN更新的情况。
通过本文的介绍,相信你已经对Java平台中的密钥库和证书管理有了更深入的了解。在实际项目中,根据具体情况灵活运用这些知识,将有助于提高系统的安全性和稳定性。
超级会员免费看
1965

被折叠的 条评论
为什么被折叠?



