public void CrlBuilderTest(KeyHashPair keyHashPair) { var crlBuilder = CrlBuilder.Create(m_issuerCert.SubjectName, keyHashPair.HashAlgorithmName) .SetThisUpdate(DateTime.UtcNow.Date) .SetNextUpdate(DateTime.UtcNow.Date.AddDays(30)); // little endian byte array as serial number? byte[] serial = new byte[] { 4, 5, 6, 7 }; var revokedarray = new RevokedCertificate(serial); crlBuilder.RevokedCertificates.Add(revokedarray); string serstring = "123456789101"; var revokedstring = new RevokedCertificate(serstring); crlBuilder.RevokedCertificates.Add(revokedstring); crlBuilder.CrlExtensions.Add(X509Extensions.BuildCRLNumber(1111)); crlBuilder.CrlExtensions.Add(X509Extensions.BuildAuthorityKeyIdentifier(m_issuerCert)); var i509Crl = crlBuilder.CreateForRSA(m_issuerCert); X509CRL x509Crl = new X509CRL(i509Crl.RawData); Assert.NotNull(x509Crl); Assert.NotNull(x509Crl.CrlExtensions); Assert.NotNull(x509Crl.RevokedCertificates); Assert.AreEqual(m_issuerCert.SubjectName.RawData, x509Crl.IssuerName.RawData); Assert.AreEqual(crlBuilder.ThisUpdate, x509Crl.ThisUpdate); Assert.AreEqual(crlBuilder.NextUpdate, x509Crl.NextUpdate); Assert.AreEqual(2, x509Crl.RevokedCertificates.Count); Assert.AreEqual(serial, x509Crl.RevokedCertificates[0].UserCertificate); Assert.AreEqual(serstring, x509Crl.RevokedCertificates[1].SerialNumber); Assert.AreEqual(2, x509Crl.CrlExtensions.Count); Assert.True(x509Crl.VerifySignature(new X509Certificate2(m_issuerCert.RawData), true)); }
public void CrlInternalBuilderTest() { var dname = new X500DistinguishedName("CN=Test"); var hash = HashAlgorithmName.SHA256; var crlBuilder = CrlBuilder.Create(dname, hash) .SetNextUpdate(DateTime.Today.AddDays(30)); byte[] serial = new byte[] { 4, 5, 6, 7 }; var revokedarray = new RevokedCertificate(serial); crlBuilder.RevokedCertificates.Add(revokedarray); string serstring = "45678910"; var revokedstring = new RevokedCertificate(serstring); crlBuilder.RevokedCertificates.Add(revokedstring); crlBuilder.CrlExtensions.Add(X509Extensions.BuildCRLNumber(123)); var crlEncoded = crlBuilder.Encode(); Assert.NotNull(crlEncoded); var x509Crl = new X509CRL(); x509Crl.DecodeCrl(crlEncoded); Assert.NotNull(x509Crl); Assert.NotNull(x509Crl.CrlExtensions); Assert.NotNull(x509Crl.RevokedCertificates); Assert.AreEqual(dname.RawData, x509Crl.IssuerName.RawData); //Assert.AreEqual(crlBuilder.ThisUpdate, x509Crl.ThisUpdate); //Assert.AreEqual(crlBuilder.NextUpdate, x509Crl.NextUpdate); Assert.AreEqual(2, x509Crl.RevokedCertificates.Count); Assert.AreEqual(serial, x509Crl.RevokedCertificates[0].UserCertificate); Assert.AreEqual(serstring, x509Crl.RevokedCertificates[1].SerialNumber); Assert.AreEqual(1, x509Crl.CrlExtensions.Count); Assert.AreEqual(hash, x509Crl.HashAlgorithmName); }
/// <summary> /// Create CA test certificates. /// </summary> private void CreateCATestCerts(string tempStorePath) { Assert.IsTrue(EraseStore(tempStorePath)); string subjectName = "CN=CA Test Cert, O=OPC Foundation"; X509Certificate2 newCACert = CertificateFactory.CreateCertificate( CertificateStoreType.Directory, tempStorePath, null, null, null, subjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow, CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, true, null, null); _caCert = newCACert; // initialize cert revocation list (CRL) X509CRL newCACrl = CertificateFactory.RevokeCertificateAsync(tempStorePath, newCACert).Result; _caCrl = newCACrl; }
public override async Task Init() { await _semaphoreSlim.WaitAsync(); try { Opc.Ua.Utils.Trace(Opc.Ua.Utils.TraceMasks.Information, "InitializeCertificateGroup: {0}", m_subjectName); var result = await _keyVaultServiceClient.GetCertificateAsync(Configuration.Id).ConfigureAwait(false); Certificate = new X509Certificate2(result.Cer); if (Opc.Ua.Utils.CompareDistinguishedName(Certificate.Subject, Configuration.SubjectName)) { _caCertSecretIdentifier = result.SecretIdentifier.Identifier; _caCertKeyIdentifier = result.KeyIdentifier.Identifier; Crl = await _keyVaultServiceClient.LoadIssuerCACrl(Configuration.Id, Certificate); } else { throw new ResourceInvalidStateException("Key Vault certificate subject(" + Certificate.Subject + ") does not match cert group subject " + Configuration.SubjectName); } } catch (Exception e) { _caCertSecretIdentifier = null; _caCertKeyIdentifier = null; Certificate = null; Crl = null; throw e; } finally { _semaphoreSlim.Release(); } }
private ServiceResult AddCertificate( ISystemContext context, MethodState method, NodeId objectId, byte[] certificate, bool isTrustedCertificate) { HasSecureWriteAccess(context); lock (m_lock) { if (m_sessionId != null) { return StatusCodes.BadInvalidState; } if (certificate == null) { return StatusCodes.BadInvalidArgument; } X509Certificate2 cert = null; X509CRL crl = null; try { cert = new X509Certificate2(certificate); } catch { try { crl = new X509CRL(certificate); } catch { return StatusCodes.BadCertificateInvalid; } } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { if (cert != null) { store.Add(cert).Wait(); } if (crl != null) { store.AddCRL(crl); } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } return ServiceResult.Good; }
/// <summary> /// Revokes a certificate collection. /// Finds for each the matching CA cert version and updates Crl. /// </summary> public async Task <X509Certificate2Collection> RevokeCertificatesAsync( X509Certificate2Collection certificates) { var remainingCertificates = new X509Certificate2Collection(certificates); await LoadPublicAssets().ConfigureAwait(false); var caCertKeyInfoCollection = await _keyVaultServiceClient.GetCertificateVersionsKeyInfoAsync(Configuration.Id); DateTime now = DateTime.UtcNow; foreach (var caCertKeyInfo in caCertKeyInfoCollection) { if (remainingCertificates.Count == 0) { break; } var caRevokeCollection = new X509Certificate2Collection(); foreach (var cert in remainingCertificates) { var authorityKeyIdentifier = FindAuthorityKeyIdentifier(cert); var subjectKeyId = FindSubjectKeyIdentifierExtension(caCertKeyInfo.Certificate); if (Opc.Ua.Utils.CompareDistinguishedName(caCertKeyInfo.Certificate.Subject, cert.Issuer) && String.Equals(authorityKeyIdentifier.SerialNumber, caCertKeyInfo.Certificate.SerialNumber, StringComparison.OrdinalIgnoreCase) && String.Equals(authorityKeyIdentifier.KeyId, subjectKeyId.SubjectKeyIdentifier, StringComparison.OrdinalIgnoreCase)) { caRevokeCollection.Add(cert); } } if (caRevokeCollection.Count == 0) { continue; } var crl = await _keyVaultServiceClient.LoadIssuerCACrl(Configuration.Id, caCertKeyInfo.Certificate); var crls = new List <X509CRL>() { crl }; var newCrl = RevokeCertificate(caCertKeyInfo.Certificate, crls, caRevokeCollection, now, DateTime.MinValue, new KeyVaultSignatureGenerator(_keyVaultServiceClient, caCertKeyInfo.KeyIdentifier, caCertKeyInfo.Certificate), this.Configuration.CACertificateHashSize); await _keyVaultServiceClient.ImportIssuerCACrl(Configuration.Id, caCertKeyInfo.Certificate, newCrl).ConfigureAwait(false); foreach (var cert in caRevokeCollection) { remainingCertificates.Remove(cert); } } Crl = await _keyVaultServiceClient.LoadIssuerCACrl(Configuration.Id, Certificate); return(remainingCertificates); }
// Create an empty CRL static void CreateCACRL(string storePath, X509Certificate2 caCert) { Console.WriteLine("Creating an empty certificate revocation list (CRL) for the CA"); using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { List <X509CRL> caCRL = store.EnumerateCRLs(caCert, false); X509CRL updatedCRL = CertificateFactory.RevokeCertificate(caCert, caCRL, null); store.AddCRL(updatedCRL); } }
public void DecodeCRLs( CRLAsset crlAsset ) { var x509Crl = new X509CRL(crlAsset.Crl); Assert.NotNull(x509Crl); TestContext.Out.WriteLine($"CRLAsset: {x509Crl.Issuer}"); var crlInfo = WriteCRL(x509Crl); TestContext.Out.WriteLine(crlInfo); }
private KeyVaultCertificateGroupProvider( KeyVaultServiceClient keyVaultServiceClient, CertificateGroupConfigurationModel certificateGroupConfiguration, string serviceHost ) : base(null, certificateGroupConfiguration.ToGdsServerModel()) { _keyVaultServiceClient = keyVaultServiceClient; CertificateGroupConfiguration = certificateGroupConfiguration; _serviceHost = serviceHost ?? "localhost"; Certificate = null; Crl = null; }
/// <summary> /// Create CA certificate and Crl with new private key in KeyVault HSM. /// </summary> public async Task <bool> CreateIssuerCACertificateAsync() { await _semaphoreSlim.WaitAsync(); try { DateTime notBefore = TrimmedNotBeforeDate(); DateTime notAfter = notBefore.AddMonths(Configuration.CACertificateLifetime); // build distribution endpoint, if configured string crlDistributionPoint = BuildCrlDistributionPointUrl(); // create new CA cert in HSM storage Certificate = await _keyVaultServiceClient.CreateCACertificateAsync( Configuration.Id, Configuration.SubjectName, notBefore, notAfter, Configuration.CACertificateKeySize, Configuration.CACertificateHashSize, true, crlDistributionPoint ).ConfigureAwait(false); // update keys, ready back latest version var result = await _keyVaultServiceClient.GetCertificateAsync(Configuration.Id).ConfigureAwait(false); if (!Opc.Ua.Utils.IsEqual(result.Cer, Certificate.RawData)) { // something went utterly wrong... return(false); } _caCertSecretIdentifier = result.SecretIdentifier.Identifier; _caCertKeyIdentifier = result.KeyIdentifier.Identifier; // create default revocation list, sign with KeyVault Crl = RevokeCertificate(Certificate, null, null, notBefore, DateTime.MinValue, new KeyVaultSignatureGenerator(_keyVaultServiceClient, _caCertKeyIdentifier, Certificate), this.Configuration.CACertificateHashSize); // upload crl await _keyVaultServiceClient.ImportIssuerCACrl(Configuration.Id, Certificate, Crl).ConfigureAwait(false); return(true); } finally { _semaphoreSlim.Release(); } }
/// <summary> /// Create issuer CA cert and default Crl offline, then import in KeyVault. /// Note: Sample only for reference, importing the private key is unsecure! /// </summary> public async Task <bool> CreateImportedIssuerCACertificateAsync() { await _semaphoreSlim.WaitAsync(); try { DateTime notBefore = TrimmedNotBeforeDate(); using (var caCert = CertificateFactory.CreateCertificate( null, null, null, null, null, Configuration.SubjectName, null, Configuration.CACertificateKeySize, notBefore, Configuration.CACertificateLifetime, Configuration.CACertificateHashSize, true, null, null)) { // save only public key Certificate = new X509Certificate2(caCert.RawData); // initialize revocation list Crl = CertificateFactory.RevokeCertificate(caCert, null, null); if (Crl == null) { return(false); } // upload ca cert with private key await _keyVaultServiceClient.ImportIssuerCACertificate(Configuration.Id, new X509Certificate2Collection(caCert), true).ConfigureAwait(false); await _keyVaultServiceClient.ImportIssuerCACrl(Configuration.Id, Certificate, Crl).ConfigureAwait(false); } return(true); } finally { _semaphoreSlim.Release(); } }
/// <summary> /// Create CA test certificates. /// </summary> private async Task CreateCATestCerts(string tempStorePath) { Assert.IsTrue(EraseStore(tempStorePath)); string subjectName = "CN=CA Test Cert, O=OPC Foundation"; X509Certificate2 newCACert = CertificateFactory.CreateCertificate( null, null, subjectName, null) .SetCAConstraint() .CreateForRSA() .AddToStore(CertificateStoreType.Directory, tempStorePath); _caCert = newCACert; // initialize cert revocation list (CRL) X509CRL newCACrl = await CertificateGroup.RevokeCertificateAsync(tempStorePath, newCACert); _caCrl = newCACrl; }
public void CrlBuilderTestWithSignatureGenerator(KeyHashPair keyHashPair) { var crlBuilder = CrlBuilder.Create(m_issuerCert.SubjectName, keyHashPair.HashAlgorithmName) .SetThisUpdate(DateTime.UtcNow.Date) .SetNextUpdate(DateTime.UtcNow.Date.AddDays(30)); // little endian byte array as serial number? byte[] serial = new byte[] { 4, 5, 6, 7 }; var revokedarray = new RevokedCertificate(serial); crlBuilder.RevokedCertificates.Add(revokedarray); string serstring = "709876543210"; var revokedstring = new RevokedCertificate(serstring); crlBuilder.RevokedCertificates.Add(revokedstring); crlBuilder.CrlExtensions.Add(X509Extensions.BuildCRLNumber(1111)); crlBuilder.CrlExtensions.Add(X509Extensions.BuildAuthorityKeyIdentifier(m_issuerCert)); IX509CRL ix509Crl; using (RSA rsa = m_issuerCert.GetRSAPrivateKey()) { X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); ix509Crl = crlBuilder.CreateSignature(generator); } X509CRL x509Crl = new X509CRL(ix509Crl); Assert.NotNull(x509Crl); Assert.NotNull(x509Crl.CrlExtensions); Assert.NotNull(x509Crl.RevokedCertificates); Assert.AreEqual(m_issuerCert.SubjectName.RawData, x509Crl.IssuerName.RawData); Assert.AreEqual(crlBuilder.ThisUpdate, x509Crl.ThisUpdate); Assert.AreEqual(crlBuilder.NextUpdate, x509Crl.NextUpdate); Assert.AreEqual(2, x509Crl.RevokedCertificates.Count); Assert.AreEqual(serial, x509Crl.RevokedCertificates[0].UserCertificate); Assert.AreEqual(serstring, x509Crl.RevokedCertificates[1].SerialNumber); Assert.AreEqual(2, x509Crl.CrlExtensions.Count); using (var issuerPubKey = new X509Certificate2(m_issuerCert.RawData)) { Assert.True(x509Crl.VerifySignature(issuerPubKey, true)); } }
public async Task KeyVaultNewKeyPairAndRevokeCertificateAsync() { Skip.If(!_fixture.KeyVaultInitOk); string[] groups = await _keyVault.GetCertificateGroupIds(); foreach (string group in groups) { ApplicationTestData randomApp = _fixture.RandomGenerator.RandomApplicationTestData(); Guid requestId = Guid.NewGuid(); Opc.Ua.Gds.Server.X509Certificate2KeyPair newCert = await _keyVault.NewKeyPairRequestAsync( group, requestId.ToString(), randomApp.ApplicationRecord.ApplicationUri, randomApp.Subject, randomApp.DomainNames.ToArray(), randomApp.PrivateKeyFormat, randomApp.PrivateKeyPassword ); Assert.NotNull(newCert); Assert.False(newCert.Certificate.HasPrivateKey); Assert.True(Opc.Ua.Utils.CompareDistinguishedName(randomApp.Subject, newCert.Certificate.Subject)); Assert.False(Opc.Ua.Utils.CompareDistinguishedName(newCert.Certificate.Issuer, newCert.Certificate.Subject)); X509Certificate2 cert = new X509Certificate2(newCert.Certificate.RawData); X509CRL crl = await _keyVault.RevokeCertificateAsync(group, cert); Assert.NotNull(crl); X509Certificate2Collection caChain = await _keyVault.GetIssuerCACertificateChainAsync(group); Assert.NotNull(caChain); X509Certificate2 caCert = caChain[0]; Assert.False(caCert.HasPrivateKey); crl.VerifySignature(caCert, true); Assert.True(Opc.Ua.Utils.CompareDistinguishedName(crl.Issuer, caCert.Issuer)); // disable and delete private key from KeyVault (requires set/delete rights) await _keyVault.AcceptPrivateKeyAsync(group, requestId.ToString()); await _keyVault.DeletePrivateKeyAsync(group, requestId.ToString()); } }
/// <summary> /// Add certificate. /// </summary> public void AddCrl(X509CRL crl, bool isTrustedCertificate) { if (!IsConnected) { Connect(); } IUserIdentity oldUser = ElevatePermissions(); try { m_session.Call( ExpandedNodeId.ToNodeId(Opc.Ua.ObjectIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList, m_session.NamespaceUris), ExpandedNodeId.ToNodeId(Opc.Ua.MethodIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList_AddCertificate, m_session.NamespaceUris), crl.RawData, isTrustedCertificate ); } finally { RevertPermissions(oldUser); } }
public void GlobalSetup() { m_issuerCert = CertificateBuilder.Create("CN=Root CA") .SetCAConstraint() .CreateForRSA(); m_certificate = CertificateBuilder.Create("CN=TestCert") .SetNotBefore(DateTime.Today.AddDays(-1)) .AddExtension( new X509SubjectAltNameExtension("urn:opcfoundation.org:mypc", new string[] { "mypc", "mypc.opcfoundation.org", "192.168.1.100" })) .CreateForRSA(); var crlBuilder = CrlBuilder.Create(m_issuerCert.SubjectName, HashAlgorithmName.SHA256) .SetThisUpdate(DateTime.UtcNow.Date) .SetNextUpdate(DateTime.UtcNow.Date.AddDays(30)); var revokedarray = new RevokedCertificate(m_certificate.SerialNumber); crlBuilder.RevokedCertificates.Add(revokedarray); crlBuilder.CrlExtensions.Add(X509Extensions.BuildCRLNumber(1)); crlBuilder.CrlExtensions.Add(X509Extensions.BuildAuthorityKeyIdentifier(m_issuerCert)); m_issuerCrl = crlBuilder.CreateForRSA(m_issuerCert); m_x509Crl = new X509CRL(m_issuerCrl.RawData); var random = new Random(); m_rsaPrivateKey = m_certificate.GetRSAPrivateKey(); m_rsaPublicKey = m_certificate.GetRSAPublicKey(); // blob size for RSA padding OaepSHA256 int blobSize = m_rsaPublicKey.KeySize / 8 - 66; m_randomByteArray = new byte[blobSize]; random.NextBytes(m_randomByteArray); m_encryptedByteArray = m_rsaPublicKey.Encrypt(m_randomByteArray, RSAEncryptionPadding.OaepSHA256); m_signature = m_rsaPrivateKey.SignData(m_randomByteArray, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); }
private string WriteCRL(X509CRL x509Crl) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Issuer: {x509Crl.Issuer}"); stringBuilder.AppendLine($"ThisUpdate: {x509Crl.ThisUpdate}"); stringBuilder.AppendLine($"NextUpdate: {x509Crl.NextUpdate}"); stringBuilder.AppendLine($"RevokedCertificates:"); foreach (var revokedCert in x509Crl.RevokedCertificates) { stringBuilder.Append($"{revokedCert.SerialNumber:20}, {revokedCert.RevocationDate}, "); foreach (var entryExt in revokedCert.CrlEntryExtensions) { stringBuilder.Append($"{entryExt.Format(false)} "); } stringBuilder.AppendLine(""); } stringBuilder.AppendLine($"Extensions:"); foreach (var extension in x509Crl.CrlExtensions) { stringBuilder.AppendLine($"{extension.Format(false)}"); } return(stringBuilder.ToString()); }
private string WriteCRL(X509CRL x509Crl) { var stringBuilder = new StringBuilder(); stringBuilder.Append("Issuer: ").AppendLine(x509Crl.Issuer); stringBuilder.Append("ThisUpdate: ").Append(x509Crl.ThisUpdate).AppendLine(); stringBuilder.Append("NextUpdate: ").Append(x509Crl.NextUpdate).AppendLine(); stringBuilder.AppendLine("RevokedCertificates:"); foreach (var revokedCert in x509Crl.RevokedCertificates) { stringBuilder.AppendFormat("{0:20}", revokedCert.SerialNumber).Append(", ").Append(revokedCert.RevocationDate).Append(", "); foreach (var entryExt in revokedCert.CrlEntryExtensions) { stringBuilder.Append(entryExt.Format(false)).Append(' '); } stringBuilder.AppendLine(""); } stringBuilder.AppendLine("Extensions:"); foreach (var extension in x509Crl.CrlExtensions) { stringBuilder.AppendLine(extension.Format(false)); } return(stringBuilder.ToString()); }
/// <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 <X509CRL> RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { X509CRL updatedCRL = 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 X509Crl updatedCrl = crlGen.Generate(signatureFactory); // add updated CRL to store 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; } return(updatedCRL); }
public void Initialize(TrustListDataType trustList, X509Certificate2Collection rejectedList, bool deleteBeforeAdd) { if (deleteBeforeAdd) { CertificatesTable.Rows.Clear(); } if (trustList != null) { if ((trustList.SpecifiedLists & (uint)TrustListMasks.TrustedCertificates) != 0 && trustList.TrustedCertificates != null) { foreach (var certificateBytes in trustList.TrustedCertificates) { var certificate = new X509Certificate2(certificateBytes); List <X509CRL> crls = new List <X509CRL>(); if ((trustList.SpecifiedLists & (uint)TrustListMasks.TrustedCrls) != 0 && trustList.TrustedCrls != null) { foreach (var crlBytes in trustList.TrustedCrls) { X509CRL crl = new X509CRL(crlBytes); if (Utils.CompareDistinguishedName(crl.Issuer, certificate.Subject) && crl.VerifySignature(certificate, false)) { crls.Add(crl); } } } AddCertificate(certificate, Status.Trusted, crls); } } if ((trustList.SpecifiedLists & (uint)TrustListMasks.IssuerCertificates) != 0 && trustList.IssuerCertificates != null) { foreach (var certificateBytes in trustList.IssuerCertificates) { var certificate = new X509Certificate2(certificateBytes); List <X509CRL> crls = new List <X509CRL>(); if ((trustList.SpecifiedLists & (uint)TrustListMasks.IssuerCrls) != 0 && trustList.IssuerCrls != null) { foreach (var crlBytes in trustList.IssuerCrls) { X509CRL crl = new X509CRL(crlBytes); if (Utils.CompareDistinguishedName(crl.Issuer, certificate.Subject) && crl.VerifySignature(certificate, false)) { crls.Add(crl); } } } AddCertificate(certificate, Status.Issuer, crls); } } } if (rejectedList != null) { foreach (X509Certificate2 certificate in rejectedList) { AddCertificate(certificate, Status.Rejected, null); } } m_dataset.AcceptChanges(); NoDataWarningLabel.Visible = CertificatesTable.Rows.Count == 0; }
protected void OneTimeSetUp() { // set max RSA key size and max SHA-2 hash size ushort keySize = 4096; ushort hashSize = 512; // pki directory root for test runs. m_pkiRoot = "%LocalApplicationData%/OPC/CertValidatorTest/" + ((DateTime.UtcNow.Ticks / 10000) % 3600000).ToString() + "/"; m_issuerStore = new DirectoryCertificateStore(); m_issuerStore.Open(m_pkiRoot + "issuer"); m_trustedStore = new DirectoryCertificateStore(); m_trustedStore.Open(m_pkiRoot + "trusted"); // good applications test set var appTestDataGenerator = new ApplicationTestDataGenerator(1); m_goodApplicationTestSet = appTestDataGenerator.ApplicationTestSet(kGoodApplicationsTestCount); // create all certs and CRL m_caChain = new X509Certificate2[kCaChainCount]; m_caDupeChain = new X509Certificate2[kCaChainCount]; m_crlChain = new X509CRL[kCaChainCount]; m_crlDupeChain = new X509CRL[kCaChainCount]; m_crlRevokedChain = new X509CRL[kCaChainCount]; m_appCerts = new X509Certificate2Collection(); m_appSelfSignedCerts = new X509Certificate2Collection(); DateTime rootCABaseTime = DateTime.UtcNow; rootCABaseTime = new DateTime(rootCABaseTime.Year - 1, 1, 1); var rootCert = CertificateFactory.CreateCertificate(RootCASubject) .SetNotBefore(rootCABaseTime) .SetLifeTime(25 * 12) .SetCAConstraint() .SetHashAlgorithm(CertificateFactory.GetRSAHashAlgorithmName(hashSize)) .SetRSAKeySize(keySize) .CreateForRSA(); m_caChain[0] = rootCert; m_crlChain[0] = CertificateFactory.RevokeCertificate(rootCert, null, null); // to save time, the dupe chain uses just the default key size/hash m_caDupeChain[0] = CertificateFactory.CreateCertificate(RootCASubject) .SetNotBefore(rootCABaseTime) .SetLifeTime(25 * 12) .SetCAConstraint() .CreateForRSA(); m_crlDupeChain[0] = CertificateFactory.RevokeCertificate(m_caDupeChain[0], null, null); m_crlRevokedChain[0] = null; var signingCert = rootCert; DateTime subCABaseTime = DateTime.UtcNow; subCABaseTime = new DateTime(subCABaseTime.Year, subCABaseTime.Month, subCABaseTime.Day, 0, 0, 0, DateTimeKind.Utc); for (int i = 1; i < kCaChainCount; i++) { if (keySize > 2048) { keySize -= 1024; } if (hashSize > 256) { hashSize -= 128; } var subject = $"CN=Sub CA {i} Test Cert"; var subCACert = CertificateFactory.CreateCertificate(subject) .SetNotBefore(subCABaseTime) .SetLifeTime(5 * 12) .SetHashAlgorithm(CertificateFactory.GetRSAHashAlgorithmName(hashSize)) .SetCAConstraint(kCaChainCount - 1 - i) .SetIssuer(signingCert) .SetRSAKeySize(keySize) .CreateForRSA(); m_caChain[i] = subCACert; m_crlChain[i] = CertificateFactory.RevokeCertificate(subCACert, null, null, subCABaseTime, subCABaseTime + TimeSpan.FromDays(10)); var subCADupeCert = CertificateFactory.CreateCertificate(subject) .SetNotBefore(subCABaseTime) .SetLifeTime(5 * 12) .SetCAConstraint(kCaChainCount - 1 - i) .SetIssuer(signingCert) .CreateForRSA(); m_caDupeChain[i] = subCADupeCert; m_crlDupeChain[i] = CertificateFactory.RevokeCertificate(subCADupeCert, null, null, subCABaseTime, subCABaseTime + TimeSpan.FromDays(10)); m_crlRevokedChain[i] = null; signingCert = subCACert; } // create a CRL with a revoked Sub CA for (int i = 0; i < kCaChainCount - 1; i++) { m_crlRevokedChain[i] = CertificateFactory.RevokeCertificate( m_caChain[i], new List <X509CRL>() { m_crlChain[i] }, new X509Certificate2Collection { m_caChain[i + 1] }); } // create self signed app certs foreach (var app in m_goodApplicationTestSet) { var subject = app.Subject; var appCert = CertificateFactory.CreateCertificate( app.ApplicationUri, app.ApplicationName, subject, app.DomainNames) .CreateForRSA(); m_appSelfSignedCerts.Add(appCert); } // create signed app certs foreach (var app in m_goodApplicationTestSet) { var subject = app.Subject; var appCert = CertificateFactory.CreateCertificate( app.ApplicationUri, app.ApplicationName, subject, app.DomainNames) .SetIssuer(signingCert) .CreateForRSA(); app.Certificate = appCert.RawData; m_appCerts.Add(appCert); } // create a CRL with all apps revoked m_crlRevokedChain[kCaChainCount - 1] = CertificateFactory.RevokeCertificate( m_caChain[kCaChainCount - 1], new List <X509CRL>() { m_crlChain[kCaChainCount - 1] }, m_appCerts); }
public ObservableCollection <CertificateGroupModel> RefreshData() { try { grouped = new ObservableCollection <CertificateGroupModel>(); var TrustedCertificates = new CertificateGroupModel() { Title = "Trusted Certificates" }; var TrustedCrls = new CertificateGroupModel() { Title = "Trusted Certificate Revocation Lists" }; var IssuerCertificates = new CertificateGroupModel() { Title = "Issusers Certificates" }; var IssuerCrls = new CertificateGroupModel() { Title = "Issusers Certificate Revocation Lists" }; if (this._PushClient.ReadTrustList().TrustedCertificates.Count > 0) { foreach (var TrustedCertificate in this._PushClient.ReadTrustList().TrustedCertificates) { var cert = new X509Certificate2(TrustedCertificate); TrustedCertificates.Add(new CertificateModel { Subject = cert.Subject, ValidFrom = cert.NotBefore.ToString(), ValidTo = cert.NotAfter.ToString() }); } } if (this._PushClient.ReadTrustList().TrustedCrls.Count > 0) { foreach (var TrustedCrl in this._PushClient.ReadTrustList().TrustedCrls) { var crl = new X509CRL(TrustedCrl); TrustedCrls.Add(new CertificateModel { Subject = crl.Issuer, ValidFrom = crl.UpdateTime.ToString(), ValidTo = crl.NextUpdateTime.ToString() }); } } if (this._PushClient.ReadTrustList().IssuerCertificates.Count > 0) { foreach (var IssuerCertificate in this._PushClient.ReadTrustList().IssuerCertificates) { var cert = new X509Certificate2(IssuerCertificate); IssuerCertificates.Add(new CertificateModel { Subject = cert.Subject, ValidFrom = cert.NotBefore.ToString(), ValidTo = cert.NotAfter.ToString() }); } } if (this._PushClient.ReadTrustList().IssuerCrls.Count > 0) { foreach (var IssuerCrl in this._PushClient.ReadTrustList().IssuerCrls) { var crl = new X509CRL(IssuerCrl); IssuerCrls.Add(new CertificateModel { Subject = crl.Issuer, ValidFrom = crl.UpdateTime.ToString(), ValidTo = crl.NextUpdateTime.ToString() }); } } grouped.Add(TrustedCertificates); grouped.Add(TrustedCrls); grouped.Add(IssuerCertificates); grouped.Add(IssuerCrls); } catch (Exception ee) { Xamarin.Forms.Application.Current.MainPage.DisplayAlert("An error has occurred", "Exception message: " + ee.Message, "Dismiss"); } return(grouped); }
/// <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 <X509CRL> RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { X509CRL updatedCRL = null; 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 = X509Utils.IsCertificateAuthority(certificate); // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(certificate); if (authority != null) { keyId = authority.KeyIdentifier; serialNumber = authority.SerialNumber; } else { throw new ArgumentException("Certificate does not contain an Authority Key"); } if (!isCACert) { if (serialNumber == certificate.SerialNumber || X509Utils.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 X509Utils.FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber).ConfigureAwait(false); 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) { StorePath = storePath, StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath) }; X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword).ConfigureAwait(false); 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); var certificateCollection = new X509Certificate2Collection() { }; if (!isCACert) { certificateCollection.Add(certificate); } updatedCRL = CertificateFactory.RevokeCertificate(certCAWithPrivateKey, certCACrl, certificateCollection); store.AddCRL(updatedCRL); // delete outdated CRLs from store foreach (X509CRL caCrl in certCACrl) { store.DeleteCRL(caCrl); } store.Close(); } return(updatedCRL); }
/// <summary> /// Creates a trust list with all certs and crls in issuer and trusted list. /// i) First load all certs and crls tagged with id==Issuer or id==Trusted. /// ii) Then walk all CA cert versions and load all certs tagged with id==Issuer or id==Trusted. /// Crl is loaded too if CA cert is tagged. /// </summary> public async Task <Models.KeyVaultTrustListModel> GetTrustListAsync(string id, int?maxResults, string nextPageLink, CancellationToken ct = default) { var trustList = new Models.KeyVaultTrustListModel(id); if (maxResults == null) { maxResults = MaxResults; } Rest.Azure.IPage <SecretItem> secretItems = null; if (nextPageLink != null) { if (nextPageLink.Contains("/secrets")) { secretItems = await _keyVaultClient.GetSecretsNextAsync(nextPageLink, ct).ConfigureAwait(false); } } else { secretItems = await _keyVaultClient.GetSecretsAsync(_vaultBaseUrl, maxResults, ct).ConfigureAwait(false); } int results = 0; while (secretItems != null) { foreach (var secretItem in secretItems.Where(s => s.Tags != null)) { string tag = secretItem.Tags.FirstOrDefault(x => String.Equals(x.Key, id, StringComparison.OrdinalIgnoreCase)).Value; bool issuer = tag == TagIssuerList; bool trusted = tag == TagTrustedList; bool certType = secretItem.ContentType == ContentTypeCert; bool crlType = secretItem.ContentType == ContentTypeCrl; if (issuer || trusted && (certType || crlType)) { X509CRL crl = null; X509Certificate2 cert = null; if (certType) { var certCollection = issuer ? trustList.IssuerCertificates : trustList.TrustedCertificates; cert = await LoadCertSecret(secretItem.Identifier.Name, ct).ConfigureAwait(false); certCollection.Add(cert); } else { var crlCollection = issuer ? trustList.IssuerCrls : trustList.TrustedCrls; crl = await LoadCrlSecret(secretItem.Identifier.Name, ct).ConfigureAwait(false); crlCollection.Add(crl); } results++; } } if (secretItems.NextPageLink != null) { if (results >= maxResults) { trustList.NextPageLink = secretItems.NextPageLink; return(trustList); } else { secretItems = await _keyVaultClient.GetSecretsNextAsync(secretItems.NextPageLink, ct).ConfigureAwait(false); } } else { secretItems = null; } } Rest.Azure.IPage <CertificateItem> certItems = null; if (nextPageLink != null) { certItems = await _keyVaultClient.GetCertificateVersionsNextAsync(nextPageLink, ct).ConfigureAwait(false); } else { certItems = await _keyVaultClient.GetCertificateVersionsAsync(_vaultBaseUrl, id, maxResults, ct).ConfigureAwait(false); } while (certItems != null) { foreach (var certItem in certItems.Where(c => c.Tags != null)) { string tag = certItem.Tags.FirstOrDefault(x => String.Equals(x.Key, id, StringComparison.OrdinalIgnoreCase)).Value; bool issuer = tag == TagIssuerList; bool trusted = tag == TagTrustedList; if (issuer || trusted) { var certBundle = await _keyVaultClient.GetCertificateAsync(certItem.Id, ct).ConfigureAwait(false); var cert = new X509Certificate2(certBundle.Cer); var crl = await LoadIssuerCACrl(id, cert, ct); if (issuer) { trustList.IssuerCertificates.Add(cert); trustList.IssuerCrls.Add(crl); } else { trustList.TrustedCertificates.Add(cert); trustList.TrustedCrls.Add(crl); } results++; } } if (certItems.NextPageLink != null) { if (results >= maxResults) { trustList.NextPageLink = certItems.NextPageLink; return(trustList); } else { certItems = await _keyVaultClient.GetCertificateVersionsNextAsync(certItems.NextPageLink, ct).ConfigureAwait(false); } } else { certItems = null; } } return(trustList); }
/// <inheritdoc/> public Task AddCRL(X509CRL crl) => m_innerStore.AddCRL(crl);
/// <inheritdoc/> public Task <bool> DeleteCRL(X509CRL crl) => m_innerStore.DeleteCRL(crl);
protected void OneTimeSetUp() { // set max RSA key size and max SHA-2 hash size ushort keySize = 4096; ushort hashSize = 512; // pki directory root for test runs. m_pkiRoot = "%LocalApplicationData%/OPC/CertValidatorTest/" + ((DateTime.UtcNow.Ticks / 10000) % 3600000).ToString() + "/"; m_issuerStore = new DirectoryCertificateStore(); m_issuerStore.Open(m_pkiRoot + "issuer"); m_trustedStore = new DirectoryCertificateStore(); m_trustedStore.Open(m_pkiRoot + "trusted"); // good applications test set var appTestDataGenerator = new ApplicationTestDataGenerator(1); m_goodApplicationTestSet = appTestDataGenerator.ApplicationTestSet(kGoodApplicationsTestCount); // create all certs and CRL m_caChain = new X509Certificate2[kCaChainCount]; m_caDupeChain = new X509Certificate2[kCaChainCount]; m_caAllSameIssuerChain = new X509Certificate2[kCaChainCount]; m_crlChain = new X509CRL[kCaChainCount]; m_crlDupeChain = new X509CRL[kCaChainCount]; m_crlRevokedChain = new X509CRL[kCaChainCount]; m_appCerts = new X509Certificate2Collection(); m_appSelfSignedCerts = new X509Certificate2Collection(); DateTime rootCABaseTime = DateTime.UtcNow; rootCABaseTime = new DateTime(rootCABaseTime.Year - 1, 1, 1); var rootCert = CertificateFactory.CreateCertificate( null, null, null, null, null, "CN=Root CA Test Cert", null, keySize, rootCABaseTime, 25 * 12, hashSize, true, pathLengthConstraint: -1); m_caChain[0] = rootCert; m_crlChain[0] = CertificateFactory.RevokeCertificate(rootCert, null, null); m_caDupeChain[0] = CertificateFactory.CreateCertificate( null, null, null, null, null, "CN=Root CA Test Cert", null, keySize, rootCABaseTime, 25 * 12, hashSize, true, pathLengthConstraint: -1); m_crlDupeChain[0] = CertificateFactory.RevokeCertificate(m_caDupeChain[0], null, null); m_crlRevokedChain[0] = null; var signingCert = rootCert; DateTime subCABaseTime = DateTime.UtcNow; subCABaseTime = new DateTime(subCABaseTime.Year, subCABaseTime.Month, subCABaseTime.Day); for (int i = 1; i < kCaChainCount; i++) { if (keySize > 2048) { keySize -= 1024; } if (hashSize > 256) { hashSize -= 128; } var subject = $"CN=Sub CA {i} Test Cert"; var subCACert = CertificateFactory.CreateCertificate( null, null, null, null, null, subject, null, keySize, subCABaseTime, 5 * 12, hashSize, true, signingCert, pathLengthConstraint: kCaChainCount - 1 - i); m_caChain[i] = subCACert; m_crlChain[i] = CertificateFactory.RevokeCertificate(subCACert, null, null, subCABaseTime, subCABaseTime + TimeSpan.FromDays(10)); var subCADupeCert = CertificateFactory.CreateCertificate( null, null, null, null, null, subject, null, keySize, subCABaseTime, 5 * 12, hashSize, true, signingCert, pathLengthConstraint: kCaChainCount - 1 - i); m_caDupeChain[i] = subCADupeCert; m_crlDupeChain[i] = CertificateFactory.RevokeCertificate(subCADupeCert, null, null, subCABaseTime, subCABaseTime + TimeSpan.FromDays(10)); m_crlRevokedChain[i] = null; signingCert = subCACert; } // create a CRL with a revoked Sub CA for (int i = 0; i < kCaChainCount - 1; i++) { m_crlRevokedChain[i] = CertificateFactory.RevokeCertificate( m_caChain[i], new List <X509CRL>() { m_crlChain[i] }, new X509Certificate2Collection { m_caChain[i + 1] }); } // create self signed app certs DateTime appBaseTime = DateTime.UtcNow - TimeSpan.FromDays(1); foreach (var app in m_goodApplicationTestSet) { var subject = app.Subject; var appCert = CertificateFactory.CreateCertificate( null, null, null, app.ApplicationUri, app.ApplicationName, subject, app.DomainNames, CertificateFactory.DefaultKeySize, appBaseTime, 2 * 12, CertificateFactory.DefaultHashSize); m_appSelfSignedCerts.Add(appCert); } // create signed app certs foreach (var app in m_goodApplicationTestSet) { var subject = app.Subject; var appCert = CertificateFactory.CreateCertificate( null, null, null, app.ApplicationUri, app.ApplicationName, subject, app.DomainNames, CertificateFactory.DefaultKeySize, appBaseTime, 2 * 12, CertificateFactory.DefaultHashSize, false, signingCert); app.Certificate = appCert.RawData; m_appCerts.Add(appCert); } // create a CRL with all apps revoked m_crlRevokedChain[kCaChainCount - 1] = CertificateFactory.RevokeCertificate( m_caChain[kCaChainCount - 1], new List <X509CRL>() { m_crlChain[kCaChainCount - 1] }, m_appCerts); }
public void DecodeCRLSignature() { _ = new X509CRL(m_issuerCrl.RawData); }