public X509Certificate2 FindIssuerCertificate(X509Certificate2 serverX509Certificate2) { X509Certificate2 issuerX509Certificate2 = null; // Find the issuer certificate X509Chain x509Chain = new X509Chain(); x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; x509Chain.Build(serverX509Certificate2); // Iterate though the chain, to validate if it contain a valid root vertificate X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2 = null; IDictionary <string, X509Certificate2> map = new Dictionary <string, X509Certificate2>(); // At this point, the certificate is not valid, until a // it is proved that it has a valid root certificate while (enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; map.Add(x509Certificate2.Subject, x509Certificate2); } if (map.ContainsKey(serverX509Certificate2.Issuer)) { issuerX509Certificate2 = map[serverX509Certificate2.Issuer]; } return(issuerX509Certificate2); }
private void TestOCSP() { OcspLookup ocspLookup = new OcspLookup(); X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); certStore.Open(OpenFlags.ReadOnly); string serial = "4c 05 5a 37"; X509Certificate2Collection collection = certStore.Certificates.Find(X509FindType.FindBySerialNumber, serial, true); X509Certificate2 cert = null; if (collection.Count > 0) { cert = collection[0]; } else { // the certificate not found throw new NotImplementedException("The certificate was not found."); } X509Chain x509Chain = new X509Chain(); x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; x509Chain.Build(cert); // Iterate though the chain, to validate if it contain a valid root vertificate X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2 = null; IDictionary <string, X509Certificate2> map = new Dictionary <string, X509Certificate2>(); IList <X509Certificate2> list = new List <X509Certificate2>(); // At this point, the certificate is not valid, until a // it is proved that it has a valid root certificate while (enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; list.Add(x509Certificate2); } ocspLookup.RevocationResponseOnline(list[0], list[1], "http://ocsp.systemtest8.trust2408.com/responder"); }
private void AddCertificate(X509Certificate2 cert, UnsignedProperties unsignedProperties, bool addCert, IEnumerable <string> ocspServers, IEnumerable <X509Crl> crlList, FirmaXades.Crypto.DigestMethod digestMethod, X509Certificate2[] extraCerts = null) { if (addCert) { if (CertificateChecked(cert, unsignedProperties)) { return; } string str = Guid.NewGuid().ToString(); Cert cert2 = new Cert(); cert2.IssuerSerial.X509IssuerName = cert.IssuerName.Name; cert2.IssuerSerial.X509SerialNumber = cert.GetSerialNumberAsDecimalString(); DigestUtil.SetCertDigest(cert.GetRawCertData(), digestMethod, cert2.CertDigest); cert2.URI = "#Cert" + str; unsignedProperties.UnsignedSignatureProperties.CompleteCertificateRefs.CertRefs.CertCollection.Add(cert2); EncapsulatedX509Certificate encapsulatedX509Certificate = new EncapsulatedX509Certificate(); encapsulatedX509Certificate.Id = "Cert" + str; encapsulatedX509Certificate.PkiData = cert.GetRawCertData(); unsignedProperties.UnsignedSignatureProperties.CertificateValues.EncapsulatedX509CertificateCollection.Add(encapsulatedX509Certificate); } X509ChainElementCollection chainElements = CertUtil.GetCertChain(cert, extraCerts).ChainElements; if (chainElements.Count > 1) { X509ChainElementEnumerator enumerator = chainElements.GetEnumerator(); enumerator.MoveNext(); enumerator.MoveNext(); if (!ValidateCertificateByCRL(unsignedProperties, cert, enumerator.Current.Certificate, crlList, digestMethod)) { X509Certificate2[] array = ValidateCertificateByOCSP(unsignedProperties, cert, enumerator.Current.Certificate, ocspServers, digestMethod); if (array != null) { X509Certificate2 x509Certificate = DetermineStartCert(new List <X509Certificate2>(array)); if (x509Certificate.IssuerName.Name != enumerator.Current.Certificate.SubjectName.Name) { X509Chain certChain = CertUtil.GetCertChain(x509Certificate, array); AddCertificate(certChain.ChainElements[1].Certificate, unsignedProperties, true, ocspServers, crlList, digestMethod, array); } } } AddCertificate(enumerator.Current.Certificate, unsignedProperties, true, ocspServers, crlList, digestMethod, extraCerts); } }
/// <summary> /// Checks a certificate status in a CRL. /// </summary> /// <param name="certificate">The certificate to check</param> /// <returns>The RevocationResponse object that contains the result</returns> public RevocationResponse CheckCertificate(X509Certificate2 certificate) { /* * Assumptions: * - Certificate has an CRL Distribution Points extension value. * - An HTTP distribution point is present. */ // create RevocationResponse and set default values RevocationResponse response = new RevocationResponse(); response.IsValid = true; response.NextUpdate = DateTime.MinValue; if (certificate != null) { X509Chain x509Chain = new X509Chain(); x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; x509Chain.Build(certificate); // Iterate though the chain, to get the certificate list X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2 = null; IDictionary <string, X509Certificate2> map = new Dictionary <string, X509Certificate2>(); IList <X509Certificate2> list = new List <X509Certificate2>(); while (enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; list.Add(x509Certificate2); } // now we have a list of the certificate chain // list[0] -> the function certificate // list[0 .. lsit.Count] -> middel certificates // oces1 : none middle certificate exist // oces2 : one middle certificate exist // list[list.Count] - > root certificate // we needed to validate all certificates, except the root certificates // The question wheather the root certificates is trusted, is validated in MultipleRootX509CertificateValidator // However - In the case where the root certificate is not installed, // the chain list will only be 1 length, so no validation is perfored at all. int index = 0; //bool chainValid = true; while (index < (list.Count - 1) && response.IsValid == true) { // this.logger.Info("CRL validation the certificate: " + list[index].Subject); // Retrieve URL distribution points List <Uri> URLs = this.GetURLs(list[index]); // The list should only contain one element // so we are only interesting in the first CRL list if (URLs.Count > 0) { Uri url = URLs[0]; CrlInstance crl = this.GetInstance(url); try { if (!crl.IsRevoked(certificate)) { // so the certificate is not revoked. // remember, that the issueing certificate could be revoked. // So the next update must be the earlist of the all response.IsValid = true; if (response.NextUpdate == DateTime.MinValue) { response.NextUpdate = crl.getNextUpdate(); } else if (response.NextUpdate < crl.getNextUpdate()) { // no new update // the already registrated 'NextUpdate' is before the crl.getNextUpdate } else { // new update time // The already registrated 'NextUpdate', is greater (futher in the future) then crl.getNextUpdate // so we use the crl.getNextUpdate as next update response.NextUpdate = crl.getNextUpdate(); } } else { response.IsValid = false; } } catch (CheckCertificateRevokedUnexpectedException exception) { // could not validate the certificate - so i don't trust it response.Exception = exception; response.IsValid = false; } } else { // url server not identified, so we don't trust this certificate response.IsValid = false; } // increase the index, to check the next certificate index++; } // all the certificate in the chain is now checked. if (response.IsValid == true) { response.RevocationCheckStatus = RevocationCheckStatus.AllChecksPassed; } else { response.RevocationCheckStatus = RevocationCheckStatus.CertificateRevoked; } x509Chain.Reset(); } else { response.IsValid = false; response.Exception = new CheckCertificateRevokedUnexpectedException(new Exception("Error during CRL lookup. The certificate is null"));//did not have any CRL DistPoints. Certificate: " + certificate)); response.RevocationCheckStatus = RevocationCheckStatus.UnknownIssue; } return(response); }
public bool IsCertificateChildOfRoot(X509Certificate2 certificate, IDictionary <string, X509Certificate2> rootCertificateDirectory) { // valid until proved otherwhise bool isValid = true; X509Chain x509Chain = this.CreateChain(certificate); // Modified chain validation of the certificate. We are not interested in Ctl lists X509ChainStatus status; int index = 0; while (isValid && index < x509Chain.ChainStatus.Length) { status = x509Chain.ChainStatus[index]; switch (status.Status) { case X509ChainStatusFlags.CtlNotSignatureValid: case X509ChainStatusFlags.CtlNotTimeValid: case X509ChainStatusFlags.CtlNotValidForUsage: case X509ChainStatusFlags.NoError: case X509ChainStatusFlags.OfflineRevocation: case X509ChainStatusFlags.RevocationStatusUnknown: { // so far, still valid break; } case X509ChainStatusFlags.Cyclic: case X509ChainStatusFlags.HasExcludedNameConstraint: case X509ChainStatusFlags.HasNotDefinedNameConstraint: case X509ChainStatusFlags.HasNotPermittedNameConstraint: case X509ChainStatusFlags.HasNotSupportedNameConstraint: case X509ChainStatusFlags.InvalidBasicConstraints: case X509ChainStatusFlags.InvalidExtension: case X509ChainStatusFlags.InvalidNameConstraints: case X509ChainStatusFlags.InvalidPolicyConstraints: case X509ChainStatusFlags.NoIssuanceChainPolicy: case X509ChainStatusFlags.NotSignatureValid: case X509ChainStatusFlags.NotTimeNested: case X509ChainStatusFlags.NotTimeValid: case X509ChainStatusFlags.NotValidForUsage: case X509ChainStatusFlags.PartialChain: case X509ChainStatusFlags.Revoked: case X509ChainStatusFlags.UntrustedRoot: { this.logger.Warn("X509ChainStatusFlags '" + status.Status + "' is not valid, so the certificate '" + certificate.Subject + "' is not valid."); this.logger.Debug("x509Chain.ChainStatus.Length:" + x509Chain.ChainStatus.Length + ". Index: " + index + "."); isValid = false; break; } default: { this.logger.Warn("The certificate chain.ChainStatus '" + status.Status + "' is not implemented."); isValid = false; break; } } index++; } if (isValid) { // Check if the certificate has the default root certificate as its root string x509CertificateThumbprint = certificate.Thumbprint.ToLowerInvariant(); if (rootCertificateDirectory.ContainsKey(x509CertificateThumbprint)) { // certificate is a root certificate - not valid isValid = false; } else { // Iterate though the chain, to validate if it contain a valid root vertificate X509ChainElementCollection x509ChainElementCollection = x509Chain.ChainElements; X509ChainElementEnumerator enumerator = x509ChainElementCollection.GetEnumerator(); X509ChainElement x509ChainElement; X509Certificate2 x509Certificate2; // At this point, the certificate is not valid, until a // it is proved that it has a valid root certificate isValid = false; while (isValid == false && enumerator.MoveNext()) { x509ChainElement = enumerator.Current; x509Certificate2 = x509ChainElement.Certificate; x509CertificateThumbprint = x509Certificate2.Thumbprint.ToLowerInvariant(); if (rootCertificateDirectory.ContainsKey(x509CertificateThumbprint)) { // The current chain element is in the trusted rootCertificateDirectory isValid = true; // now the loop will break, as we have found a trusted root certificate } } this.logger.Debug("Found root certificate in the root certificate list: " + isValid.ToString()); } } return(isValid); }