/// <summary>
        /// set a new application instance certificate
        /// </summary>
        /// <param name="newCertificate"></param>
        private async Task SetOwnCertificateAsync(X509Certificate2 newCertificate)
        {
            if (newCertificate == null || !newCertificate.HasPrivateKey)
            {
                throw new ArgumentException("Empty or invalid certificate");
            }

            //  attempt to replace the old certificate from the various trust lists
            var oldCertificate = _opcApplicationConfig.SecurityConfiguration
                                 .ApplicationCertificate.Certificate;

            if (oldCertificate?.Thumbprint != newCertificate.Thumbprint)
            {
                return;
            }

            _logger.Information(
                "Setting new application certificate {Thumbprint}, {Subject}...",
                newCertificate.Thumbprint, newCertificate.SubjectName.Name);

            // copy the certificate, public key only into the trusted certificates list
            using (var publicKey = new X509Certificate2(newCertificate.RawData)) {
                var trustList =
                    _opcApplicationConfig.SecurityConfiguration.TrustedPeerCertificates;
                if (oldCertificate != null)
                {
                    trustList.Remove(oldCertificate.YieldReturn());
                }
                trustList.Add(newCertificate.YieldReturn());
            }

            // add the certificate to the own store
            try {
                var applicationCertificate = _opcApplicationConfig.SecurityConfiguration
                                             .ApplicationCertificate;
                _logger.Information(
                    "Adding own certificate to configured certificate store");
                // Remove old and add new
                if (oldCertificate != null)
                {
                    applicationCertificate.RemoveFromStore(oldCertificate);
                }
                applicationCertificate.AddToStore(newCertificate, true);
            }
            catch (Exception ex) {
                _logger.Warning(ex,
                                "Failed adding own certificate into configured certificate store.");
            }

            //
            // Work around windows issue and persist application certificate also on
            // directory if configured.  This is needed for container persistence.
            //
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
                _configuration.AppCertStoreType == CertificateStoreType.Directory)
            {
                var applicationCertificate = new CertificateIdentifier {
                    StoreType   = CertificateStoreType.Directory,
                    StorePath   = _configuration.OwnCertPath,
                    SubjectName = newCertificate.SubjectName.Name
                };
                try {
                    _logger.Information(
                        "Persisting own certificate into directory certificate store...");
                    // Remove old and add new
                    if (oldCertificate != null)
                    {
                        applicationCertificate.RemoveFromStore(oldCertificate);
                    }
                    applicationCertificate.AddToStore(newCertificate, true);
                }
                catch (Exception ex) {
                    _logger.Warning(ex,
                                    "Failed adding own certificate to directory certificate store.");
                }
            }

            _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate
            .Certificate = newCertificate;
            await _opcApplicationConfig.CertificateValidator.UpdateCertificate(
                _opcApplicationConfig.SecurityConfiguration);
        }
        /// <summary>
        /// Initialize the OPC UA Application's security configuration
        /// </summary>
        /// <returns></returns>
        private async Task InitApplicationSecurityAsync()
        {
            // update certificates validator
            _opcApplicationConfig.CertificateValidator.CertificateValidation +=
                new CertificateValidationEventHandler(VerifyCertificate);
            await _opcApplicationConfig.CertificateValidator
            .Update(_opcApplicationConfig).ConfigureAwait(false);

            // lookup for an existing certificate in the configured store
            var ownCertificate = await _opcApplicationConfig.SecurityConfiguration
                                 .ApplicationCertificate.Find(true).ConfigureAwait(false);

            if (ownCertificate == null)
            {
                //
                // Work around windows issue and lookup application certificate also on
                // directory if configured.  This is needed for container persistence.
                //
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
                    _configuration.AppCertStoreType == CertificateStoreType.Directory)
                {
                    // Use x509 store instead of directory for private cert.
                    var ownCertificateIdentifier = new CertificateIdentifier {
                        StoreType   = _configuration.AppCertStoreType,
                        StorePath   = _configuration.OwnCertPath,
                        SubjectName = _opcApplicationConfig.SecurityConfiguration
                                      .ApplicationCertificate.SubjectName
                    };
                    ownCertificate = await ownCertificateIdentifier.Find(true)
                                     .ConfigureAwait(false);

                    if ((ownCertificate != null) && !ownCertificate.Verify())
                    {
                        try {
                            _logger.Warning("Found malformed own certificate {Thumbprint}, " +
                                            "{Subject} in the store - deleting it...",
                                            ownCertificate.Thumbprint, ownCertificate.Subject);
                            ownCertificateIdentifier.RemoveFromStore(ownCertificate);
                        }
                        catch (Exception ex) {
                            _logger.Information(ex,
                                                "Failed to remove malformed own certificate");
                        }
                        ownCertificate = null;
                    }
                }
            }

            if (ownCertificate == null)
            {
                _logger.Information("Application own certificate not found. " +
                                    "Creating a new self-signed certificate with default settings...");
                ownCertificate = CertificateFactory.CreateCertificate(
                    _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.StoreType,
                    _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.StorePath,
                    null,
                    _opcApplicationConfig.ApplicationUri, _opcApplicationConfig.ApplicationName,
                    _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.SubjectName,
                    null, CertificateFactory.defaultKeySize,
                    DateTime.UtcNow - TimeSpan.FromDays(1),
                    CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize,
                    false, null, null);

                _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.Certificate =
                    ownCertificate;
                _logger.Information(
                    "New application certificate with {Thumbprint}, {Subject} created",
                    ownCertificate.Thumbprint, ownCertificate.SubjectName.Name);
            }
            else
            {
                _logger.Information("Application certificate with {Thumbprint}, {Subject} " +
                                    "found in the certificate store",
                                    ownCertificate.Thumbprint, ownCertificate.SubjectName.Name);
            }
            // Set the Certificate as the newly created certificate
            await SetOwnCertificateAsync(ownCertificate);

            if (_opcApplicationConfig.SecurityConfiguration.AutoAcceptUntrustedCertificates)
            {
                _logger.Warning(
                    "WARNING: Automatically accepting certificates. This is a security risk.");
            }
        }