信任服务器上所有客户端证书的ssl安全含义(Java X509TrustManager)
在本网站和其他网站上,通常建议使用自定义的“空”X509TrustManager
实现(即信任所有证书的实现,例如此答案:https://stackoverflow.com/a/54358567或此答案中的“选项2:https://stackoverflow.com/a/2893932)。人们(正确地)批评这是不安全和危险的建议。这通常用于客户端信任任何服务器证书
我想知道,对于信任任何客户端证书的服务器而言,这种做法是否一定是不安全的(假设所述证书随后根据受信任证书列表单独检查)
上下文:我正在尝试创建一个基本的Gemini服务器(https://gemini.circumlunar.space/docs/specification.gmi)。提供的大多数页面都不需要客户端证书,但如果客户端提供随机证书,我不希望TLS握手失败。某些页面(例如,管理员的日志查看器)可能需要特定的客户端证书(例如,使用存储在服务器上硬编码文件路径的公钥)。其他页面可能希望信任证书的动态列表(例如,来自注册用户数据库)
如果我创建一个信任所有客户端证书的自定义X509TrustManager
,并在我的SSLServerSocketFactory
中使用它:
- 由
clientSocket.getSession().getPeerCertificates()
返回的证书是否仍然根据其私钥进行了预验证(即,如果有人出示了管理员证书,但没有私钥,getPeerCertificates()
是否会返回空数组)李> - 将我的TrustManager中的
checkServerTrusted()
/getAcceptedIssuers()
方法保留为空/null是否存在任何风险?如果这个TrustManager只由我的服务器socket工厂使用,这些方法会被调用吗李> - 有没有更好的方法来实现我的目标李>
# 1 楼答案
与最初不请求客户端证书相比,请求但不验证客户端证书不会带来任何安全问题
使用客户端证书进行身份验证而不进行验证显然会增加问题,因为在这种情况下,攻击者可能会提供自制的证书。但是正如您所写的,稍后在接受is进行身份验证之前,客户机证书将在TLS握手之外进行检查(希望正确)。在这种情况下,不在握手时检查是完全安全的
即使证书验证已关闭,仍将验证客户端是否拥有提供的证书,即它是否具有匹配的私钥
checkServerTrusted
将被调用以检查服务器证书,即仅在客户端。所以这个函数并不重要。 我不确定getAcceptedIssuers
——可能是在将接受的CA列表发送给客户端时调用它。不过,这个列表是否为空并不重要