/** * Checks if an OCSP response is genuine * @param ocspResp the OCSP response * @param responderCert the responder certificate * @return true if the OCSP response verifies against the responder certificate */ public bool IsSignatureValid(BasicOcspResp ocspResp, X509Certificate responderCert) { try { return ocspResp.Verify(responderCert.GetPublicKey()); } catch (OcspException) { return false; } }
/** * Verifies an OCSP response against a KeyStore. * @param ocsp the OCSP response * @param keystore the <CODE>KeyStore</CODE> * @param provider the provider or <CODE>null</CODE> to use the BouncyCastle provider * @return <CODE>true</CODE> is a certificate was found */ public static bool VerifyOcspCertificates(BasicOcspResp ocsp, ICollection<X509Certificate> keystore) { try { foreach (X509Certificate certStoreX509 in keystore) { try { if (ocsp.Verify(certStoreX509.GetPublicKey())) return true; } catch { } } } catch { } return false; }
//2. The signature on the response is valid; private void ValidateResponseSignature(BasicOcspResp or, Org.BouncyCastle.Crypto.AsymmetricKeyParameter asymmetricKeyParameter) { if (!or.Verify(asymmetricKeyParameter)) { throw new Exception("Invalid OCSP signature"); } }
/// <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); }
private void ValidarResponseSignature(BasicOcspResp in_OcspResp, Org.BouncyCastle.Crypto.AsymmetricKeyParameter in_PublicKey) { if (!in_OcspResp.Verify(in_PublicKey)) { throw new Exception("Firma OCSP Invalida"); } }
private static void CheckBasicOcspResp(CertID id, BasicOcspResp basicResp, OcesCertificate ocspCertificate, Ca ca) { DateTime nowInGmt = DateTime.Now.ToUniversalTime(); /* check condition: The certificate identified in a received response corresponds to that which was identified in the corresponding request; */ SingleResp[] responses = basicResp.Responses; if (responses.Length != 1) { throw new OcspException("unexpected number of responses received"); } if (!id.SerialNumber.Value.Equals(responses[0].GetCertID().SerialNumber)) { throw new OcspException("Serial number mismatch problem"); } /* check condition The signature on the response is valid; */ try { ChainVerifier.VerifyTrust(ocspCertificate.ExportCertificate(), ca); } catch(ChainVerificationException e) { throw new OcspException("OCSP response certificate chain is invalid", e); } /* check the signature on the ocsp response */ var ocspBcCertificate = new X509CertificateParser().ReadCertificate(ocspCertificate.ExportCertificate().RawData); if (!basicResp.Verify(ocspBcCertificate.GetPublicKey())) { throw new OcspException("signature validation failed for ocsp response"); } if (!CanSignOcspResponses(ocspBcCertificate)) { throw new OcspException("ocsp signing certificate has not been cleared for ocsp response signing"); } /* check expiry of the signing certificate */ if (ocspCertificate.ValidityStatus() != CertificateStatus.Valid) { throw new OcspException("OCSP certificate expired or not yet valid"); } /* check condition The time at which the status being indicated is known to be correct (thisUpdate) is sufficiently recent. */ SingleResp response = responses[0]; var diff = response.ThisUpdate - nowInGmt; if (diff > new TimeSpan(0, 1, 0)) { throw new OcspException("OCSP response signature is from the future. Timestamp of thisUpdate field: " + response.ThisUpdate); } if (response.NextUpdate != null && response.NextUpdate.Value < nowInGmt) { throw new OcspException("OCSP response is no longer valid"); } }
static void CheckValidityOfResponse(CertID id, BasicOcspResp responseObject, Ca ca) { var inputStream = new MemoryStream(responseObject.GetEncoded()); var asn1Sequence = (Asn1Sequence)new Asn1InputStream(inputStream).ReadObject(); var response = BasicOcspResponse.GetInstance(asn1Sequence); var ocspChain = CreateOcspCertificateChain(ca); if(ocspChain.Length == 0) { throw new OcspException("OCSP certificate chain is invalid"); } var ocesOcspCertificate = OcesCertificateFactory.Instance.Generate(CompleteOcspChain(response, ocspChain)); CheckBasicOcspResp(id, responseObject, ocesOcspCertificate, ca); var signingCertificate = new X509CertificateParser().ReadCertificate(response.Certs[0].GetEncoded()); var issuingCertificate = new X509CertificateParser().ReadCertificate(ocspChain[0].GetRawCertData()); signingCertificate.Verify(issuingCertificate.GetPublicKey()); if (!responseObject.Verify(signingCertificate.GetPublicKey())) { throw new OcspException("Signature is invalid"); } }