public async Task <X509CertificateCollection> KeyVaultSigningRequestAsync()
        {
            Skip.If(!_fixture.KeyVaultInitOk);
            X509CertificateCollection certCollection = new X509CertificateCollection();

            string[] groups = await _keyVault.GetCertificateGroupIds();

            foreach (string group in groups)
            {
                var certificateGroupConfiguration = await _keyVault.GetCertificateGroupConfiguration(group);

                ApplicationTestData randomApp      = _fixture.RandomGenerator.RandomApplicationTestData();
                X509Certificate2    csrCertificate = CertificateFactory.CreateCertificate(
                    null, null, null,
                    randomApp.ApplicationRecord.ApplicationUri,
                    null,
                    randomApp.Subject,
                    randomApp.DomainNames.ToArray(),
                    certificateGroupConfiguration.DefaultCertificateKeySize,
                    DateTime.UtcNow.AddDays(-10),
                    certificateGroupConfiguration.DefaultCertificateLifetime,
                    certificateGroupConfiguration.DefaultCertificateHashSize
                    );
                byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, randomApp.DomainNames);

                X509Certificate2 newCert = await _keyVault.SigningRequestAsync(
                    group,
                    randomApp.ApplicationRecord.ApplicationUri,
                    certificateRequest);

                // get issuer cert used for signing
                X509Certificate2Collection issuerCerts = await _keyVault.GetIssuerCACertificateChainAsync(group);

#if WRITECERT
                // save cert for debugging
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreType.Directory))
                {
                    Assert.NotNull(store);
                    store.Open("d:\\unittest");
                    await store.Add(newCert);

                    foreach (var cert in issuerCerts)
                    {
                        await store.Add(cert);
                    }
                }
#endif
                Assert.NotNull(issuerCerts);
                Assert.True(issuerCerts.Count >= 1);
                X509TestUtils.VerifySignedApplicationCert(randomApp, newCert, issuerCerts);
                certCollection.Add(newCert);
            }
            return(certCollection);
        }
        /// <summary>
        /// Saves the certificate in the rejected certificate store.
        /// </summary>
        private void SaveCertificate(X509Certificate2 certificate)
        {
            lock (m_lock)
            {
                if (m_rejectedCertificateStore != null)
                {
                    Utils.Trace((int)Utils.TraceMasks.Error, "Writing rejected certificate to directory: {0}", m_rejectedCertificateStore);
                    try
                    {
                        ICertificateStore store = m_rejectedCertificateStore.OpenStore();

                        try
                        {
                            store.Delete(certificate.Thumbprint);
                            store.Add(certificate);
                        }
                        finally
                        {
                            store.Close();
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace(e, "Could not write certificate to directory: {0}", m_rejectedCertificateStore);
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Updates the certificate authority certificate and CRL in the trusted list.
        /// </summary>
        private async Task UpdateAuthorityCertInTrustedList()
        {
            string trustedListStorePath = Configuration.TrustedListPath;

            if (!String.IsNullOrEmpty(Configuration.TrustedListPath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(trustedListStorePath))
                {
                    X509Certificate2Collection certs = await store.FindByThumbprint(Certificate.Thumbprint);

                    if (certs.Count == 0)
                    {
                        await store.Add(Certificate);
                    }

                    // delete existing CRL in trusted list
                    foreach (var crl in store.EnumerateCRLs(Certificate, false))
                    {
                        if (crl.VerifySignature(Certificate, false))
                        {
                            store.DeleteCRL(crl);
                        }
                    }

                    // copy latest CRL to trusted list
                    using (ICertificateStore storeAuthority = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
                    {
                        foreach (var crl in storeAuthority.EnumerateCRLs(Certificate, true))
                        {
                            store.AddCRL(crl);
                        }
                    }
                }
            }
        }
        public async Task TestNoFileConfigAsServerX509Store()
        {
#if NETCOREAPP2_1_OR_GREATER
            // this test fails on macOS, ignore
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Assert.Ignore("X509Store trust lists not supported on mac OS.");
            }
#endif
            var applicationInstance = new ApplicationInstance()
            {
                ApplicationName = ApplicationName
            };
            Assert.NotNull(applicationInstance);
            ApplicationConfiguration config = await applicationInstance.Build(ApplicationUri, ProductUri)
                                              .AsServer(new string[] { "opc.tcp://localhost:51000" })
                                              .AddUnsecurePolicyNone()
                                              .AddSignAndEncryptPolicies()
                                              .AddUserTokenPolicy(UserTokenType.UserName)
                                              .AsClient()
                                              .SetDefaultSessionTimeout(10000)
                                              .AddSecurityConfiguration(SubjectName, CertificateStoreType.X509Store)
                                              .Create().ConfigureAwait(false);

            Assert.NotNull(config);
            bool certOK = await applicationInstance.CheckApplicationInstanceCertificate(true, 0).ConfigureAwait(false);

            using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore())
            {
                await store.Add(applicationInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate);
            }
            Assert.True(certOK);
        }
Exemple #5
0
        public async Task VerifyAppChainsOneTrusted()
        {
            var stopWatch = new Stopwatch();

            stopWatch.Start();
            // verify cert with issuer chain
            for (int v = 0; v < kCaChainCount; v++)
            {
                long start = stopWatch.ElapsedMilliseconds;
                TestContext.Out.WriteLine($"Chain Number {v}, Total Elapsed: {start}");
                CleanupValidatorAndStores();
                TestContext.Out.WriteLine($"Cleanup: {stopWatch.ElapsedMilliseconds-start}");
                for (int i = 0; i < kCaChainCount; i++)
                {
                    ICertificateStore store = i == v ? m_trustedStore : m_issuerStore;
                    await store.Add(m_caChain[i]);

                    store.AddCRL(m_crlChain[i]);
                }
                TestContext.Out.WriteLine($"AddChains: {stopWatch.ElapsedMilliseconds - start}");
                var certValidator = InitValidatorWithStores();
                TestContext.Out.WriteLine($"InitValidator: {stopWatch.ElapsedMilliseconds - start}");
                foreach (var app in m_goodApplicationTestSet)
                {
                    certValidator.Validate(new X509Certificate2(app.Certificate));
                }
                TestContext.Out.WriteLine($"Validation: {stopWatch.ElapsedMilliseconds - start}");
            }
            TestContext.Out.WriteLine($"Total: {stopWatch.ElapsedMilliseconds}");
        }
        private void PasteMI_Click(object sender, EventArgs e)
        {
            try
            {
                string xml = (string)ClipboardHack.GetData(DataFormats.Text);

                if (String.IsNullOrEmpty(xml))
                {
                    return;
                }

                // deserialize the data.
                CertificateIdentifier id = null;

                using (XmlTextReader reader = new XmlTextReader(new StringReader(xml)))
                {
                    DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateIdentifier));
                    id = (CertificateIdentifier)serializer.ReadObject(reader, false);
                }

                if (id.Certificate != null)
                {
                    using (ICertificateStore store = m_storeId.OpenStore())
                    {
                        store.Add(id.Certificate);
                    }

                    AddItem(id.Certificate);
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Exemple #7
0
        protected async Task UpdateGroupStore(string storePath, X509Certificate2Collection certs, IList <Opc.Ua.X509CRL> crls)
        {
            if (!String.IsNullOrEmpty(storePath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    X509Certificate2Collection oldCertificates = await store.Enumerate();

                    foreach (var cert in oldCertificates)
                    {
                        await store.Delete(cert.Thumbprint);
                    }
                    foreach (var crl in store.EnumerateCRLs())
                    {
                        store.DeleteCRL(crl);
                    }
                    foreach (var cert in certs)
                    {
                        await store.Add(cert);
                    }
                    foreach (var crl in crls)
                    {
                        store.AddCRL(crl);
                    }
                }
            }
        }
        /// <summary>
        /// Synchronous helper implementation of CheckApplicationInstanceCertificate for C++ Proxy
        /// </summary>
        public static void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration)
        {
            // create a default certificate id none specified.
            CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate;

            if (id == null)
            {
                id             = new CertificateIdentifier();
                id.StoreType   = Utils.DefaultStoreType;
                id.StorePath   = Utils.DefaultStorePath;
                id.SubjectName = configuration.ApplicationName;
            }

            // check for certificate with a private key.
            X509Certificate2 certificate = id.Find(true).Result;

            if (certificate != null)
            {
                return;
            }

            // construct the subject name from the
            List <string> hostNames = new List <string>();

            hostNames.Add(Utils.GetHostName());

            string commonName  = Utils.Format("CN={0}", configuration.ApplicationName);
            string domainName  = Utils.Format("DC={0}", hostNames[0]);
            string subjectName = Utils.Format("{0}, {1}", commonName, domainName);

            // create a new certificate with a new public key pair.
            certificate = CertificateFactory.CreateCertificate(
                configuration.ApplicationUri,
                configuration.ApplicationName,
                subjectName,
                hostNames)
                          .CreateForRSA()
                          .AddToStore(
                id.StoreType,
                id.StorePath);

            id.Certificate = certificate;

            // update and save the configuration file.
            configuration.SaveToFile(configuration.SourceFilePath);

            // add certificate to the trusted peer store so other applications will trust it.
            using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore())
            {
                X509Certificate2Collection certificateCollection = store.FindByThumbprint(certificate.Thumbprint).Result;
                if (certificateCollection != null)
                {
                    store.Add(certificateCollection[0]).Wait();
                }
            }

            // tell the certificate validator about the new certificate.
            configuration.CertificateValidator.Update(configuration.SecurityConfiguration).Wait();
        }
        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;
        }
Exemple #10
0
        /// <summary>
        /// Handles a drop event.
        /// </summary>
        protected override void NodesTV_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                TreeNode node = NodesTV.GetNodeAt(PointToClient(new Point(e.X, e.Y)));

                if (node == null)
                {
                    return;
                }

                ContainerInfo info = node.Tag as ContainerInfo;

                if (info == null)
                {
                    return;
                }

                if (info.Type == ContainerInfoType.Store)
                {
                    CertificateStoreIdentifier id = info.GetCertificateStore();

                    if (id == null)
                    {
                        return;
                    }

                    object[] certificates = e.Data.GetData(typeof(object[])) as object[];

                    if (certificates == null)
                    {
                        return;
                    }

                    using (ICertificateStore store = id.OpenStore())
                    {
                        for (int ii = 0; ii < certificates.Length; ii++)
                        {
                            X509Certificate2 certificate = certificates[ii] as X509Certificate2;

                            if (certificate != null)
                            {
                                store.Add(certificate);
                            }
                        }
                    }

                    NodesTV.SelectedNode = node;
                    return;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
        public async Task TestNoFileConfigAsServerX509Store()
        {
#if NETCOREAPP2_1_OR_GREATER
            // this test fails on macOS, ignore
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Assert.Ignore("X509Store trust lists not supported on mac OS.");
            }
#endif
            var applicationInstance = new ApplicationInstance()
            {
                ApplicationName = ApplicationName
            };
            Assert.NotNull(applicationInstance);
            ApplicationConfiguration config = await applicationInstance.Build(ApplicationUri, ProductUri)
                                              .AsServer(new string[] { EndpointUrl })
                                              .AddUnsecurePolicyNone()
                                              .AddSignAndEncryptPolicies()
                                              .AddUserTokenPolicy(UserTokenType.UserName)
                                              .AsClient()
                                              .SetDefaultSessionTimeout(10000)
                                              .AddSecurityConfiguration(SubjectName, CertificateStoreType.X509Store)
                                              .Create().ConfigureAwait(false);

            Assert.NotNull(config);
            var  applicationCertificate = applicationInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate;
            bool deleteAfterUse         = applicationCertificate.Certificate != null;

            bool certOK = await applicationInstance.CheckApplicationInstanceCertificate(true, 0).ConfigureAwait(false);

            Assert.True(certOK);
            using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore())
            {
                // store public key in trusted store
                var rawData = applicationCertificate.Certificate.RawData;
                await store.Add(new X509Certificate2(rawData));
            }

            if (deleteAfterUse)
            {
                var thumbprint = applicationCertificate.Certificate.Thumbprint;
                using (ICertificateStore store = applicationCertificate.OpenStore())
                {
                    bool success = await store.Delete(thumbprint);

                    Assert.IsTrue(success);
                }
                using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore())
                {
                    bool success = await store.Delete(thumbprint);

                    Assert.IsTrue(success);
                }
            }
        }
        private ServiceResult AddCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] certificate,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

            ServiceResult result = StatusCodes.Good;

            lock (m_lock)
            {
                if (m_sessionId != null)
                {
                    result = StatusCodes.BadInvalidState;
                }
                else if (certificate == null)
                {
                    result = StatusCodes.BadInvalidArgument;
                }
                else
                {
                    X509Certificate2 cert = null;
                    try
                    {
                        cert = new X509Certificate2(certificate);
                    }
                    catch
                    {
                        // note: a previous version of the sample code accepted also CRL,
                        // but the behaviour was not as specified and removed
                        // https://mantis.opcfoundation.org/view.php?id=6342
                        result = StatusCodes.BadCertificateInvalid;
                    }

                    using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                    {
                        if (cert != null)
                        {
                            store.Add(cert).GetAwaiter().GetResult();
                        }
                    }

                    m_node.LastUpdateTime.Value = DateTime.UtcNow;
                }
            }

            // report the TrustListUpdatedAuditEvent
            object[] inputParameters = new object[] { certificate, isTrustedCertificate };
            m_node.ReportTrustListUpdatedAuditEvent(context, objectId, "Method/AddCertificate", method.NodeId, inputParameters, result.StatusCode);

            return(result);
        }
Exemple #13
0
        private void ImportMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string directory = Environment.CurrentDirectory;

                if (m_certificateFile != null)
                {
                    directory = m_certificateFile.DirectoryName;
                }

                OpenFileDialog dialog = new OpenFileDialog
                {
                    CheckFileExists  = true,
                    CheckPathExists  = true,
                    DefaultExt       = "*.der",
                    Filter           = "Certificate Files (*.der)|*.der|All Files (*.*)|*.*",
                    Title            = "Import Certificate",
                    Multiselect      = false,
                    ValidateNames    = true,
                    FileName         = m_certificateFile?.Name,
                    InitialDirectory = directory,
                    RestoreDirectory = true
                };

                if (dialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                m_certificateFile = new FileInfo(dialog.FileName);

                X509Certificate2 certificate = CertificateFactory.Load(new X509Certificate2(File.ReadAllBytes(dialog.FileName)), false);

                if (certificate != null)
                {
                    if (!String.IsNullOrEmpty(m_trustedStorePath))
                    {
                        using (ICertificateStore store = CreateStore(m_trustedStorePath))
                        {
                            store.Add(certificate);
                        }
                    }
                }

                AddCertificate(certificate, Status.Trusted, null);
                NoDataWarningLabel.Visible = CertificatesTable.Rows.Count == 0;
            }
            catch (Exception ex)
            {
                Opc.Ua.Client.Controls.ExceptionDlg.Show(Text, ex);
            }
        }
Exemple #14
0
        public async Task VerifyAppChainsWithGoodAndInvalidChain()
        {
            // verify cert with issuer chain
            for (int v = 0; v < kCaChainCount; v++)
            {
                CleanupValidatorAndStores();
                for (int i = 0; i < kCaChainCount; i++)
                {
                    ICertificateStore store = i == v ? m_trustedStore : m_issuerStore;
                    await store.Add(m_caChain[i]);

                    store.AddCRL(m_crlChain[i]);
                    await store.Add(m_caDupeChain[i]);

                    store.AddCRL(m_crlDupeChain[i]);
                }
                var certValidator = InitValidatorWithStores();
                foreach (var app in m_goodApplicationTestSet)
                {
                    certValidator.Validate(new X509Certificate2(app.Certificate));
                }
            }
        }
Exemple #15
0
        private void MoveCertificate(DataRow row, Status status)
        {
            Status oldStatus = (Status)row[4];

            row[4] = status;
            SetIcon(row, status);

            string targetStorePath = null;

            switch (status)
            {
            case Status.Trusted: { targetStorePath = m_trustedStorePath; break; }

            case Status.Issuer: { targetStorePath = m_issuerStorePath; break; }

            case Status.Rejected: { targetStorePath = m_rejectedStorePath; break; }
            }

            string oldStorePath = null;

            switch (oldStatus)
            {
            case Status.Trusted: { oldStorePath = m_trustedStorePath; break; }

            case Status.Issuer: { oldStorePath = m_issuerStorePath; break; }

            case Status.Rejected: { oldStorePath = m_rejectedStorePath; break; }
            }

            X509Certificate2 certificate = (X509Certificate2)row[7];

            if (oldStorePath != targetStorePath)
            {
                if (!String.IsNullOrEmpty(targetStorePath))
                {
                    using (ICertificateStore store = CreateStore(targetStorePath))
                    {
                        store.Add(certificate);
                    }
                }

                if (!String.IsNullOrEmpty(oldStorePath))
                {
                    using (ICertificateStore store = CreateStore(oldStorePath))
                    {
                        store.Delete(certificate.Thumbprint);
                    }
                }
            }
        }
 /// <summary>
 /// Add to certificate store
 /// </summary>
 /// <param name="store"></param>
 /// <param name="certificates"></param>
 /// <param name="noCopy"></param>
 /// <returns></returns>
 public static void Add(this ICertificateStore store,
                        IEnumerable <X509Certificate2> certificates,
                        bool noCopy = false)
 {
     if (certificates == null)
     {
         throw new ArgumentNullException(nameof(certificates));
     }
     foreach (var cert in certificates)
     {
         Try.Op(() => store.Delete(cert.Thumbprint));
         store.Add(noCopy ? cert : new X509Certificate2(cert));
     }
 }
Exemple #17
0
        /// <summary>
        /// Saves the certificate in the invalid certificate directory.
        /// </summary>
        private void SaveCertificate(X509Certificate2 certificate)
        {
            try {
                ICertificateStore store = m_rejectedCertificateStore.OpenStore();

                try {
                    store.Delete(certificate.Thumbprint);
                    store.Add(certificate);
                } finally {
                    store.Close();
                }
            } catch (Exception e) {
                Utils.Trace(e, "Could not write certificate to directory: {0}", m_rejectedCertificateStore);
            }
        }
Exemple #18
0
        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;
                try
                {
                    cert = new X509Certificate2(certificate);
                }
                catch
                {
                    // note: a previous version of the sample code accepted also CRL,
                    // but the behaviour was not as specified and removed
                    // https://mantis.opcfoundation.org/view.php?id=6342
                    return(StatusCodes.BadCertificateInvalid);
                }

                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                {
                    if (cert != null)
                    {
                        store.Add(cert).Wait();
                    }
                }

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return(ServiceResult.Good);
        }
Exemple #19
0
        private void PasteMI_Click(object sender, EventArgs e)
        {
            try
            {
                string xml = (string)ClipboardHack.GetData(DataFormats.Text);

                if (String.IsNullOrEmpty(xml))
                {
                    return;
                }

                // check if in the favorites list.
                ContainerInfo info = NodesTV.SelectedNode.Tag as ContainerInfo;

                // check if pasting into a store.
                if (info.Type == ContainerInfoType.Store)
                {
                    CertificateIdentifier id = null;

                    using (XmlTextReader reader = new XmlTextReader(new StringReader(xml)))
                    {
                        DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateIdentifier));
                        id = (CertificateIdentifier)serializer.ReadObject(reader, false);
                    }

                    if (id.Certificate != null)
                    {
                        CertificateStoreIdentifier storeId = info.GetCertificateStore();

                        using (ICertificateStore store = storeId.OpenStore())
                        {
                            store.Add(id.Certificate);
                        }
                    }

                    SelectNode();
                    return;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Exemple #20
0
        /// <summary>
        /// Adds an application certificate to a store.
        /// </summary>
        private static void AddApplicationCertificateToStore(
            CertificateStoreIdentifier csid,
            X509Certificate2 certificate,
            string oldThumbprint)
        {
            ICertificateStore store = csid.OpenStore();

            try
            {
                // delete the old certificate.
                if (oldThumbprint != null)
                {
                    store.Delete(oldThumbprint);
                }

                // delete certificates with the same application uri.
                if (store.FindByThumbprint(certificate.Thumbprint) != null)
                {
                    return;
                }
                string applicationUri = Utils.GetApplicationUriFromCertficate(certificate);

                // delete any existing certificates.
                foreach (X509Certificate2 target in store.Enumerate())
                {
                    if (!Utils.CompareDistinguishedName(target.Subject, certificate.Subject))
                    {
                        continue;
                    }
                    if (Utils.GetApplicationUriFromCertficate(target) == applicationUri)
                    {
                        store.Delete(target.Thumbprint);
                    }
                }

                // add new certificate.
                store.Add(new X509Certificate2(certificate.RawData));
            }
            finally
            {
                store.Close();
            }
        }
        /// <summary>
        /// Adds the certificate to the Trusted Certificate Store
        /// </summary>
        /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param>
        /// <param name="certificate">The certificate to register.</param>
        public static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate)
        {
            ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();

            try
            {
                // check if it already exists.
                X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint);

                if (existingCertificates.Count > 0)
                {
                    return;
                }

                List <string> subjectName = Utils.ParseDistinguishedName(certificate.Subject);

                // check for old certificate.
                X509Certificate2Collection certificates = await store.Enumerate();

                for (int ii = 0; ii < certificates.Count; ii++)
                {
                    if (Utils.CompareDistinguishedName(certificates[ii], subjectName))
                    {
                        if (certificates[ii].Thumbprint == certificate.Thumbprint)
                        {
                            return;
                        }

                        await store.Delete(certificates[ii].Thumbprint);

                        break;
                    }
                }

                // add new certificate.
                X509Certificate2 publicKey = new X509Certificate2(certificate.RawData);
                await store.Add(publicKey);
            }
            finally
            {
                store.Close();
            }
        }
        /// <summary>
        /// Updates the certificate authority certificate and CRL in the trusted list.
        /// </summary>
        protected async Task UpdateAuthorityCertInTrustedList()
        {
            string trustedListStorePath = Configuration.TrustedListPath;

            if (!String.IsNullOrEmpty(Configuration.TrustedListPath))
            {
                using (ICertificateStore authorityStore = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
                    using (ICertificateStore trustedStore = CertificateStoreIdentifier.OpenStore(trustedListStorePath))
                    {
                        X509Certificate2Collection certificates = await authorityStore.Enumerate();

                        foreach (var certificate in certificates)
                        {
                            if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName))
                            {
                                X509Certificate2Collection certs = await trustedStore.FindByThumbprint(certificate.Thumbprint);

                                if (certs.Count == 0)
                                {
                                    await trustedStore.Add(new X509Certificate2(certificate.RawData));
                                }

                                // delete existing CRL in trusted list
                                foreach (var crl in trustedStore.EnumerateCRLs(certificate, false))
                                {
                                    if (crl.VerifySignature(certificate, false))
                                    {
                                        trustedStore.DeleteCRL(crl);
                                    }
                                }

                                // copy latest CRL to trusted list
                                foreach (var crl in authorityStore.EnumerateCRLs(certificate, true))
                                {
                                    trustedStore.AddCRL(crl);
                                }
                            }
                        }
                    }
            }
        }
Exemple #23
0
        private async Task <bool> UpdateStoreCertificates(
            CertificateTrustList trustList,
            X509Certificate2Collection updatedCerts)
        {
            bool result             = true;
            ICertificateStore store = null;

            try
            {
                store = trustList.OpenStore();
                var storeCerts = await store.Enumerate().ConfigureAwait(false);

                foreach (var cert in storeCerts)
                {
                    if (!updatedCerts.Contains(cert))
                    {
                        if (!store.Delete(cert.Thumbprint).Result)
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        updatedCerts.Remove(cert);
                    }
                }
                foreach (var cert in updatedCerts)
                {
                    await store.Add(cert).ConfigureAwait(false);
                }
            }
            catch
            {
                result = false;
            }
            finally
            {
                store?.Close();
            }
            return(result);
        }
Exemple #24
0
        private async Task <bool> UpdateStoreCertificates(
            string storePath,
            X509Certificate2Collection updatedCerts)
        {
            bool result = true;

            try
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    var storeCerts = await store.Enumerate().ConfigureAwait(false);

                    foreach (var cert in storeCerts)
                    {
                        if (!updatedCerts.Contains(cert))
                        {
                            if (!await store.Delete(cert.Thumbprint).ConfigureAwait(false))
                            {
                                result = false;
                            }
                        }
                        else
                        {
                            updatedCerts.Remove(cert);
                        }
                    }
                    foreach (var cert in updatedCerts)
                    {
                        await store.Add(cert).ConfigureAwait(false);
                    }
                }
            }
            catch
            {
                result = false;
            }
            return(result);
        }
Exemple #25
0
        /// <summary>
        /// Extension to add a certificate to a <see cref="ICertificateStore"/>.
        /// </summary>
        /// <remarks>
        /// Saves also the private key, if available.
        /// If written to a Pfx file, the password is used for protection.
        /// </remarks>
        /// <param name="certificate">The certificate to store.</param>
        /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param>
        /// <param name="storePath">The store path (syntax depends on storeType).</param>
        /// <param name="password">The password to use to protect the certificate.</param>
        /// <returns></returns>
        public static X509Certificate2 AddToStore(
            this X509Certificate2 certificate,
            string storeType,
            string storePath,
            string password = null)
        {
            // add cert to the store.
            if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType))
            {
                using (ICertificateStore store = Opc.Ua.CertificateStoreIdentifier.CreateStore(storeType))
                {
                    if (store == null)
                    {
                        throw new ArgumentException("Invalid store type");
                    }

                    store.Open(storePath);
                    store.Add(certificate, password).Wait();
                    store.Close();
                }
            }
            return(certificate);
        }
Exemple #26
0
        private bool UpdateStoreCertificates(
            string storePath,
            X509Certificate2Collection updatedCerts)
        {
            bool result = true;

            try
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    var storeCerts = store.Enumerate().Result;
                    foreach (var cert in storeCerts)
                    {
                        if (!updatedCerts.Contains(cert))
                        {
                            if (!store.Delete(cert.Thumbprint).Result)
                            {
                                result = false;
                            }
                        }
                        else
                        {
                            updatedCerts.Remove(cert);
                        }
                    }
                    foreach (var cert in updatedCerts)
                    {
                        store.Add(cert).Wait();
                    }
                }
            }
            catch
            {
                result = false;
            }
            return(result);
        }
Exemple #27
0
        /// <summary>
        /// Adds the certificate to the Trusted Certificate Store
        /// </summary>
        /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param>
        /// <param name="certificate">The certificate to register.</param>
        private static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            string storePath = null;

            if (configuration != null && configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null)
            {
                storePath = configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath;
            }

            if (String.IsNullOrEmpty(storePath))
            {
                Utils.Trace(Utils.TraceMasks.Information, "WARNING: Trusted peer store not specified.");
                return;
            }

            try
            {
                ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();

                if (store == null)
                {
                    Utils.Trace("Could not open trusted peer store. StorePath={0}", storePath);
                    return;
                }

                try
                {
                    // check if it already exists.
                    X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint);

                    if (existingCertificates.Count > 0)
                    {
                        return;
                    }

                    Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", storePath);

                    List <string> subjectName = X509Utils.ParseDistinguishedName(certificate.Subject);

                    // check for old certificate.
                    X509Certificate2Collection certificates = await store.Enumerate();

                    for (int ii = 0; ii < certificates.Count; ii++)
                    {
                        if (X509Utils.CompareDistinguishedName(certificates[ii], subjectName))
                        {
                            if (certificates[ii].Thumbprint == certificate.Thumbprint)
                            {
                                return;
                            }

                            await store.Delete(certificates[ii].Thumbprint);

                            break;
                        }
                    }

                    // add new certificate.
                    X509Certificate2 publicKey = new X509Certificate2(certificate.RawData);
                    await store.Add(publicKey);
                }
                finally
                {
                    store.Close();
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", storePath);
            }
        }
Exemple #28
0
        private ServiceResult UpdateCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            byte[] certificate,
            byte[][] issuerCertificates,
            string privateKeyFormat,
            byte[] privateKey,
            ref bool applyChangesRequired)
        {
            HasApplicationSecureAdminAccess(context);

            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            privateKeyFormat = privateKeyFormat?.ToUpper();
            if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX"))
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported.");
            }

            ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId);

            certificateGroup.UpdateCertificate = null;

            X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection();
            X509Certificate2           newCert;

            try
            {
                // build issuer chain
                if (issuerCertificates != null)
                {
                    foreach (byte[] issuerRawCert in issuerCertificates)
                    {
                        var newIssuerCert = new X509Certificate2(issuerRawCert);
                        newIssuerCollection.Add(newIssuerCert);
                    }
                }

                newCert = new X509Certificate2(certificate);
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid.");
            }

            // validate new subject matches the previous subject
            if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name))
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application.");
            }

            // self signed
            bool selfSigned = X509Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer);

            if (selfSigned && newIssuerCollection.Count != 0)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate.");
            }

            if (!selfSigned)
            {
                try
                {
                    // verify cert with issuer chain
                    CertificateValidator            certValidator    = new CertificateValidator();
                    CertificateTrustList            issuerStore      = new CertificateTrustList();
                    CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection();
                    foreach (var issuerCert in newIssuerCollection)
                    {
                        issuerCollection.Add(new CertificateIdentifier(issuerCert));
                    }
                    issuerStore.TrustedCertificates = issuerCollection;
                    certValidator.Update(issuerStore, issuerStore, null);
                    certValidator.Validate(newCert);
                }
                catch
                {
                    throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list.");
                }
            }

            var updateCertificate = new UpdateCertificateData();

            try
            {
                var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider;
                switch (privateKeyFormat)
                {
                case null:
                case "":
                {
                    X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result;
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PFX":
                {
                    X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate));
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PEM":
                {
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate));
                    break;
                }
                }
                updateCertificate.IssuerCollection = newIssuerCollection;
                updateCertificate.SessionId        = context.SessionId;
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key.");
            }

            certificateGroup.UpdateCertificate = updateCertificate;
            applyChangesRequired = true;

            if (updateCertificate != null)
            {
                try
                {
                    using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore())
                    {
                        Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate);
                        appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait();
                        Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey);
                        var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider;
                        appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait();
                        // keep only track of cert without private key
                        var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData);
                        updateCertificate.CertificateWithPrivateKey.Dispose();
                        updateCertificate.CertificateWithPrivateKey = certOnly;
                    }
                    using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath))
                    {
                        foreach (var issuer in updateCertificate.IssuerCollection)
                        {
                            try
                            {
                                Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer);
                                issuerStore.Add(issuer).Wait();
                            }
                            catch (ArgumentException)
                            {
                                // ignore error if issuer cert already exists
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex));
                    throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex);
                }
            }

            return(ServiceResult.Good);
        }
    /// <summary>
    /// Creates a self signed application instance certificate.
    /// </summary>
    /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param>
    /// <param name="storePath">The store path (syntax depends on storeType).</param>
    /// <param name="password">The password to use to protect the certificate.</param>
    /// <param name="applicationUri">The application uri (created if not specified).</param>
    /// <param name="applicationName">Name of the application (optional if subjectName is specified).</param>
    /// <param name="subjectName">The subject used to create the certificate (optional if applicationName is specified).</param>
    /// <param name="domainNames">The domain names that can be used to access the server machine (defaults to local computer name if not specified).</param>
    /// <param name="keySize">Size of the key (1024, 2048 or 4096).</param>
    /// <param name="startTime">The start time.</param>
    /// <param name="lifetimeInMonths">The lifetime of the key in months.</param>
    /// <param name="hashSizeInBits">The hash size in bits.</param>
    /// <param name="isCA">if set to <c>true</c> then a CA certificate is created.</param>
    /// <param name="issuerCAKeyCert">The CA cert with the CA private key.</param>
    /// <returns>The certificate with a private key.</returns>
    public static X509Certificate2 CreateCertificate(
        string storeType,
        string storePath,
        string password,
        string applicationUri,
        string applicationName,
        string subjectName,
        IList <String> domainNames,
        ushort keySize,
        DateTime startTime,
        ushort lifetimeInMonths,
        ushort hashSizeInBits,
        bool isCA = false,
        X509Certificate2 issuerCAKeyCert = null,
        byte[] publicKey = null)
    {
        if (issuerCAKeyCert != null)
        {
            if (!issuerCAKeyCert.HasPrivateKey)
            {
                throw new NotSupportedException("Cannot sign with a CA certificate without a private key.");
            }
        }

        if (publicKey != null && issuerCAKeyCert == null)
        {
            throw new NotSupportedException("Cannot use a public key without a CA certificate with a private key.");
        }

        // set default values.
        X509Name subjectDN = SetSuitableDefaults(
            ref applicationUri,
            ref applicationName,
            ref subjectName,
            ref domainNames,
            ref keySize,
            ref lifetimeInMonths);

        using (var cfrg = new CertificateFactoryRandomGenerator())
        {
            // cert generators
            SecureRandom random           = new SecureRandom(cfrg);
            X509V3CertificateGenerator cg = new X509V3CertificateGenerator();

            // Serial Number
            BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
            cg.SetSerialNumber(serialNumber);

            // subject and issuer DN
            X509Name issuerDN = null;
            if (issuerCAKeyCert != null)
            {
                issuerDN = new CertificateFactoryX509Name(issuerCAKeyCert.Subject);
            }
            else
            {
                // self signed
                issuerDN = subjectDN;
            }
            cg.SetIssuerDN(issuerDN);
            cg.SetSubjectDN(subjectDN);

            // valid for
            cg.SetNotBefore(startTime);
            cg.SetNotAfter(startTime.AddMonths(lifetimeInMonths));

            // set Private/Public Key
            AsymmetricKeyParameter subjectPublicKey;
            AsymmetricKeyParameter subjectPrivateKey;
            if (publicKey == null)
            {
                var keyGenerationParameters = new KeyGenerationParameters(random, keySize);
                var keyPairGenerator        = new RsaKeyPairGenerator();
                keyPairGenerator.Init(keyGenerationParameters);
                AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
                subjectPublicKey  = subjectKeyPair.Public;
                subjectPrivateKey = subjectKeyPair.Private;
            }
            else
            {
                // special case, if a cert is signed by CA, the private key of the cert is not needed
                subjectPublicKey  = PublicKeyFactory.CreateKey(publicKey);
                subjectPrivateKey = null;
            }
            cg.SetPublicKey(subjectPublicKey);

            // add extensions
            // Subject key identifier
            cg.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false,
                            new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey)));

            // Basic constraints
            cg.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCA));

            // Authority Key identifier references the issuer cert or itself when self signed
            AsymmetricKeyParameter issuerPublicKey;
            BigInteger             issuerSerialNumber;
            if (issuerCAKeyCert != null)
            {
                issuerPublicKey    = GetPublicKeyParameter(issuerCAKeyCert);
                issuerSerialNumber = GetSerialNumber(issuerCAKeyCert);
            }
            else
            {
                issuerPublicKey    = subjectPublicKey;
                issuerSerialNumber = serialNumber;
            }

            cg.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false,
                            new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey),
                                                       new GeneralNames(new GeneralName(issuerDN)), issuerSerialNumber));

            if (!isCA)
            {
                // Key usage
                cg.AddExtension(X509Extensions.KeyUsage, true,
                                new KeyUsage(KeyUsage.DataEncipherment | KeyUsage.DigitalSignature |
                                             KeyUsage.NonRepudiation | KeyUsage.KeyCertSign | KeyUsage.KeyEncipherment));

                // Extended Key usage
                cg.AddExtension(X509Extensions.ExtendedKeyUsage, true,
                                new ExtendedKeyUsage(new List <DerObjectIdentifier>()
                {
                    new DerObjectIdentifier("1.3.6.1.5.5.7.3.1"), // server auth
                    new DerObjectIdentifier("1.3.6.1.5.5.7.3.2"), // client auth
                }));

                // subject alternate name
                List <GeneralName> generalNames = new List <GeneralName>();
                generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri));
                generalNames.AddRange(CreateSubjectAlternateNameDomains(domainNames));
                cg.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(generalNames.ToArray()));
            }
            else
            {
                // Key usage CA
                cg.AddExtension(X509Extensions.KeyUsage, true,
                                new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign));
            }

            // sign certificate
            AsymmetricKeyParameter signingKey;
            if (issuerCAKeyCert != null)
            {
                // signed by issuer
                signingKey = GetPrivateKeyParameter(issuerCAKeyCert);
            }
            else
            {
                // self signed
                signingKey = subjectPrivateKey;
            }
            ISignatureFactory signatureFactory =
                new Asn1SignatureFactory(GetRSAHashAlgorithm(hashSizeInBits), signingKey, random);
            Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

            // convert to X509Certificate2
            X509Certificate2 certificate = null;
            if (subjectPrivateKey == null)
            {
                // create the cert without the private key
                certificate = new X509Certificate2(x509.GetEncoded());
            }
            else
            {
                // note: this cert has a private key!
                certificate = CreateCertificateWithPrivateKey(x509, null, subjectPrivateKey, random);
            }

            Utils.Trace(Utils.TraceMasks.Security, "Created new certificate: {0}", certificate.Thumbprint);

            // add cert to the store.
            if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(storeType))
                {
                    if (store == null)
                    {
                        throw new ArgumentException("Invalid store type");
                    }

                    store.Open(storePath);
                    store.Add(certificate, password).Wait();
                    store.Close();
                }
            }

            return(certificate);
        }
    }
        /// <summary>
        /// Configures all OPC stack settings
        /// </summary>
        public async Task ConfigureAsync()
        {
            // Instead of using a Config.xml we configure everything programmatically.

            //
            // OPC UA Application configuration
            //
            PublisherOpcApplicationConfiguration = new ApplicationConfiguration();

            // Passed in as command line argument
            PublisherOpcApplicationConfiguration.ApplicationName = ApplicationName;
            PublisherOpcApplicationConfiguration.ApplicationUri  = $"urn:{Utils.GetHostName()}:{PublisherOpcApplicationConfiguration.ApplicationName}:microsoft:";
            PublisherOpcApplicationConfiguration.ProductUri      = "https://github.com/Azure/iot-edge-opc-publisher";
            PublisherOpcApplicationConfiguration.ApplicationType = ApplicationType.ClientAndServer;


            //
            // Security configuration
            //
            PublisherOpcApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration();

            // Application certificate
            PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate             = new CertificateIdentifier();
            PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType   = OpcOwnCertStoreType;
            PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath   = OpcOwnCertStorePath;
            PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = PublisherOpcApplicationConfiguration.ApplicationName;
            Logger.Information($"Application Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType}");
            Logger.Information($"Application Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath}");
            Logger.Information($"Application Certificate subject name is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName}");

            // Use existing certificate, if it is there.
            X509Certificate2 certificate = await PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Find(true);

            if (certificate == null)
            {
                Logger.Information($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,");
                Logger.Information($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash.");
                certificate = CertificateFactory.CreateCertificate(
                    PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType,
                    PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath,
                    null,
                    PublisherOpcApplicationConfiguration.ApplicationUri,
                    PublisherOpcApplicationConfiguration.ApplicationName,
                    PublisherOpcApplicationConfiguration.ApplicationName,
                    null,
                    CertificateFactory.defaultKeySize,
                    DateTime.UtcNow - TimeSpan.FromDays(1),
                    CertificateFactory.defaultLifeTime,
                    CertificateFactory.defaultHashSize,
                    false,
                    null,
                    null
                    );
                PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate can not be created! Cannot continue without it!");
            }
            else
            {
                Logger.Information("Application certificate found in Application Certificate Store");
            }
            PublisherOpcApplicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate);
            Logger.Information($"Application certificate is for Application URI '{PublisherOpcApplicationConfiguration.ApplicationUri}', Application '{PublisherOpcApplicationConfiguration.ApplicationName} and has Subject '{PublisherOpcApplicationConfiguration.ApplicationName}'");

            // TrustedIssuerCertificates
            PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates           = new CertificateTrustList();
            PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = OpcIssuerCertStoreType;
            PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = OpcIssuerCertStorePath;
            Logger.Information($"Trusted Issuer store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}");
            Logger.Information($"Trusted Issuer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}");

            // TrustedPeerCertificates
            PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates           = new CertificateTrustList();
            PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = OpcTrustedCertStoreType;
            if (string.IsNullOrEmpty(OpcTrustedCertStorePath))
            {
                // Set default.
                PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStoreType == X509Store ? OpcTrustedCertX509StorePathDefault : OpcTrustedCertDirectoryStorePathDefault;
                if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP")))
                {
                    // Use environment variable.
                    PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP");
                }
            }
            else
            {
                PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStorePath;
            }
            Logger.Information($"Trusted Peer Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType}");
            Logger.Information($"Trusted Peer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}");

            // RejectedCertificateStore
            PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore           = new CertificateTrustList();
            PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = OpcRejectedCertStoreType;
            PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = OpcRejectedCertStorePath;
            Logger.Information($"Rejected certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType}");
            Logger.Information($"Rejected Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath}");

            // AutoAcceptUntrustedCertificates
            // This is a security risk and should be set to true only for debugging purposes.
            PublisherOpcApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false;

            // RejectSHA1SignedCertificates
            // We allow SHA1 certificates for now as many OPC Servers still use them
            PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = false;
            Logger.Information($"Rejection of SHA1 signed certificates is {(PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}");

            // MinimunCertificatesKeySize
            // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them
            PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = 1024;
            Logger.Information($"Minimum certificate key size set to {PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize}");

            // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store.
            if (TrustMyself)
            {
                // Ensure it is trusted
                try
                {
                    ICertificateStore store = PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();
                    if (store == null)
                    {
                        Logger.Information($"Can not open trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}");
                    }
                    else
                    {
                        try
                        {
                            Logger.Information($"Adding publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}");
                            X509Certificate2           publicKey      = new X509Certificate2(certificate.RawData);
                            X509Certificate2Collection certCollection = await store.FindByThumbprint(publicKey.Thumbprint);

                            if (certCollection.Count > 0)
                            {
                                Logger.Information($"A certificate with the same thumbprint is already in the trusted store.");
                            }
                            else
                            {
                                await store.Add(publicKey);
                            }
                        }
                        finally
                        {
                            store.Close();
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e, $"Can not add publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}");
                }
            }
            else
            {
                Logger.Information("Publisher certificate is not added to trusted peer store.");
            }


            //
            // TransportConfigurations
            //

            PublisherOpcApplicationConfiguration.TransportQuotas = new TransportQuotas();
            PublisherOpcApplicationConfiguration.TransportQuotas.MaxByteStringLength = 4 * 1024 * 1024;
            PublisherOpcApplicationConfiguration.TransportQuotas.MaxMessageSize      = 4 * 1024 * 1024;

            // the maximum string length could be set to ajust for large number of nodes when reading the list of published nodes
            PublisherOpcApplicationConfiguration.TransportQuotas.MaxStringLength = OpcMaxStringLength;

            // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s
            PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout = OpcOperationTimeout;
            Logger.Information($"OperationTimeout set to {PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout}");


            //
            // ServerConfiguration
            //
            PublisherOpcApplicationConfiguration.ServerConfiguration = new ServerConfiguration();

            // BaseAddresses
            if (PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Count == 0)
            {
                // We do not use the localhost replacement mechanism of the configuration loading, to immediately show the base address here
                PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Utils.GetHostName()}:{PublisherServerPort}{PublisherServerPath}");
            }
            foreach (var endpoint in PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses)
            {
                Logger.Information($"Publisher server base address: {endpoint}");
            }

            // SecurityPolicies
            // We do not allow security policy SecurityPolicies.None, but always high security
            ServerSecurityPolicy newPolicy = new ServerSecurityPolicy()
            {
                SecurityMode      = MessageSecurityMode.SignAndEncrypt,
                SecurityPolicyUri = SecurityPolicies.Basic256Sha256
            };

            PublisherOpcApplicationConfiguration.ServerConfiguration.SecurityPolicies.Add(newPolicy);
            Logger.Information($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added");

            // MaxRegistrationInterval
            PublisherOpcApplicationConfiguration.ServerConfiguration.MaxRegistrationInterval = LdsRegistrationInterval;
            Logger.Information($"LDS(-ME) registration intervall set to {LdsRegistrationInterval} ms (0 means no registration)");

            //
            // TraceConfiguration
            //
            //
            // TraceConfiguration
            //
            PublisherOpcApplicationConfiguration.TraceConfiguration            = new TraceConfiguration();
            PublisherOpcApplicationConfiguration.TraceConfiguration.TraceMasks = OpcStackTraceMask;
            PublisherOpcApplicationConfiguration.TraceConfiguration.ApplySettings();
            Utils.Tracing.TraceEventHandler += new EventHandler <TraceEventArgs>(LoggerOpcUaTraceHandler);
            Logger.Information($"opcstacktracemask set to: 0x{OpcStackTraceMask:X}");

            // add default client configuration
            PublisherOpcApplicationConfiguration.ClientConfiguration = new ClientConfiguration();

            // validate the configuration now
            await PublisherOpcApplicationConfiguration.Validate(PublisherOpcApplicationConfiguration.ApplicationType);
        }