信任存储与密钥存储 - 使用 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.keyStoreTypejavax.net.ssl.trustStoreType 系统属性来使用不同类型的密钥库(例如PKCS12)。 @Donal:很好的补充。您是否碰巧知道是否有所有受支持容器的列表?我只知道PKCS12和JKS(前者是反复试验的结果......)。 密钥库格式因可用的提供程序而异(请参阅this list,了解默认情况下与 Oracle JRE 捆绑的那些)。 this question也有讨论。其他提供程序(例如 BouncyCastle)可用于其他格式。【参考方案2】:

术语确实有点混乱,但javax.net.ssl.keyStorejavax.net.ssl.trustStore 都用于指定要使用的密钥库,用于两种不同的目的。密钥库有多种格式,甚至不一定是文件(参见this question),keytool 只是对它们执行各种操作的工具(导入/导出/列表/...)。

javax.net.ssl.keyStorejavax.net.ssl.trustStore 参数是用于构建 KeyManagers 和 TrustManagers 的默认参数(分别),然后用于构建 SSLContext,它本质上包含要使用的 SSL/TLS 设置当通过 SSLSocketFactorySSLEngine 建立 SSL/TLS 连接时。这些系统属性正是默认值的来源,然后由SSLContext.getDefault() 使用,例如SSLSocketFactory.getDefault() 本身使用。 (如果您不想将默认值和特定的SSLContexts 用于给定目的,所有这些都可以通过 API 在许多地方进行自定义。)

KeyManagerTrustManager 之间的区别(以及javax.net.ssl.keyStorejavax.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密钥库中的证书?

Java安全(JCA/JSSE):数字证书

keytool常用操作

在 spring boot application.properties 中指定信任存储信息

信任库中信任哪些证书?