/// <param name="crl"></param> /// <returns></returns> public virtual bool Match(X509Crl crl) { try { byte[] computedValue = DigestUtilities.CalculateDigest (algorithm, crl.GetEncoded()); return Arrays.Equals(digestValue, computedValue); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException("Maybe BouncyCastle provider is not installed ?", ex); } catch (CrlException ex) { throw new RuntimeException(ex); } }
internal static void GetCertStatus( DateTime validDate, X509Crl crl, Object cert, CertStatus certStatus) { X509Crl bcCRL = null; try { bcCRL = new X509Crl(CertificateList.GetInstance((Asn1Sequence)Asn1Sequence.FromByteArray(crl.GetEncoded()))); } catch (Exception exception) { throw new Exception("Bouncy Castle X509Crl could not be created.", exception); } X509CrlEntry crl_entry = (X509CrlEntry)bcCRL.GetRevokedCertificate(GetSerialNumber(cert)); if (crl_entry == null) return; X509Name issuer = GetIssuerPrincipal(cert); if (issuer.Equivalent(crl_entry.GetCertificateIssuer(), true) || issuer.Equivalent(crl.IssuerDN, true)) { DerEnumerated reasonCode = null; if (crl_entry.HasExtensions) { try { reasonCode = DerEnumerated.GetInstance( GetExtensionValue(crl_entry, X509Extensions.ReasonCode)); } catch (Exception e) { throw new Exception( "Reason code CRL entry extension could not be decoded.", e); } } // for reason keyCompromise, caCompromise, aACompromise or // unspecified if (!(validDate.Ticks < crl_entry.RevocationDate.Ticks) || reasonCode == null || reasonCode.Value.TestBit(0) || reasonCode.Value.TestBit(1) || reasonCode.Value.TestBit(2) || reasonCode.Value.TestBit(8)) { if (reasonCode != null) // (i) or (j) (1) { certStatus.Status = reasonCode.Value.SignValue; } else // (i) or (j) (2) { certStatus.Status = CrlReason.Unspecified; } certStatus.RevocationDate = new DateTimeObject(crl_entry.RevocationDate); } } }
/// <summary> /// Revoke the CA signed certificate. /// The issuer CA public key, the private key and the crl reside in the storepath. /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store. /// </summary> public static async Task RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { try { string subjectName = certificate.IssuerName.Name; string keyId = null; string serialNumber = null; // caller may want to create empty CRL using the CA cert itself bool isCACert = IsCertificateAuthority(certificate); // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = FindAuthorityKeyIdentifier(certificate); if (authority != null) { keyId = authority.KeyId; serialNumber = authority.SerialNumber; } else { throw new ArgumentException("Certificate does not contain an Authority Key"); } if (!isCACert) { if (serialNumber == certificate.SerialNumber || Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates"); } } X509Certificate2 certCA = null; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { if (store == null) { throw new ArgumentException("Invalid store path/type"); } certCA = await FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber); if (certCA == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store."); } if (!certCA.HasPrivateKey) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate."); } CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA); certCAIdentifier.StorePath = storePath; certCAIdentifier.StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath); X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword); if (certCAWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?"); } List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false); using (var cfrg = new CertificateFactoryRandomGenerator()) { // cert generators SecureRandom random = new SecureRandom(cfrg); BigInteger crlSerialNumber = BigInteger.Zero; Org.BouncyCastle.X509.X509Certificate bcCertCA = new X509CertificateParser().ReadCertificate(certCA.RawData); AsymmetricKeyParameter signingKey = GetPrivateKeyParameter(certCAWithPrivateKey); ISignatureFactory signatureFactory = new Asn1SignatureFactory(GetRSAHashAlgorithm(defaultHashSize), signingKey, random); X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); crlGen.SetIssuerDN(bcCertCA.IssuerDN); crlGen.SetThisUpdate(DateTime.UtcNow); crlGen.SetNextUpdate(DateTime.UtcNow.AddMonths(12)); // merge all existing revocation list X509CrlParser parser = new X509CrlParser(); foreach (X509CRL caCrl in certCACrl) { X509Crl crl = parser.ReadCrl(caCrl.RawData); crlGen.AddCrl(crl); var crlVersion = GetCrlNumber(crl); if (crlVersion.IntValue > crlSerialNumber.IntValue) { crlSerialNumber = crlVersion; } } if (isCACert) { // add a dummy revoked cert crlGen.AddCrlEntry(BigInteger.One, DateTime.UtcNow, CrlReason.Superseded); } else { // add the revoked cert crlGen.AddCrlEntry(GetSerialNumber(certificate), DateTime.UtcNow, CrlReason.PrivilegeWithdrawn); } crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(bcCertCA)); // set new serial number crlSerialNumber = crlSerialNumber.Add(BigInteger.One); crlGen.AddExtension(X509Extensions.CrlNumber, false, new CrlNumber(crlSerialNumber)); // generate updated CRL Org.BouncyCastle.X509.X509Crl updatedCrl = crlGen.Generate(signatureFactory); // add updated CRL to store X509CRL updatedCRL = new X509CRL(updatedCrl.GetEncoded()); store.AddCRL(updatedCRL); // delete outdated CRLs from store foreach (X509CRL caCrl in certCACrl) { store.DeleteCRL(caCrl); } } store.Close(); } } catch (Exception e) { throw e; } }