Принятие просроченного CRL с BouncyCastle - PullRequest
0 голосов
/ 18 мая 2018

Я проверяю сертификаты X509 в автономном режиме с надувным замком и столкнулся с проблемой со старыми CRL.Я еще не нашел возможности принять CRL, срок действия которых истек, по моему мнению, если сертификат был отозван, он должен оставаться аннулированным после истечения CRL.Кроме того, если CRL пуст, я просто хочу принять это, у меня нет способа получить более новый CRL на данный момент.

Просто чтобы уточнить, это будет вариант использования:

  1. Создать сертификат в 2015 году, действительный 2015-2020
  2. Отзыв сертификата с CRL в 2017 году, ключ был украден, создать CRL только на 1 год, потому что я ошибаюсь или планирую перевернуться и никогда не получувокруг него
  3. Проверьте сертификат в 2019 году, CRL истек, оживленный замок снова принимает отозванный сертификат - что явно не то, что я хочу

В настоящее время я устанавливаюпроверка отзыва на false и выполнение проверки самостоятельно.Я нигде не нашел в Интернете ничего об этом.

Это мой код:

final X509CertSelector endConstraints = new X509CertSelector();
endConstraints.setSerialNumber(signer.getSID().getSerialNumber());

final PKIXBuilderParameters buildParams = new PKIXBuilderParameters(trustAnchors, endConstraints);
//a CertStore object with Certificates and CRLs
buildParams.addCertStore(certificates);
//currently deactivated
buildParams.setRevocationEnabled(false);

final CertPathBuilder builder = CertPathBuilder.getInstance(SignedFileVerifier.CERTIFICATE_PATH_ALGORITHM, SignedFileVerifier.PROVIDER);
final CertPathBuilderResult result = builder.build(buildParams);

//here I manually check the CRLs, which I don't want to do
checkRevocation(result.getCertPath().getCertificates(), certificates, trustAnchors);

//if this passes I return the found certificate
return (X509Certificate) result.getCertPath().getCertificates().get(0);

Точное исключение:

Caused by: org.bouncycastle.jce.exception.ExtCertPathValidatorException: No CRLs found for issuer "cn=goodOldIssuerCA0,ou=jUnit Test Issuer,o=BOGO Company,c=AT"
    at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(Unknown Source)
    at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(Unknown Source)
    at org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi.build(Unknown Source)
    at org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi.build(Unknown Source)
    ...

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

В основном вся моя проблема происходит в методе PKIXCRLUtil#findCRLs в пакете org.bouncycastle.jce.provider.Этот метод используется для загрузки списков отзыва сертификатов и всегда проверяет дату здесь:

if (crl.getNextUpdate().after(validityDate))
    {
        X509Certificate cert = crlselect.getCertificateChecking();

        if (cert != null)
            {
            if (crl.getThisUpdate().before(cert.getNotAfter()))
            {
                finalSet.add(crl);
            }
        }
        else
        {
            finalSet.add(crl);
        }
}

Код, который я в итоге использовал, приведен ниже.По сути, я сначала объединяю все открытые ключи в карту по их именам (может быть, серийный номер будет лучше?), Затем перебираю все сертификаты, которые есть в цепочке.Сначала я получаю открытый ключ издателей сертификатов, потому что он мне нужен для проверки CRL, полученного от того же эмитента.Затем я создаю X509CRLSelector эмитента и загружаю все CRL этим эмитентом.Затем я перебираю списки отзыва сертификатов, найденные в магазине, проверяю их с помощью открытого ключа эмитента, проверяю, был ли сертификат отозван, и выдает исключение, если это так.В моей текущей реализации было бы нормально, если бы CRL не был найден, это можно добавить, проверив, что selectedCRLs не пусто.

private void checkRevocation(final List<X509Certificate> certificates, final CertStore revocationLists, final Set<TrustAnchor> trustAnchors) throws GeneralSecurityException {
    final Map<String, PublicKey> publicKeyMap = extractPublicKeys(certificates, trustAnchors);

    //check the whole chain, we don't know if the issuer or the signer was revoked
    for(final X509Certificate certificate : certificates){
        final X500Principal issuerX500Principal = certificate.getIssuerX500Principal();

        //get the issuer of this certificate
        final PublicKey issuerPublicKey = publicKeyMap.get(issuerX500Principal.getName());

        if(issuerPublicKey == null){
            throw new GeneralSecurityException("Unable to find issuer for certificate '" + certificate.getSubjectX500Principal() + "'");
        }

        final X509CRLSelector crlSelector = new X509CRLSelector();
        //we only use the issuer, not the date or time, don't want CRLs to expire
        crlSelector.addIssuer(issuerX500Principal);

        //get all CRLs that match this issuer
        final Collection<? extends CRL> selectedCRLs = revocationLists.getCRLs(crlSelector);
        for(final CRL crl : selectedCRLs){
            final X509CRL x509CRL = (X509CRL)crl;
            //check first if the crl is really published by the issuer
            x509CRL.verify(issuerPublicKey);

            //check if the current certificate was revoked
            final X509CRLEntry revokedCertificate = x509CRL.getRevokedCertificate(certificate);

            //if we found a revoked certificate throw an exception
            if(revokedCertificate != null){
                throw new GeneralSecurityException(String.format("Unable to use certificate '%1$s', revocation after %2$tF %2$tT, reason: %3$s",
                        certificate.getSubjectX500Principal(), revokedCertificate.getRevocationDate(), revokedCertificate.getRevocationReason()));
            }
        }
    }
}

private Map<String, PublicKey> extractPublicKeys(final List<X509Certificate> certificates, final Set<TrustAnchor> trustAnchors) {
    final Map<String, PublicKey> certificateMap = new HashMap<>();
    for(final X509Certificate certificate : certificates){
        certificateMap.put(certificate.getSubjectX500Principal().getName(), certificate.getPublicKey());
    }

    for(final TrustAnchor trustAnchor : trustAnchors){
        final X509Certificate certificate = trustAnchor.getTrustedCert();
        certificateMap.put(certificate.getSubjectX500Principal().getName(), certificate.getPublicKey());
    }
    return certificateMap;
}
0 голосов
/ 27 мая 2018

Полностью отключить проверки CRL.Нет, я не шучу.Общее мнение в сообществе безопасности заключается в том, что отзыв нарушен .Современные браузеры даже не проверяют CRL.Если бы вы могли включить строгую проверку CRL в своем браузере (многие даже не позволят вам это сделать), то вы бы обнаружили, что большая часть Интернета недоступна.

...