使用新密钥对创建临时 SSL / TLS 套接字

问题描述 投票:0回答:2

我找到的每个教程都解释了如何在使用 keytool 实用程序手动创建 SSL 证书后,使用密钥库文件和信任库来存储 SSL 证书,从而创建与

SSLSocket
的 SSL/TLS 连接。

我很想知道如何做同样的事情,但使用动态生成的公钥/证书(短暂的)。

在 Java 中创建 RSA/EC 密钥对是如此简单,那么为什么我们不能将它也用于

SSLSocket
呢?在我看来,这有两大优点:它允许前向保密,同时我不必处理 Android 的密码、实用程序、文件读取器和密钥库转换器。

java ssl cryptography ssl-certificate
2个回答
3
投票

我认为这有两大优点:它允许前向保密

前向保密通常涉及 ECDHE 或 DHE 等密钥协议(尽管后者现在由于僵局而被广泛弃用)。

不时地重新生成证书密钥是一个很好的做法,尽管没有必要为每个 TLS 会话都创建一个新证书。

在 Java 中创建 RSA/EC 密钥对是如此简单,为什么我们不能将它也用于 SSLSocket?

您还需要 X509 证书,而不仅仅是密钥。您仍然可以即时制作这些,但您必须签署证书。证书要么是自签名的,要么您需要一个可以根据需要非常快速地签署证书的证书颁发机构。实际上,后者并不存在,并且意味着握手速度非常慢。

如果证书是自签名的,浏览器或任何其他用户代理将不知道如何信任该证书,并且使用自签名证书会严重影响 TLS 的使用。


2
投票
作为技术上正确但相当无用的替代方案:

TLS 实际上定义了“匿名”密钥交换方法

DH_anonECDH_anon (以及使用它们的密码套件),它们使用临时密钥对进行前向秘密密钥协商,并且不需要身份验证,因此不需要服务器上的任何证书或密钥库或(可能)客户端上的信任库。

未经身份验证,它们很容易受到主动攻击,因此真正想要安全的人们(和当局)认为它们不可接受使用。 Java(JSSE)确实实现了它们,但默认情况下不启用它们;您的代码必须使用适当修改或设置的列表来调用

.setEnabledCiphers

。大多数其他 SSL/TLS 实现要么类似地禁用它们,要么根本不实现它们。

但从技术上讲,这是一种无需长期密钥和证书即可执行 TLS 的有效方法,因此无需手动管理它们。

顺便说一句,我

相信这就是为什么创建一个 (SSLContext

 and) 
SSLSocketFactory
 with (
KeyManager
 for) 不包含有效 privateKeyEntry 的密钥库不会给出错误,因为原则上它可以创建套接字(或引擎)用于匿名连接。相反,由于实际上从未使用匿名密钥交换,因此这些工厂会导致所有后续连接失败,许多非专业程序员都难以诊断。 (相反,尝试为空信任库创建验证器会引发特定异常,例如“信任锚集不得为空”。)

更新: 2018 年晚些时候,TLS 1.3 删除了此选项,始终要求使用证书或预共享密钥 (PSK) 进行服务器身份验证,并且 Java/JSSE 不实现用户可配置的 PSK。 (1.3 还使用使用自动配置的临时 PSK 的前向保密版本替换了以前的会话恢复方法,JSSE 确实实现了这一点。)尽管 1.0 和 1.1(如早期的 SSL2 和 SSL3),2023 年的 OTOH 1.2 仍然被广泛实施和大量使用)已被许多当局禁止并基本上消失了。

© www.soinside.com 2019 - 2024. All rights reserved.