我有一个客户机/服务器,它使用SSL进行通信。
客户端中的keystore JKS包含两个具有不同密钥用法的证书。Cert 1用于SSL通信,cert 2用于签名数据:
KU=keyEncipherment,digitalSignature, EKU=clientAuthKU=nonRepudiation,digitalSignature当我用这个运行时,它会选择第一个(正确!)。如果我从JKS中删除第一个证书,它会在连接到服务器时使用nonRepudiation选择证书(错误!?)。
这对我来说毫无意义,因为nonRep永远不应该像afaik那样使用。
那么,我能做些什么来解决这个问题呢?我如何使Java只挑选具有正常密钥使用的证书呢?
顺便说一句,JDK1.70_21在Windows上。我使用的代码是标准的。仅获得默认密钥管理器等
发布于 2014-03-27 17:53:47
首先,您的第二个证书可能有nonRepudiation密钥使用扩展,但据我所知,这并不意味着它对客户端证书的使用无效。TLS规范实际上并没有提到客户端的密钥使用,尽管从技术上讲,它使用的是数字签名(因此您的两个证书都是有效的)。假设digitalSignature确实是必需的(据我所知,它实际上是这样的),您的证书都有它,所以您的证书都是合适的。一个人也有其他的关键用法,这是另一回事。
此外,clientAuth不是密钥使用扩展,而是扩展的密钥使用扩展(或Netscape扩展)。您的第二个证书没有任何扩展的密钥使用扩展,因此可以使用任何扩展的密钥。
其次,JSSE中默认X509KeyManager实现的作者选择在缺少完美匹配时返回不完美匹配。请参阅代码注释
/*
* 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)在所有情况下都由服务器来检查密钥的使用情况。
在使用javax.net.ssl.keyStore属性设置的密钥存储库中放置一个您不希望用于SSL/TLS使用的证书,或者使用它构建SSLContext,这似乎很奇怪。
我不知道为什么要把它放在这个密钥存储库中,但是如果您需要另一个证书才能用于应用程序中的其他东西,通常将它放在不同的密钥库中比较容易。
或者,您可以实现自己的X509KeyManager,并根据需要重写它的chooseClientAlias方法。在本例中,我将创建一个类,该类委托对默认X509KeyManager的所有调用(使用默认算法从KeyManagerFactory获得,并使用密钥存储库初始化),但chooseClientAlias除外,在返回别名之前,您将检查密钥使用类型。这当然是可行的,但比使用两个密钥存储库的工作要多一些。
供参考:
https://stackoverflow.com/questions/22691658
复制相似问题