Я пытаюсь обработать сертификаты X509 в несколько этапов и столкнулся с парой проблем. Я новичок в JCE, поэтому еще не совсем в курсе всего.
Мы хотим иметь возможность анализировать несколько разных сертификатов X509 на основе разных кодировок (PEM, DER и PCKS7). Я экспортировал тот же сертификат из https://belgium.beв формате PEM и PCKS7, используя FireFox (сертификат, включая цепочку). Я пропустил пару строк, которые не нужны для вопросов.
public List parse(FileInputStream fis) {
/*
* Generate a X509 Certificate initialized with the data read from the inputstream.
* NOTE: Generation fails when using BufferedInputStream on PKCS7 certificates.
*/
List certificates = null;
log.debug("Parsing new certificate.");
certificates = (List) cf.generateCertificates(fis);
return certificates;
}
Этот код работает нормально, пока я работаю с FileInputStream вместо BufferedInputStream для PCKS7, что уже довольно странно, я думаю? Но я могу с этим жить.
Следующим шагом является проверка этих цепочек сертификатов. 1) Проверьте, все ли сертификаты имеют действительную дату (легко) 2) Проверить цепочку сертификатов с помощью OCSP (и вернуться к CRL, если в сертификате не найден URL-адрес OCSP). Вот тут я не совсем уверен, как с этим справиться.
Я использую Sun JCE, но, похоже, для него не так много доступной документации (в примерах)?
Сначала я сделал простую реализацию, которая проверяет только цепочку, минуя проверки OCSP/CRL.
private Boolean validateChain(List certificates) {
PKIXParameters params;
CertPath certPath;
CertPathValidator certPathValidator;
Boolean valid = Boolean.FALSE;
params = new PKIXParameters(keyStore);
params.setRevocationEnabled(false);
certPath = cf.generateCertPath(certificates);
certPathValidator = CertPathValidator.getInstance("PKIX");
PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)
certPathValidator.validate(certPath, params);
if(null != result) {
valid = Boolean.TRUE;
}
return valid;
}
Это нормально работает для моего сертификата PEM, но не для сертификата PCKS7 (тот же сертификат, только экспортированный в другом формате). Ява.security.cert.CertPathValidatorException: путь не связывается ни с одним из якорей доверия.
Единственная разница, которую я вижу, заключается в том, что порядок формирования CertPath отличается? Я не смог понять, что пошло не так, поэтому пока оставил это и продолжил работу с сертификатом PEM, но давайте назовем это ВОПРОСОМ 1 ;)
После этого я хотел реализовать проверку OCSP. Очевидно, если я включу OCSP, используя: Security.setProperty("ocsp.enable", "true");и установим params.setRevocationEnabled(true); он должен быть в состоянии найти URL-адрес OCSP самостоятельно, но, похоже, это не так. Что должна делать стандартная реализация (ВОПРОС 2)? java.security.cert.CertPathValidatorException: необходимо указать местоположение ответчика OCSP.
Обходя это, я нашел способ получить URL-адрес OCSP из сертификата, используя AuthorityInfoAccessExtension и тому подобное.
Но после установки URL-адреса OCSP вручную в свойстве ocsp.url я получаю java.security.cert.CertPathValidatorException: Ошибка ответа OCSP: UNAUTHORIZED
Кажется, я многое упустил необходимых шагов, в то время как во многих онлайн-справках говорится о настройке ocsp.enableдолжно быть все, что вам нужно сделать?
Возможно, кто-то из вас, вундеркиндов, не может немного помочь мне в этом процессе? Покажите мне, в чем я совершенно не прав :)
Следующим шагом будет реализация проверок CRL, если OCSP не найден. Если кто-нибудь может указать какой-либо пример или показать мне какую-либо документацию по этому вопросу, я также буду очень признателен!
Спасибо!
РЕДАКТИРОВАТЬ: Поскольку он не подбирает свойства сам по себе, я пытался установить все свойства самостоятельно, используя следующее:
// Activate OCSP
Security.setProperty("ocsp.enable", "true");
// Activate CRLDP -- no idea what this is
Security.setProperty("com.sun.security.enableCRLDP", "true");
X509Certificate target = (X509Certificate) certPath.getCertificates().get(0);
Security.setProperty("ocsp.responderURL","http://ocsp.pki.belgium.be/");
Security.setProperty("ocsp.responderCertIssuerName", target.getIssuerX500Principal().getName());
Security.setProperty("ocsp.responderCertSubjectName", target.getSubjectX500Principal().getName());
Security.setProperty("ocsp.responderCertSerialNumber", target.getSerialNumber().toString(16));
Что дает исключение: java.security.cert.CertPathValidatorException: не удается найти сертификат ответчика (устанавливается с помощью свойств безопасности OCSP).