/** * Verifies a single certificate. * @param cert the certificate to verify * @param crls the certificate revocation list or <CODE>null</CODE> * @param calendar the date or <CODE>null</CODE> for the current date * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE> * if no error */ public static String VerifyCertificate(X509Certificate cert, ICollection<X509Crl> crls, DateTime calendar) { try { if (!cert.IsValid(calendar)) return "The certificate has expired or is not yet valid"; if (crls != null) { foreach (X509Crl crl in crls) { if (crl.IsRevoked(cert)) return "Certificate revoked"; } } } catch (Exception e) { return e.ToString(); } return null; }
/** * Loads the default root certificates at <java.home>/lib/security/cacerts * with the default provider. * @return a <CODE>KeyStore</CODE> */ // public static KeyStore LoadCacertsKeyStore() { // return LoadCacertsKeyStore(null); // } /** * Loads the default root certificates at <java.home>/lib/security/cacerts. * @param provider the provider or <code>null</code> for the default provider * @return a <CODE>KeyStore</CODE> */ // public static KeyStore LoadCacertsKeyStore(String provider) { // File file = new File(System.GetProperty("java.home"), "lib"); // file = new File(file, "security"); // file = new File(file, "cacerts"); // FileInputStream fin = null; // try { // fin = new FileInputStream(file); // KeyStore k; // if (provider == null) // k = KeyStore.GetInstance("JKS"); // else // k = KeyStore.GetInstance("JKS", provider); // k.Load(fin, null); // return k; // } // catch (Exception e) { // throw new ExceptionConverter(e); // } // finally { // try{fin.Close();}catch(Exception ex){} // } // } /** * Verifies a single certificate. * @param cert the certificate to verify * @param crls the certificate revocation list or <CODE>null</CODE> * @param calendar the date or <CODE>null</CODE> for the current date * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE> * if no error */ public static String VerifyCertificate(X509Certificate cert, object[] crls, DateTime calendar) { try { if (!cert.IsValid(calendar)) return "The certificate has expired or is not yet valid"; } catch (Exception e) { return e.ToString(); } return null; }
/** * Verifies a single certificate. * @param cert the certificate to verify * @param crls the certificate revocation list or <CODE>null</CODE> * @param calendar the date or <CODE>null</CODE> for the current date * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE> * if no error */ public static String VerifyCertificate(X509Certificate cert, ICollection<X509Crl> crls, DateTime calendar) { foreach (String oid in cert.GetCriticalExtensionOids()) { if (oid == X509Extensions.KeyUsage.Id || oid == X509Extensions.CertificatePolicies.Id || oid == X509Extensions.PolicyMappings.Id || oid == X509Extensions.InhibitAnyPolicy.Id || oid == X509Extensions.CrlDistributionPoints.Id || oid == X509Extensions.IssuingDistributionPoint.Id || oid == X509Extensions.DeltaCrlIndicator.Id || oid == X509Extensions.PolicyConstraints.Id || oid == X509Extensions.BasicConstraints.Id || oid == X509Extensions.SubjectAlternativeName.Id || oid == X509Extensions.NameConstraints.Id) { continue; } try { // EXTENDED KEY USAGE and TIMESTAMPING is ALLOWED if (oid == X509Extensions.ExtendedKeyUsage.Id && cert.GetExtendedKeyUsage().Contains("1.3.6.1.5.5.7.3.8")) { continue; } } catch (CertificateParsingException) { // DO NOTHING; } return "Has unsupported critical extension"; } try { if (!cert.IsValid(calendar.ToUniversalTime())) return "The certificate has expired or is not yet valid"; if (crls != null) { foreach (X509Crl crl in crls) { if (crl.IsRevoked(cert)) return "Certificate revoked"; } } } catch (Exception e) { return e.ToString(); } return null; }
/// <summary> /// Validates the cert with the provided ocsp responses. /// </summary> /// <param name="certificate">The cert to validate</param> /// <param name="issuer">The issuer of the cert to validate</param> /// <param name="validationTime">The time on which the cert was needed to validated</param> /// <param name="ocspResponses">The list of ocsp responses to use</param> /// <returns>The OCSP response that was used, <c>null</c> if none was found</returns> /// <exception cref="RevocationException{T}">When the certificate was revoked on the provided time</exception> /// <exception cref="RevocationUnknownException">When the certificate (or the OCSP) can't be validated</exception> public static BCAO.BasicOcspResponse Verify(this X509Certificate2 certificate, X509Certificate2 issuer, DateTime validationTime, IList <BCAO.BasicOcspResponse> ocspResponses) { DateTime minTime = validationTime - ClockSkewness; DateTime maxTime = validationTime + ClockSkewness; BCX.X509Certificate certificateBC = DotNetUtilities.FromX509Certificate(certificate); BCX.X509Certificate issuerBC = DotNetUtilities.FromX509Certificate(issuer); ValueWithRef <BCO.SingleResp, ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse> > singleOcspRespLeaf = ocspResponses .Select((rsp) => new ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse>(new BCO.BasicOcspResp(rsp), rsp)) //convert, but keep the original .SelectMany((r) => r.Value.Responses.Select(sr => new ValueWithRef <BCO.SingleResp, ValueWithRef <BCO.BasicOcspResp, BCAO.BasicOcspResponse> >(sr, r))) //get the single respononses, but keep the parent .Where((sr) => sr.Value.GetCertID().SerialNumber.Equals(certificateBC.SerialNumber) && sr.Value.GetCertID().MatchesIssuer(issuerBC)) //is it for this cert? .Where((sr) => sr.Value.ThisUpdate >= minTime || (sr.Value.NextUpdate != null && sr.Value.NextUpdate.Value >= minTime)) //was it issued on time? .OrderByDescending((sr) => sr.Value.ThisUpdate) //newest first .FirstOrDefault(); if (singleOcspRespLeaf == null) { return(null); } BCO.SingleResp singleOcspResp = singleOcspRespLeaf.Value; BCO.BasicOcspResp basicOcspResp = singleOcspRespLeaf.Reference.Value; BCAO.BasicOcspResponse basicOcspResponse = singleOcspRespLeaf.Reference.Reference; //get the signer name BCAX.X509Name responderName = basicOcspResp.ResponderId.ToAsn1Object().Name; if (responderName == null) { trace.TraceEvent(TraceEventType.Error, 0, "OCSP response for {0} does not have a ResponderID", certificate.Subject); throw new RevocationUnknownException("OCSP response for {0} does not have a ResponderID"); } //Get the signer certificate var selector = new BCS.X509CertStoreSelector(); selector.Subject = responderName; BCX.X509Certificate ocspSignerBc = (BCX.X509Certificate)basicOcspResp .GetCertificates("Collection").GetMatches(selector) .Cast <BCX.X509Certificate>().FirstOrDefault(); if (ocspSignerBc == null) { throw new RevocationUnknownException("The OCSP is signed by a unknown certificate"); } //verify the response signature if (!basicOcspResp.Verify(ocspSignerBc.GetPublicKey())) { throw new RevocationUnknownException("The OCSP has an invalid signature"); } //OCSP must be issued by same issuer an the certificate that it validates. try { if (!ocspSignerBc.IssuerDN.Equals(issuerBC.SubjectDN)) { throw new ApplicationException(); } ocspSignerBc.Verify(issuerBC.GetPublicKey()); } catch (Exception e) { throw new RevocationUnknownException("The OCSP signer was not issued by the proper CA", e); } //verify if the OCSP signer certificate is stil valid if (!ocspSignerBc.IsValid(basicOcspResp.ProducedAt)) { throw new RevocationUnknownException("The OCSP signer was not valid at the time the ocsp was issued"); } //check if the signer may issue OCSP IList ocspSignerExtKeyUsage = ocspSignerBc.GetExtendedKeyUsage(); if (!ocspSignerExtKeyUsage.Contains("1.3.6.1.5.5.7.3.9")) { throw new RevocationUnknownException("The OCSP is signed by a certificate that isn't allowed to sign OCSP"); } //finally, check if the certificate is revoked or not var revokedStatus = (BCO.RevokedStatus)singleOcspResp.GetCertStatus(); if (revokedStatus != null) { trace.TraceEvent(TraceEventType.Verbose, 0, "OCSP response for {0} indicates that the certificate is revoked on {1}", certificate.Subject, revokedStatus.RevocationTime); if (maxTime >= revokedStatus.RevocationTime) { throw new RevocationException <BCAO.BasicOcspResponse>(basicOcspResponse, "The certificate was revoked on " + revokedStatus.RevocationTime.ToString("o")); } } return(basicOcspResponse); }
/** * Verifies a single certificate. * @param cert the certificate to verify * @param crls the certificate revocation list or <CODE>null</CODE> * @param calendar the date or <CODE>null</CODE> for the current date * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE> * if no error */ public static String VerifyCertificate(X509Certificate cert, ICollection<X509Crl> crls, DateTime calendar) { foreach (String oid in cert.GetCriticalExtensionOids()) { // KEY USAGE and DIGITAL SIGNING is ALLOWED if ("2.5.29.15".Equals(oid) && cert.GetKeyUsage()[0]) { continue; } try { // EXTENDED KEY USAGE and TIMESTAMPING is ALLOWED if ("2.5.29.37".Equals(oid) && cert.GetExtendedKeyUsage().Contains("1.3.6.1.5.5.7.3.8")) { continue; } } catch (CertificateParsingException) { // DO NOTHING; } return "Has unsupported critical extension"; } try { if (!cert.IsValid(calendar)) return "The certificate has expired or is not yet valid"; if (crls != null) { foreach (X509Crl crl in crls) { if (crl.IsRevoked(cert)) return "Certificate revoked"; } } } catch (Exception e) { return e.ToString(); } return null; }
public static CertificateSecurityInformation Verify(this Org.BouncyCastle.X509.X509Certificate cert, DateTime date, int[] keyUsageIndexes, int minimumKeySize, IX509Store certs, ref IList <CertificateList> crls, ref IList <BasicOcspResponse> ocsps) { CertificateSecurityInformation result = new CertificateSecurityInformation(); result.Certificate = new X509Certificate2(cert.GetEncoded()); //check key size AsymmetricKeyParameter key = cert.GetPublicKey(); if (!VerifyKeySize(key, minimumKeySize)) { result.securityViolations.Add(CertSecurityViolation.NotValidKeySize); trace.TraceEvent(TraceEventType.Warning, 0, "The key was smaller then {0}", minimumKeySize); } //check key usages foreach (int i in keyUsageIndexes) { if (!cert.GetKeyUsage()[i]) { result.securityViolations.Add(CertSecurityViolation.NotValidForUsage); trace.TraceEvent(TraceEventType.Warning, 0, "The key usage did not have the correct usage flag {0} set", i); } } //build extra store X509Certificate2Collection extraStore = new X509Certificate2Collection(); foreach (Org.BouncyCastle.X509.X509Certificate obj in certs.GetMatches(null)) { extraStore.Add(new X509Certificate2(obj.GetEncoded())); } CertificateSecurityInformation dest = result; CertificateSecurityInformation previous = null; Org.BouncyCastle.X509.X509Certificate issuer = cert.ValidateAndGetDerivedIssuer(certs); if (issuer != null) { trace.TraceEvent(TraceEventType.Verbose, 0, "Detected eHealth variant of proxy certificate"); //check proxy certificate, is it still valid? if (!cert.IsValid(date)) { dest.securityViolations.Add(CertSecurityViolation.NotTimeValid); trace.TraceEvent(TraceEventType.Warning, 0, "The proxy certificate is expired or not yet valid, {0} not between {1}-{2}", date, cert.NotBefore, cert.NotAfter); } //The issuer signature of the proxy certificate is already checked... //check issuer previous = dest; dest = new CertificateSecurityInformation(); dest.Certificate = new X509Certificate2(issuer.GetEncoded()); //check key size of the issuer key = issuer.GetPublicKey(); if (!VerifyKeySize(key, minimumKeySize)) { dest.securityViolations.Add(CertSecurityViolation.NotValidKeySize); trace.TraceEvent(TraceEventType.Warning, 0, "The key of the issuer was smaller then {0}", minimumKeySize); } //check key usage of the issuer foreach (int i in new int[] { 0, 1 }) { if (!issuer.GetKeyUsage()[i]) { dest.securityViolations.Add(CertSecurityViolation.NotValidForUsage); trace.TraceEvent(TraceEventType.Warning, 0, "The key usage of the issuer did not have the correct usage flag set"); } } } //check the chain Chain chain; if (crls != null || ocsps != null) { chain = dest.Certificate.BuildChain(date, extraStore, crls, ocsps); } else { chain = dest.Certificate.BuildChain(date, extraStore); } //process the chain foreach (ChainElement ce in chain.ChainElements) { //connect the prepared link if (previous != null) { previous.IssuerInfo = dest; } //update the link dest.Certificate = ce.Certificate; foreach (X509ChainStatus status in ce.ChainElementStatus.Where(x => x.Status != X509ChainStatusFlags.NoError)) { dest.securityViolations.Add((CertSecurityViolation)Enum.Parse(typeof(CertSecurityViolation), Enum.GetName(typeof(X509ChainStatusFlags), status.Status))); } //prepare the next link previous = dest; dest = new CertificateSecurityInformation(); } if (chain.ChainStatus.Count(x => x.Status == X509ChainStatusFlags.PartialChain) > 0) { result.securityViolations.Add(CertSecurityViolation.IssuerTrustUnknown); } trace.TraceEvent(TraceEventType.Verbose, 0, "Verified certificate {0} for date {1}", cert.SubjectDN.ToString(), date); return(result); }
public static bool IsBetter(this Org.BouncyCastle.X509.X509Certificate self, Org.BouncyCastle.X509.X509Certificate other, DateTime time) { return(other == null || (self.IsValid(time) && !other.IsValid(time)) || (self.IsValid(time) && other.IsValid(time) && self.NotBefore > other.NotBefore)); }