SSL和公钥安全性

时间:2011-10-31 02:04:05

标签: ssl ssl-certificate

我正在使用带有SSL的HTTP从Android设备上使用Web服务。自签名(不受信任)证书用于客户端身份验证

我对如何将公钥/私钥用于SSL有一般性的了解。根据我的理解,我可以清楚地看到如何使用证书来建立安全连接并安全地传输数据。但是我不明白它们是如何用于客户端身份验证的,因为证书包含公钥并且不保密。

我有几个问题:

我在哪里可以阅读有关SSL和证书如何用于客户端身份验证的信息?

即使证书未公开......通过访问浏览器中的HTTPS URL,我可以查看并保存证书。然后,我可以将证书打包到密钥库中,并从应用程序中使用它。

this post Jeremy Huiskamp写道

  

客户端身份验证将在服务器请求时自动执行   它

...因此可以使用证书执行客户端身份验证和数据加密吗?

编辑回答我的问题的第一部分:客户端密钥库不仅应包含服务器的公钥,还应包含客户端的私钥。然后服务器必须能够使用客户端的公钥解密?这是否意味着密钥库应该有两个证书?

2 个答案:

答案 0 :(得分:10)

首先,快速了解公钥加密术语:

  • 使用私钥进行签名和解密/解密,
  • 使用公钥验证(签名)和加密/加密。

(你并没有真正使用公钥“解密”。)

使用带有或不带客户端身份验证的SSL / TLS,服务器会提供一个证书(*),并为其提供私钥。服务器在SSL / TLS握手期间(在连接开始时)发送其证书,并且能够解密客户端使用其私钥(它保持私有)发送的内容。私钥和证书存储在服务器的密钥库中(如果未在Java中实现,则存储在等效密钥库中)。

作为其中一部分,客户端使用其 truststore (一种包含可信证书的密钥库的形式)来验证服务器证书。服务器证书可以通过显式位于信任库中来信任,或者在大多数情况下通过链接到信任库(PKI)中的可信CA证书来信任。

Java中密钥库和信任库之间的术语可能有点令人困惑,您可以找到更多details in this answer

关于您的问题,客户端的信任库不包含服务器的公钥,而是包含其证书或可以验证的CA证书。 (这不仅仅是拥有公钥,而是知道它的位置,使用证书中的其他信息。)

除此之外使用客户端证书身份验证时,服务器端还有一个信任库(或等效服务器),客户端也有一个密钥库,因为为此目的,角色是相反的。

在使用客户端身份验证的SSL / TLS握手中,服务器从发送它的客户端请求证书(如果可用)。

在握手结束时,客户端发送一条CertificateVerify消息,该消息使用客户端证书私钥对客户端和服务器之间到目前为止交换的所有消息进行签名(因此这是两者都知道的)。然后,服务器能够根据作为此交换的一部分获得的客户端证书中的公钥来验证此签名。这向服务器证明,客户端的任何人都拥有与其发送的证书中的公钥对应的私钥。

服务器的下一步是验证是否信任该证书,即是否信任身份和公钥之间的绑定,如证书中所示和“密封”。 这通常使用PKI完成,您可以根据已知的CA检查证书,或者如果您的部署环境足够小,则针对一组固定的可信证书。 (可能有alternative methods of verification,但它们的可用性实际上取决于您要部署此系统的情况。)

因此,对于你的第二个问题:

  • 客户端密钥库应至少包含客户端的证书及其私钥。
  • 客户端信任库应包含服务器证书或可用于验证服务器证书的CA证书。

由于密钥库和信任库都是用于不同目的的密钥库(在存储格式意义上,通常是文件),因此通常可以使用相同的密钥库来同时满足密钥库和信任库的目的。

(*)有些密码套件不依赖于证书,但对于这个问题来说这是不寻常的和偏离主题的。

答案 1 :(得分:3)

证书只是将身份绑定到公钥。这种绑定不是秘密,因此不需要保密证书。如果我有John Smith的证书,我可以证明John Smith拥有对应于特定公钥的密钥。但由于我不知道这个密钥,证书对我没用。

当通过证书进行身份验证时,一步始终是让出示证书的人证明他们知道证书中与公钥对应的密钥。如果您无法通过该步骤,则身份验证将失败。

服务器的密钥库应该具有服务器的证书。客户端的密钥库应该具有客户端的证书。客户端将其证书提供给服务器,因此服务器将以这种方式学习客户端的公钥。 (反之亦然。)