java KeyUsage 不允许数字签名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15355031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:20:10  来源:igfitidea点击:

KeyUsage does not allow digital signatures

javasslx509certificatedigital-signature

提问by chaplean

I'm trying to send HTTPS request from my Java EE program to the host that requires certificate authentication. I have a proper keystore file, truststore with imported CA, the listing of both shows that certificates are inside.

我正在尝试将 HTTPS 请求从我的 Java EE 程序发送到需要证书身份验证的主机。我有一个正确的密钥库文件,带有导入 CA 的信任库,两者的列表都显示证书在里面。

But I receive the following error:

但我收到以下错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: KeyUsage does not allow digital signatures
    at ...

...

Caused by: sun.security.validator.ValidatorException: KeyUsage does not allow digital signatures
    at sun.security.validator.EndEntityChecker.checkTLSServer(EndEntityChecker.java:270)
    at sun.security.validator.EndEntityChecker.check(EndEntityChecker.java:141)
    at sun.security.validator.Validator.validate(Validator.java:264)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
    at     sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1319)
... 29 more

Viewing the certificate contents in the part of Extensions I see the following:

查看扩展部分中的证书内容,我看到以下内容:

Extensions:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 33 87 72 1D 09 2F DF FF   1A A7 D1 C0 E1 CF C5 FA  3.r../..........
0010: A4 19 54 2E                                        ..T.
]
]

#2: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
   SSL client
]

#3: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 74 9F 43 07 CC 75 FA D3   D0 13 0F 65 36 CC 4A 9A  t.C..u.....e6.J.
0010: E0 8E 9C 52                                        ...R
]
]

#4: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
  [DistributionPoint:
     [URIName: http://test.az:7447/Test%20CA.crl]
]]

#5: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
]

So my certificate does contain KeyUsage [ DigitalSignature ]

所以我的证书确实包含KeyUsage [ DigitalSignature ]

The code snippet of the place throwing the exception looks like the following:

抛出异常的地方的代码片段如下所示:

private final static int KU_SIGNATURE = 0;

...

private void checkTLSServer(X509Certificate cert, String parameter)
        throws CertificateException {
    Set<String> exts = getCriticalExtensions(cert);

    ...

    } else if (KU_SERVER_SIGNATURE.contains(parameter)) {
        if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
            throw new ValidatorException
                    ("KeyUsage does not allow digital signatures",
                    ValidatorException.T_EE_EXTENSIONS, cert);
        }
    }

    ...
}

and checkKeyUsagefunction:

checkKeyUsage函数:

private boolean checkKeyUsage(X509Certificate cert, int bit)
        throws CertificateException {
    boolean[] keyUsage = cert.getKeyUsage();
    if (keyUsage == null) {
        return true;
    }
    return (keyUsage.length > bit) && keyUsage[bit];
}

it fails in return (keyUsage.length > bit) && keyUsage[bit];

返回失败(keyUsage.length > bit) && keyUsage[bit];

The question is why the result of above expression = false? When bit = 0 and cert.getKeyUsage() must return an array of boolean [true, false, false, false, false, false, false, false, false]

问题是为什么上面表达式的结果= false?当 bit = 0 并且 cert.getKeyUsage() 必须返回一个布尔数组 [true, false, false, false, false, false, false, false, false]

回答by Chris D

The error actually comes from verifying the server's certificate. That certificate has a key usage section that doesn't include a digitalSignature bit.

该错误实际上来自验证服务器的证书。该证书有一个不包含 digitalSignature 位的密钥使用部分。

Some cipher suites require the digital signature bit, specifically Diffie-Hellman key exchange (DHE_RSA and ECDHE_RSA). You may be able to avoid this error by avoiding those cipher types. Otherwise the server certificate needs to support it.

一些密码套件需要数字签名位,特别是 Diffie-Hellman 密钥交换(DHE_RSA 和 ECDHE_RSA)。您可以通过避免这些密码类型来避免此错误。否则服务器证书需要支持它。