Java — проверка сертификата с помощью системы TrustStore

Предпосылка: у меня есть сертификат, и я хочу убедиться, что система "доверяет" этому сертификату (подписанному доверенным корневым ЦС с помощью Java/операционной системы)

Я нашел несколько различных решений о том, как это сделать.

Опция 1:

Используйте классы SSL для получения доверия.

TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init((KeyStore) null);
for (TrustManager trustManager : tmfactory.getTrustManagers()) {
    if (trustManager instanceof X509TrustManager) {
        try {
            ((X509TrustManager) trustManager).checkClientTrusted(new X509Certificate[] {new JcaX509CertificateConverter().getCertificate(holder)}, "RSA");
            System.out.println("This certificate is trusted by a Root CA");
        } catch (CertificateException e) {
            e.printStackTrace();
        }
    }
}

Поскольку этот подход сильно зависит от классов SSL (которые не нужны текущему проекту), мы ищем альтернативы.

Вариант 2. Загрузите файл cacertsfile Java в хранилище ключей и проверьте соответствие каждого «наиболее надежного» сертификата моему сертификату.

String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());

// This class retrieves the most-trusted CAs from the keystore
PKIXParameters params = new PKIXParameters(keystore);
// Get the set of trust anchors, which contain the most-trusted CA certificates
Set<X509Certificate> rootCertificates = params.getTrustAnchors().parallelStream().map(TrustAnchor::getTrustedCert).collect(Collectors.toSet());
return rootCertificates.contains(holderX509);

Проблема с этим подходом заключается в том, что для проверки целостности файла, закодированного JKS, требуется пароль. В то время как SSL, по-видимому, не использует (или, скорее, использует System.getProperty("javax.net.ssl.trustStorePassword"), который снова сильно привязан к SSL.

Вопрос. Существует ли промежуточное решение между ручной загрузкой сертификатов из файла и чистым SSL? Я чувствую, что должен быть какой-то класс, который я могу вызвать, чтобы просто проверить доверие системы к сертификату без необходимости прыгать через пару обручей.


person Spartan9209    schedule 13.04.2016    source источник
comment
Здесь нет ничего плохого в использовании TrustManager. Вот для чего это нужно. Преодолейте свое отвращение.   -  person user207421    schedule 20.04.2016


Ответы (2)


После прочтения Дэвида Хука «Начало криптографии с Java» я создал следующий пример для проверки цепочки сертификатов (который выполняет первоначальную цель использования системного хранилища доверенных сертификатов для проверки корневых ЦС).

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
InputStream is = new ByteArrayInputStream(some bytes in an array);
CertPath certPath = certificateFactory.generateCertPath(is, "PKCS7"); // Throws Certificate Exception when a cert path cannot be generated
CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", new BouncyCastleProvider());
PKIXParameters parameters = new PKIXParameters(KeyTool.getCacertsKeyStore());

PKIXCertPathValidatorResult validatorResult = (PKIXCertPathValidatorResult) certPathValidator.validate(certPath, parameters); // This will throw a CertPathValidatorException if validation fails

Это также позволяет отказаться от использования классов SSL — вместо этого используются классы/алгоритмы безопасности Java.

person Spartan9209    schedule 26.04.2016

Если не считать загрузки сторонней библиотеки, другой альтернативы, вероятно, нет.

Почему вы пытаетесь избежать библиотеки «SSL»? Он входит в стандартную библиотеку и поэтому не нагружает вашу программу.

В любом случае проверка сертификата является важной частью SSL. Я сомневаюсь, что кто-то утруждал себя созданием библиотеки, которая делала бы это без реализации существенного подмножества протокола SSL. Просто нет реальной причины для этого.

person Andrew Michael Felsher    schedule 19.04.2016