信任存储与密钥存储 - 使用 keytool 创建
Posted
技术标签:
【中文标题】信任存储与密钥存储 - 使用 keytool 创建【英文标题】:Trust Store vs Key Store - creating with keytool 【发布时间】:2011-09-14 12:24:50 【问题描述】:我了解密钥库通常会保存私钥/公钥,而信任库仅保存公钥(并代表您打算与之通信的受信任方的列表)。嗯,这是我的第一个假设,所以如果这不正确,我可能还没有很好地开始......
我有兴趣了解使用 keytool 时如何/何时区分商店。
到目前为止,我已经使用
创建了一个密钥库keytool -import -alias bob -file bob.crt -keystore keystore.ks
创建我的 keystore.ks 文件。我回答 yes
我是否信任 bob 的问题,但我不清楚这是否创建了密钥库文件或信任库文件?我可以将我的应用程序设置为使用该文件。
-Djavax.net.ssl.keyStore=keystore.ks -Djavax.net.ssl.keyStorePassword=x
-Djavax.net.ssl.trustStore=keystore.ks -Djavax.net.ssl.trustStorePassword=x
并且设置了System.setProperty( "javax.net.debug", "ssl")
,我可以在受信任的证书下看到证书(但不在密钥库部分下)。我要导入的特定证书只有一个公钥,我打算用它通过 SSL 连接向 Bob 发送内容(但也许最好留给另一个问题!)。
任何指示或澄清将不胜感激。无论您导入什么,keytool 的输出是否都相同,并且只是约定一个是密钥库,另一个是信任库?使用SSL等有什么关系?
【问题讨论】:
我不确定您所说的“我正在导入的特定证书只有一个公钥”是什么意思:它只是一个公钥(即不是证书)还是非 CA 证书? 嗯,不确定。我从浏览器导出为 PEM 文件。这有帮助吗? 如果是从浏览器导出的,可能是证书。它是服务器证书(CN 或 subjectAltName 与服务器名称匹配)吗?它是 CA 证书吗(在 Basic Constraints 下查看,您应该可以使用浏览器看到它)。 tl;dr: 信任存储包含公共的、受信任的根 (CA) 证书,而身份/密钥存储包含私有的身份证书;但是,就文件而言,它们是相同的。 技术上没有区别,只是将可信证书与服务器/客户端证书分开的一些逻辑和舒适性。 【参考方案1】:密钥库和信任库文件之间没有区别。两者都是专有 JKS 文件格式的文件。区别在于使用:据我所知,Java 在创建 SSL 连接时将仅使用 -Djavax.net.ssl.trustStore
系统属性引用的存储来查找要信任的证书。键和-Djavax.net.ssl.keyStore
相同。但理论上,对信任库和密钥库使用同一个文件是可以的。
【讨论】:
您可以通过设置javax.net.ssl.keyStoreType
和javax.net.ssl.trustStoreType
系统属性来使用不同类型的密钥库(例如PKCS12)。
@Donal:很好的补充。您是否碰巧知道是否有所有受支持容器的列表?我只知道PKCS12和JKS(前者是反复试验的结果......)。
密钥库格式因可用的提供程序而异(请参阅this list,了解默认情况下与 Oracle JRE 捆绑的那些)。 this question也有讨论。其他提供程序(例如 BouncyCastle)可用于其他格式。【参考方案2】:
术语确实有点混乱,但javax.net.ssl.keyStore
和javax.net.ssl.trustStore
都用于指定要使用的密钥库,用于两种不同的目的。密钥库有多种格式,甚至不一定是文件(参见this question),keytool
只是对它们执行各种操作的工具(导入/导出/列表/...)。
javax.net.ssl.keyStore
和 javax.net.ssl.trustStore
参数是用于构建 KeyManager
s 和 TrustManager
s 的默认参数(分别),然后用于构建 SSLContext
,它本质上包含要使用的 SSL/TLS 设置当通过 SSLSocketFactory
或 SSLEngine
建立 SSL/TLS 连接时。这些系统属性正是默认值的来源,然后由SSLContext.getDefault()
使用,例如SSLSocketFactory.getDefault()
本身使用。 (如果您不想将默认值和特定的SSLContext
s 用于给定目的,所有这些都可以通过 API 在许多地方进行自定义。)
KeyManager
和TrustManager
之间的区别(以及javax.net.ssl.keyStore
和javax.net.ssl.trustStore
之间的区别)如下(引自JSSE ref guide):
TrustManager:确定是否 远程身份验证凭据(和 因此连接)应该是 值得信赖。
KeyManager:确定哪个 要发送到的身份验证凭据 远程主机。
(其他参数可用,它们的默认值在JSSE ref guide 中描述。请注意,虽然信任库有默认值,但密钥库没有默认值。)
本质上,javax.net.ssl.keyStore
中的密钥库旨在包含您的私钥和证书,而javax.net.ssl.trustStore
旨在包含当远程方出示其证书时您愿意信任的 CA 证书。在某些情况下,它们可以是同一个存储,但使用不同存储通常更好(尤其是当它们基于文件时)。
【讨论】:
感谢您的回复,这让事情变得更清楚了。尽管在使用方面我仍然感到困惑,但我可以使用 pk12 pri/pub 密钥(xxx.p12)作为密钥库(通过 -D)并创建 SSL 连接(受信任)而不通过任何提及信任库 - D...哦,好吧。 您不需要指定信任库,因为它有一个默认值(它与 JRE 捆绑在一起),通常在$JAVA_HOME/lib/security/cacerts
中(请参阅我发送的第二个 JSSE 参考指南链接)。与浏览器一样,它包含一组默认的受信任 CA 证书。通常,客户端将始终使用信任库来检查服务器证书,但仅在服务器请求客户端证书时才使用密钥库,并且服务器将始终将密钥库用于自己的密钥+证书,但信任库仅用于客户端发送客户端证书时使用。
感谢您提供有用的信息。在Weblogic中,有“identity-key-store”存储服务器的SSL证书,然后有“trust-key-store”存储服务器信任的SSL证书,所以如果我说“identity-key”是正确的-store" 只不过是一个 "keystore" 和 "trust-key-store" 只不过是一个 "truststore" ?
@Bruno 我们还应该注意,当有 "jssecacerts" 时,会忽略 "cacerts" 吗?【参考方案3】:
Keystore 被服务器用来存储私钥,Truststore 被第三方客户端用来存储服务器提供的用于访问的公钥。我已经在我的生产应用程序中做到了这一点。以下是为 SSL 通信生成 java 证书的步骤:
-
在 windows 中使用 keygen 命令生成证书:
keytool -genkey -keystore server.keystore -alias mycert -keyalg RSA -keysize 2048 -validity 3950
-
自证证书:
keytool -selfcert -alias mycert -keystore server.keystore -validity 3950
-
将证书导出到文件夹:
keytool -export -alias mycert -keystore server.keystore -rfc -file mycert.cer
-
将证书导入客户端信任库:
keytool -importcert -alias mycert -file mycert.cer -keystore truststore
【讨论】:
嗨,我有一个场景,我在同一个容器(tomcat)中有两个不同的应用程序。从这两个应用程序中,我必须从双方调用其余端点到每个应用程序。比如,从 A 到 B 和 B 到 A(A 和 B 是两个应用程序)。在这种情况下我需要使用信任库吗?因为我正在使用正在使用密钥库的自定义休息客户端。请提出建议。【参考方案4】:keystore 只存储私钥,而 truststore 存储公钥。您需要为 SSL 通信生成一个 java 证书。您可以在 windows 中使用 keygen 命令,这可能是最简单的解决方案。
【讨论】:
信任库存储受信任的证书。 @user207421 可信证书 ** :)【参考方案5】:用常见用例/目的或外行方式解释:
TrustStore:用于存储证书 受信任的实体。一个进程可以维护所有受信任方的证书存储 它信任。
keyStore :用于存储服务器keys(公共和私有) 连同签署的证书。
在 SSL 握手期间,
客户端尝试访问 https://
因此,服务器通过提供 SSL 证书(存储在其 keyStore 中)来响应
现在,客户端接收 SSL 证书并通过 trustStore 对其进行验证(即客户端的 trustStore 已经具有它信任的预定义证书集。)。就像:我可以信任这台服务器吗?这是我要与之交谈的同一服务器吗?没有中间人攻击?
一旦客户端验证它正在与它信任的服务器通信,那么 SSL 通信就可以通过共享密钥进行。
注意:我在这里不是在谈论服务器端的客户端身份验证。如果服务器也想进行客户端身份验证,则服务器还维护一个 trustStore 来验证客户端。然后就变成了双向 TLS。
【讨论】:
太好了,举个例子就更容易理解了。谢谢!【参考方案6】:这些是使用 Keytool 在本地计算机中创建信任库的步骤。 在本地计算机中为 URL 创建信任库的步骤。
1) 使用 chrome 在浏览器中点击 url
2) 检查 chrome 中 url 左侧的 "i" 图标并单击它
3) 检查证书选项并单击它,将打开一个对话框
4) 检查“证书路径”选项卡,了解可用于创建信任库的证书数量
5) 转到您要创建的"details" tab -> click"Copy to File" -> Give the path and the name for the certificate
。
6) 检查是否有父证书并按照"5"点操作。
7) 创建所有证书后,打开命令提示符并导航到您创建证书的路径。
8) 提供以下 Keytool 命令来添加证书并创建信任库。
Sample:
keytool -import -alias abcdefg -file abcdefg.cer -keystore cacerts
where "abcdefg" is the alias name and "abcdefg.cer" is the actual certificate name and "cacerts" is the truststore name
9) 为所有证书提供 keytool 命令并将它们添加到信任库。
keytool -list -v -keystore cacerts
【讨论】:
以上是关于信任存储与密钥存储 - 使用 keytool 创建的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 keytool 列出存储在 PKCS12 密钥库中的证书?
如何使用keytool列出存储在PKCS12密钥库中的证书?