信任存储与密钥存储 - 使用 keytool 创建

2022-08-31 05:15:38

我知道密钥库通常保存私钥/公钥,而信任库只保存公钥(并表示您打算与之通信的受信任方的列表)。好吧,这是我的第一个假设,所以如果这是不正确的,我可能还没有很好地开始......

我有兴趣了解在使用keytool时如何/何时区分商店。

所以,到目前为止,我已经创建了一个密钥库,使用

keytool -import -alias bob -file bob.crt -keystore keystore.ks

这将创建我的密钥库.ks文件。我回答了我是否信任 bob 的问题,但我不清楚这是否创建了密钥库文件或信任库文件?我可以将我的应用程序设置为将该文件用作任一。yes

-Djavax.net.ssl.keyStore=keystore.ks -Djavax.net.ssl.keyStorePassword=x
-Djavax.net.ssl.trustStore=keystore.ks -Djavax.net.ssl.trustStorePassword=x

使用set,我可以在受信任的证书下看到证书(但不在密钥库部分下)。我正在导入的特定证书只有一个公钥,我打算使用它通过SSL连接将内容发送到Bob(但也许最好留给另一个问题!System.setProperty( "javax.net.debug", "ssl")

任何指示或澄清将不胜感激。keytool 的输出是否与您导入的任何内容相同,并且它只是约定说一个是密钥库,另一个是信任库?使用SSL等时有什么关系?


答案 1

这个术语确实有点令人困惑,但两者都用于指定使用哪些密钥库,用于两个不同的目的。密钥库有各种格式,甚至不一定是文件(请参阅此问题),只是对它们执行各种操作(导入/导出/列表/...)的工具。javax.net.ssl.keyStorejavax.net.ssl.trustStorekeytool

和 参数是用于构建 s 和 s(分别)的默认参数,然后用于构建一个本质上包含 SSL/TLS 设置的参数,以便在通过 或 建立 SSL/TLS 连接时使用。这些系统属性只是默认值的来源,然后由 本身使用,例如。(如果您不想将默认值和特定值用于给定目的,则可以通过API在多个位置进行自定义。javax.net.ssl.keyStorejavax.net.ssl.trustStoreKeyManagerTrustManagerSSLContextSSLSocketFactorySSLEngineSSLContext.getDefault()SSLSocketFactory.getDefault()SSLContext

和 之间的区别(以及 和 之间的区别)如下(引自 JSSE 参考指南):KeyManagerTrustManagerjavax.net.ssl.keyStorejavax.net.ssl.trustStore

信任管理器:确定是否应信任远程身份验证凭据(以及连接)。

密钥管理器:确定要发送到远程主机的身份验证凭据。

(其他参数可用,其默认值在 JSSE 参考指南中进行了描述。请注意,虽然信任存储区有默认值,但密钥存储区没有默认值。

从本质上讲,中的密钥库旨在包含您的私钥和证书,而密钥库旨在包含您在远程方提供其证书时愿意信任的 CA 证书。在某些情况下,它们可以是同一个存储,尽管使用不同的存储通常更好(特别是当它们基于文件时)。javax.net.ssl.keyStorejavax.net.ssl.trustStore


答案 2

以常见的用例/目的或外行方式解释:

信任存储 :用于存储受信任实体的证书。进程可以维护它信任的所有受信任方的证书存储。

keyStore :用于存储服务器密钥(公钥和私钥)以及签名证书。

在 SSL 握手期间,

  1. 客户端尝试访问 https://

  2. 因此,服务器通过提供SSL证书(存储在其密钥库中)来响应。

  3. 现在,客户端接收 SSL 证书并通过 trustStore 进行验证(即客户端的 trustStore 已经具有它信任的预定义证书集)。它就像:我可以信任这个服务器吗?这是否是我尝试与之通信的同一台服务器?没有中间人攻击?

  4. 一旦客户端验证它是否正在与它信任的服务器通信,那么SSL通信就可以通过共享密钥进行。

注意:我在这里不是在谈论服务器端客户端身份验证的任何内容。如果服务器也要执行客户端身份验证,则服务器还会维护一个 trustStore 来验证客户端。然后它成为相互TLS。