Проверка сертификатов X509 с использованием Java APis
Я пытаюсь проверить сертификат по хранилищу ключей Java, и это код, который я использую, как показано ниже. Если он завершается успешно, то я предполагаю, что проверка прошла правильно, иначе, если выдается исключение, проверка завершается неудачно. Моя забота:
Достаточно ли приведенного ниже кода для подтверждения сертификата? Как в том, что я что-то упускаю здесь (например, проверка данных, подписанных компьютером, отправляющим мне сертификат?)? 2. Следует ли проверять подпись, содержащуюся в сертификате? Если да, то как?
Заранее спасибо за ответ! Прадип
// To check the validity of the dates
cert.checkValidity();
//Check the chain
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List<X509Certificate> mylist = new ArrayList<X509Certificate>();
mylist.add(cert);
CertPath cp = cf.generateCertPath(mylist);
PKIXParameters params = new PKIXParameters(getTrustStore());
params.setRevocationEnabled(false);
CertPathValidator cpv =
CertPathValidator.getInstance(CertPathValidator.getDefaultType());
PKIXCertPathValidatorResult pkixCertPathValidatorResult =
(PKIXCertPathValidatorResult) cpv.validate(cp, params);
3 ответа
Как правило, сертификат будет выдан промежуточным органом выдачи, а не "корневым" органом (это все, что должно быть в вашем хранилище доверенных сертификатов). Большинство протоколов поощряют отправку "цепочки" сертификатов, а не только сертификата объекта.
Вы должны добавить все промежуточные сертификаты, чтобы сформировать полную цепочку.
Чтобы быть уверенным, что сертификат все еще действителен, не следует отключать проверки отзыва. Если вы не хотите получать CRL (который может быть большим), эмитент может предложить поддержку OCSP. Но это должно быть включено во время выполнения Java путем установки определенных системных свойств.
Если средство проверки пути успешно возвращается, вам не нужно ничего проверять. Если сертификат недействителен, возникнет исключение.
Также нет необходимости в явной проверке даты действия. Это происходит во время проверки (с использованием текущего времени, если вы не укажете время через PKIXParameters
).
Более подробное обсуждение проверки, включая пример кода, см. В предыдущем моем ответе.
Если вы довольны настройками доверия по умолчанию (так как они будут использоваться по умолчанию SSLContext
), вы могли бы построить X509TrustManager
независимо от SSL/TLS и используйте, если проверить свой сертификат самостоятельно.
Это будет выглядеть так:
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null);
// you could use a non-default KeyStore as your truststore too, instead of null.
for (TrustManager trustManager: trustManagerFactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
x509TrustManager.checkServerTrusted(...);
}
}
(Вам также следует проверить идентификацию сервера и соответствие сертификата, см. RFC 6125 (Представление и проверка идентичности доменной службы приложений в инфраструктуре открытых ключей Интернета с использованием сертификатов X.509 (PKIX) в контексте безопасности транспортного уровня (TLS)).).)
Здесь вы проверяете, есть ли сертификат (в вашем примере cert
) был подписан (напрямую) любым доверенным центром сертификации в доверенном хранилище.
Кроме того, вы проверяете срок действия, но проверка отзыва не выполняется.
Так что если cert
не был подписан ни одним из доверенных центров сертификации, вы получите исключение.
Так что кода достаточно, чтобы проверить, cert
был подписан любым из доверенных центров сертификации
Если вы используете аутентификацию на сервере, то кода в посте недостаточно.
Этот код просто подтверждает, что конкретный сертификат подписан доверенным центром сертификации.
Однако у вас нет никаких указаний на то, что "сущность", отправляющая вам этот сертификат, на самом деле является владельцем сертификата (т.е. они владеют закрытым ключом, связанным с этим сертификатом).
Это часть аутентификации SSL, где, например, клиент отправляет ClientKeyExchange
сообщение зашифровано с помощью открытого ключа удаленного сервера, и он уверен, что если другая сторона является фальшивкой, расшифровать сообщение будет невозможно