Java SSL 选择错误的证书,忽略 key 用法

标签 java ssl certificate

我有一个使用 SSL 进行通信的客户端/服务器。

客户端中的 keystore JKS 包含两个 具有不同 key 用途的证书。证书 1 用于 SSL 通信,证书 2 用于签名数据:

  1. 一个证书具有 KU=keyEncipherment,digitalSignature, EKU=clientAuth
  2. 一个证书具有 KU=nonRepudiation,digitalSignature

当我运行它时,它选择第一个(正确!)。如果我从 JKS 中删除第一个证书,它会在连接到服务器时选择带有 nonRepudiation 的证书(错误!?)。

这对我来说毫无意义,因为 nonRep 永远不应该像那样使用。

那么,我该如何解决这个问题,如何使 Java SSL 仅选择具有合理 key 使用的证书?

顺便说一句,Windows 上的 JDK1.70_21。我使用的代码是标准的代码。只是获取默认的 key 管理器等

最佳答案

首先,您的第二个证书可能具有 nonRepudiation key 使用扩展,但据我所知,这并不会使它对于客户端证书使用无效。 TLS 规范并没有真正说明客户端 key 的使用情况,尽管从技术上讲,它使用数字签名(因此您的两个证书都可能有效)。假设确实需要 digitalSignature (据我所知,这在实践中),您的两个证书都有它,所以您的两个证书都是合适的。事实上,还有其他关键用途是另一回事。

此外,clientAuth 不是 key 使用扩展,而是扩展 key 使用扩展(或 Netscape 扩展)。您的第二个证书缺少任何扩展 key 使用扩展,因此可以保留任何扩展 key 使用。

其次,JSSE 中默认 X509KeyManager 实现的作者选择在缺少完美匹配时返回不完美匹配。请参阅code comments :

/*
* Return the best alias that fits the given parameters.
* The algorithm we use is:
* . scan through all the aliases in all builders in order
* . as soon as we find a perfect match, return
* (i.e. a match with a cert that has appropriate key usage
* and is not expired).
* . if we do not find a perfect match, keep looping and remember
* the imperfect matches
* . at the end, sort the imperfect matches. we prefer expired certs
* with appropriate key usage to certs with the wrong key usage.
* return the first one of them.
*/
private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,

因此,当带有 keyEncipherment,digitalSignature,clientAuth 的证书丢失时,它将依赖于另一个证书。

这是一个有争议的选择,但不一定是坏选择。有些实现和部署不一定 100% 标准兼容,而且无论您的 CA 给您什么,都可以方便地发送某些内容。归根结底,这并不是一个巨大的风险,因为 (a) 实际上由您来选择在 keystore 中放入的内容,以及 (b) 由服务器来检查所有情况下的 key 使用情况。

将您不想用于 SSL/TLS 的证书放入您使用 javax.net.ssl.keyStore 属性设置的 keystore 中,或者构建一个证书,这似乎很奇怪一个 SSLContext 及其。

我不确定为什么要将其放入此 keystore 中,但如果您需要其他证书可用于应用程序中的其他内容,通常将其放入不同的 keystore 中会更容易。

或者,您可以实现自己的 X509KeyManager 并根据需要重写其 chooseClientAlias 方法。在这种情况下,我将创建一个类,将所有调用委托(delegate)给默认的 X509KeyManager (使用默认算法从 KeyManagerFactory 获取并使用您的 keystore 初始化),除了 chooseClientAlias 您可以在返回别名之前检查 key 使用类型。这当然是可行的,但比使用两个 keystore 要多一些工作。

供引用:

关于Java SSL 选择错误的证书,忽略 key 用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22691658/

相关文章:

java - 什么是 Javadoc 摘要片段?

java - OSGi:如何获取其他包的类加载器

java - 编译时强制 Jaxb 优先选择联合成员类型

java - 如何使用主机名 validator ?

ssl - curl 无法识别 subjectAltName

node.js - 如何在 Node 中使用客户端证书执行 HTTPS GET

node.js - P12 PFX NodeJS 请求

java - C# 中的 ByteBuffer.PutDouble 等价物

php - 多站点 Wordpress、SSL 和 htaccess 以将子文件夹用作根目录

iis - 如何获得经过验证的 SSL 证书