/// <summary>Verifies a single certificate against a key store (if present).</summary> /// <param name="signCert">the certificate to verify</param> /// <param name="issuerCert">the issuer certificate</param> /// <param name="signDate">the date the certificate needs to be valid</param> /// <returns> /// a list of <c>VerificationOK</c> objects. /// The list will be empty if the certificate couldn't be verified. /// </returns> public override IList <VerificationOK> Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate) { // verify using the CertificateVerifier if root store is missing if (rootStore == null) { return(base.Verify(signCert, issuerCert, signDate)); } try { IList <VerificationOK> result = new List <VerificationOK>(); // loop over the trusted anchors in the root store foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { try { signCert.Verify(anchor.GetPublicKey()); result.Add(new VerificationOK(signCert, this.GetType(), "Certificate verified against root store.")); result.AddAll(base.Verify(signCert, issuerCert, signDate)); return(result); } catch (GeneralSecurityException) { continue; } } result.AddAll(base.Verify(signCert, issuerCert, signDate)); return(result); } catch (GeneralSecurityException) { return(base.Verify(signCert, issuerCert, signDate)); } }
/// <summary>Verifies a time stamp against a KeyStore.</summary> /// <param name="ts">the time stamp</param> /// <param name="keystore">the <CODE>KeyStore</CODE></param> /// <param name="provider">the provider or <CODE>null</CODE> to use the BouncyCastle provider</param> /// <returns><CODE>true</CODE> is a certificate was found</returns> public static bool VerifyTimestampCertificates(TimeStampToken ts, List <X509Certificate> keystore) { IList <Exception> exceptionsThrown = new List <Exception>(); try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { SignUtils.IsSignatureValid(ts, certStoreX509); return(true); } catch (Exception ex) { exceptionsThrown.Add(ex); } } } catch (Exception e) { exceptionsThrown.Add(e); } foreach (Exception ex in exceptionsThrown) { LOGGER.Error(ex.Message, ex); } return(false); }
/// <summary>Verifies an OCSP response against a KeyStore.</summary> /// <param name="ocsp">the OCSP response</param> /// <param name="keystore">the <CODE>KeyStore</CODE></param> /// <param name="provider">the provider or <CODE>null</CODE> to use the BouncyCastle provider</param> /// <returns><CODE>true</CODE> is a certificate was found</returns> public static bool VerifyOcspCertificates(BasicOcspResp ocsp, List <X509Certificate> keystore) { try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { return(SignUtils.IsSignatureValid(ocsp, certStoreX509)); } catch (Exception) { } } } catch (Exception) { } return(false); }
/// <summary>Verifies a time stamp against a KeyStore.</summary> /// <param name="ts">the time stamp</param> /// <param name="keystore">the <CODE>KeyStore</CODE></param> /// <param name="provider">the provider or <CODE>null</CODE> to use the BouncyCastle provider</param> /// <returns><CODE>true</CODE> is a certificate was found</returns> public static bool VerifyTimestampCertificates(TimeStampToken ts, List <X509Certificate> keystore) { try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { SignUtils.IsSignatureValid(ts, certStoreX509); return(true); } catch (Exception) { } } } catch (Exception) { } return(false); }
/// <summary>Checks if a CRL verifies against the issuer certificate or a trusted anchor.</summary> /// <param name="crl">the CRL</param> /// <param name="crlIssuer">the trusted anchor</param> /// <returns>true if the CRL can be trusted</returns> public virtual bool IsSignatureValid(X509Crl crl, X509Certificate crlIssuer) { // check if the CRL was issued by the issuer if (crlIssuer != null) { try { crl.Verify(crlIssuer.GetPublicKey()); return(true); } catch (GeneralSecurityException) { LOGGER.Warn("CRL not issued by the same authority as the certificate that is being checked"); } } // check the CRL against trusted anchors if (rootStore == null) { return(false); } try { // loop over the certificate in the key store foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { try { // check if the crl was signed by a trusted party (indirect CRLs) crl.Verify(anchor.GetPublicKey()); return(true); } catch (GeneralSecurityException) { continue; } } } catch (GeneralSecurityException) { return(false); } return(false); }
/// <summary>Verifies an OCSP response against a KeyStore.</summary> /// <param name="ocsp">the OCSP response</param> /// <param name="keystore">the <CODE>KeyStore</CODE></param> /// <param name="provider">the provider or <CODE>null</CODE> to use the BouncyCastle provider</param> /// <returns><CODE>true</CODE> is a certificate was found</returns> public static bool VerifyOcspCertificates(BasicOcspResp ocsp, List <X509Certificate> keystore) { IList <Exception> exceptionsThrown = new List <Exception>(); try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { return(SignUtils.IsSignatureValid(ocsp, certStoreX509)); } catch (Exception ex) { exceptionsThrown.Add(ex); } } } catch (Exception e) { exceptionsThrown.Add(e); } foreach (Exception ex in exceptionsThrown) { LOGGER.Error(ex.Message, ex); } return(false); }
/// <summary>Verifies a certificate chain against a KeyStore.</summary> /// <param name="certs">the certificate chain</param> /// <param name="keystore">the <CODE>KeyStore</CODE></param> /// <param name="crls">the certificate revocation list or <CODE>null</CODE></param> /// <param name="calendar">the date, shall not be null</param> /// <returns> /// <CODE>null</CODE> if the certificate chain could be validated or a /// <CODE>Object[]{cert,error}</CODE> where <CODE>cert</CODE> is the /// failed certificate and <CODE>error</CODE> is the error message /// </returns> public static IList <VerificationException> VerifyCertificates(X509Certificate[] certs, List <X509Certificate> keystore, ICollection <X509Crl> crls, DateTime calendar) { IList <VerificationException> result = new List <VerificationException>(); for (int k = 0; k < certs.Length; ++k) { X509Certificate cert = (X509Certificate)certs[k]; String err = VerifyCertificate(cert, crls, calendar); if (err != null) { result.Add(new VerificationException(cert, err)); } try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { if (VerifyCertificate(certStoreX509, crls, calendar) != null) { continue; } try { cert.Verify(certStoreX509.GetPublicKey()); return(result); } catch (Exception) { continue; } } catch (Exception) { } } } catch (Exception) { } int j; for (j = 0; j < certs.Length; ++j) { if (j == k) { continue; } X509Certificate certNext = (X509Certificate)certs[j]; try { cert.Verify(certNext.GetPublicKey()); break; } catch (Exception) { } } if (j == certs.Length) { result.Add(new VerificationException(cert, "Cannot be verified against the KeyStore or the certificate chain" )); } } if (result.Count == 0) { result.Add(new VerificationException((X509Certificate)null, "Invalid state. Possible circular certificate chain" )); } return(result); }
/// <summary> /// Verifies if an OCSP response is genuine /// If it doesn't verify against the issuer certificate and response's certificates, it may verify /// using a trusted anchor or cert. /// </summary> /// <param name="ocspResp">the OCSP response</param> /// <param name="issuerCert">the issuer certificate. This certificate is considered trusted and valid by this method. /// </param> /// <param name="signDate">sign date</param> public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert, DateTime signDate) { // OCSP response might be signed by the issuer certificate or // the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate responderCert = null; // first check if the issuer certificate signed the response // since it is expected to be the most common case if (IsSignatureValid(ocspResp, issuerCert)) { responderCert = issuerCert; } // if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses // from properties or from certificate chain received with response if (responderCert == null) { if (ocspResp.GetCerts() != null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp); foreach (X509Certificate cert in certs) { IList keyPurposes = null; try { keyPurposes = cert.GetExtendedKeyUsage(); if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert)) { responderCert = cert; break; } } catch (CertificateParsingException) { } } // Certificate signing the ocsp response is not found in ocsp response's certificate chain received // and is not signed by the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } // RFC 6960 4.2.2.2. Authorized Responders: // "Systems relying on OCSP responses MUST recognize a delegation certificate as being issued // by the CA that issued the certificate in question only if the delegation certificate and the // certificate being checked for revocation were signed by the same key." // and // "This certificate MUST be issued directly by the CA that is identified in the request" responderCert.Verify(issuerCert.GetPublicKey()); // check if lifetime of certificate is ok responderCert.CheckValidity(signDate); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null) { X509Crl crl; try { // TODO should also check for Authority Information Access according to RFC6960 4.2.2.2.1. "Revocation Checking of an Authorized Responder" // TODO should also respect onlineCheckingAllowed property? crl = CertificateUtil.GetCRL(responderCert); } catch (Exception) { crl = (X509Crl)null; } if (crl != null && crl is X509Crl) { CRLVerifier crlVerifier = new CRLVerifier(null, null); crlVerifier.SetRootStore(rootStore); crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed); if (!crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, signDate)) { throw new VerificationException(issuerCert, "Authorized OCSP responder certificate was revoked."); } } else { ILog logger = LogManager.GetLogger(typeof(iText.Signatures.OCSPVerifier)); logger.Error("Authorized OCSP responder certificate revocation status cannot be checked"); } } } else { // TODO throw exception starting from iText version 7.2, but only after OCSPVerifier would allow explicit setting revocation check end points/provide revocation data // throw new VerificationException(issuerCert, "Authorized OCSP responder certificate revocation status cannot be checked."); // certificate chain is not present in response received // try to verify using rootStore according to RFC 6960 2.2. Response: // "The key used to sign the response MUST belong to one of the following: // - ... // - a Trusted Responder whose public key is trusted by the requestor; // - ..." if (rootStore != null) { try { foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { if (IsSignatureValid(ocspResp, anchor)) { // certificate from the root store is considered trusted and valid by this method responderCert = anchor; break; } } } catch (Exception) { responderCert = (X509Certificate)null; } } if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified: it does not contain certificate chain and response is not signed by issuer certificate or any from the root store." ); } } } }
/// <summary> /// Verifies if an OCSP response is genuine /// If it doesn't verify against the issuer certificate and response's certificates, it may verify /// using a trusted anchor or cert. /// </summary> /// <param name="ocspResp">the OCSP response</param> /// <param name="issuerCert">the issuer certificate</param> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> /// <exception cref="System.IO.IOException"/> public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert) { //OCSP response might be signed by the issuer certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate responderCert = null; //first check if the issuer certificate signed the response //since it is expected to be the most common case if (IsSignatureValid(ocspResp, issuerCert)) { responderCert = issuerCert; } //if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses // from properties or from certificate chain received with response if (responderCert == null) { if (ocspResp.GetCerts() != null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp); foreach (X509Certificate cert in certs) { IList keyPurposes = null; try { keyPurposes = cert.GetExtendedKeyUsage(); if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert)) { responderCert = cert; break; } } catch (CertificateParsingException) { } } // Certificate signing the ocsp response is not found in ocsp response's certificate chain received // and is not signed by the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } } else { //certificate chain is not present in response received //try to verify using rootStore if (rootStore != null) { try { foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { if (IsSignatureValid(ocspResp, anchor)) { responderCert = anchor; break; } } } catch (Exception) { responderCert = (X509Certificate)null; } } // OCSP Response does not contain certificate chain, and response is not signed by any // of the rootStore or the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } } } //check "This certificate MUST be issued directly by the CA that issued the certificate in question". responderCert.Verify(issuerCert.GetPublicKey()); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null) { X509Crl crl; try { crl = CertificateUtil.GetCRL(responderCert); } catch (Exception) { crl = (X509Crl)null; } if (crl != null && crl is X509Crl) { CRLVerifier crlVerifier = new CRLVerifier(null, null); crlVerifier.SetRootStore(rootStore); crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed); crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, DateTimeUtil.GetCurrentUtcTime()); return; } } //check if lifetime of certificate is ok responderCert.CheckValidity(); }