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

但是我收到以下错误:

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

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

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

]

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

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

private final static int KU_SIGNATURE = 0;

...

private void checkTLSServer(X509Certificate cert, String parameter)

throws CertificateException {

Set 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);

}

}

...

}

和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];

}

它失败了(keyUsage.length> bit)&&的keyUsage [比特];

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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐