Я пытаюсь отправить HTTPS-запрос из моей программы Java EE на хост, для которого требуется аутентификация сертификата. У меня есть правильный файл хранилища ключей, truststore с импортированным CA, список обоих показывает, что сертификаты находятся внутри.KeyUsage не разрешает цифровые подписи
Но я получаю следующее сообщение об ошибке:
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<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);
}
}
...
}
и 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> бит) & & keyUsage [бит];
Вопрос в том, почему результат вышеуказанного выражения = false? Когда бит = 0 и cert.getKeyUsage() должен возвращать массив логических значений [true, false, false, false, false, false, false, false, false]
Вы проверили все сертификаты в цепочке (в частности, сертификаты CA)? – Bruno
Да, на самом деле я использую хранилище ключей и доверенное хранилище с моего старого сервера, который запускает JRE6, и на нем нет никаких проблем, но новый с JRE7 выдает выше исключения. – chaplean
Получаете ли вы что-нибудь более точное при использовании '-Djavax.net.debug = all'? – Bruno