private static X509Certificate2 CheckSigner(this TimeStampToken tst, Timestamp value) { BC.X509Certificate signerBc = tst.GetSigner(); if (signerBc == null) { trace.TraceEvent(TraceEventType.Warning, 0, "The signer of the time-stamp {0} isn't found", tst.TimeStampInfo.SerialNumber); X509CertificateHelper.AddErrorStatus(value.TimestampStatus, null, X509ChainStatusFlags.NotSignatureValid, "Signer not found"); return(null); } //check the signature try { tst.Validate(signerBc); } catch (Exception e) { trace.TraceEvent(TraceEventType.Warning, 0, "The signature from {1} of the time-stamp {0} is invalid: {2}", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN, e.Message); X509CertificateHelper.AddErrorStatus(value.TimestampStatus, null, X509ChainStatusFlags.NotSignatureValid, "Time-stamp not signed by indicated certificate: " + e.Message); } //check if the certificate may be used for time-stamping IList signerExtKeyUsage = signerBc.GetExtendedKeyUsage(); if (!signerExtKeyUsage.Contains("1.3.6.1.5.5.7.3.8")) { trace.TraceEvent(TraceEventType.Warning, 0, "The signer {1} of the time-stamp {0} isn't allowed to sign timestamps", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN); X509CertificateHelper.AddErrorStatus(value.TimestampStatus, null, X509ChainStatusFlags.NotSignatureValid, "The certificate may not be used for timestamps"); } return(new X509Certificate2(signerBc.GetEncoded())); }
internal static bool HasUnsupportedCriticalExtension(X509Certificate cert) { 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(true); } return(false); }
internal static bool HasUnsupportedCriticalExtension(X509Certificate cert) { if (cert == null) { throw new ArgumentException("X509Certificate can't be null."); } foreach (String oid in cert.GetCriticalExtensionOids()) { if (oid == X509Extensions.BasicConstraints.Id || oid == X509Extensions.CertificatePolicies.Id || oid == X509Extensions.CrlDistributionPoints.Id || oid == X509Extensions.DeltaCrlIndicator.Id || oid == X509Extensions.InhibitAnyPolicy.Id || oid == X509Extensions.IssuingDistributionPoint.Id || oid == X509Extensions.NameConstraints.Id || oid == X509Extensions.PolicyConstraints.Id || oid == X509Extensions.PolicyMappings.Id || oid == X509Extensions.SubjectAlternativeName.Id) { continue; } if (oid == X509Extensions.KeyUsage.Id) { bool[] keyUsageFlags = cert.GetKeyUsage(); if (keyUsageFlags[KEY_USAGE_DIGITAL_SIGNATURE] || keyUsageFlags[KEY_USAGE_NON_REPUDIATION]) { continue; } } try { // EXTENDED KEY USAGE and TIMESTAMPING is ALLOWED if (oid == X509Extensions.ExtendedKeyUsage.Id && cert.GetExtendedKeyUsage().Contains(OID.X509Extensions.ID_KP_TIMESTAMPING)) { continue; } } catch (CertificateParsingException) { // DO NOTHING; } return(true); } return(false); }
/** * 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; }
/** * 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; }
/// <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); }
static bool CanSignOcspResponses(X509Certificate ocspCertificate) { return ocspCertificate.GetExtendedKeyUsage().Contains(KeyPurposeID.IdKPOcspSigning.Id); }
static bool CanSignOcspResponses(X509Certificate ocspCertificate) { return(ocspCertificate.GetExtendedKeyUsage().Contains(KeyPurposeID.IdKPOcspSigning.Id)); }
private bool GetExtendedKeyUsage(string oidValue) => HasExtendedKeyUsage && _bcX509.GetExtendedKeyUsage().Contains(oidValue);