public static void GenerateSslCertificate(PfxData pfx, Org.BouncyCastle.Security.SecureRandom random)
        {
            string curveName = "curve25519"; curveName = "secp256k1";

            // IIS does not support Elliptic Curve...
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair certKeyPair = KeyGenerator.GenerateEcKeyPair(curveName, random);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair certKeyPair = KeyGenerator.GenerateRsaKeyPair(2048, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair certKeyPair = KeyGenerator.GenerateDsaKeyPair(1024, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair certKeyPair = KeyGenerator.GenerateDHKeyPair(1024, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair certKeyPair = KeyGenerator.GenerateGostKeyPair(4096, random);



            Org.BouncyCastle.X509.X509Certificate sslCertificate = SelfSignSslCertificate(random, pfx.Certificate, certKeyPair.Public, pfx.PrivateKey);

            bool val = CerGenerator.ValidateSelfSignedCert(sslCertificate, pfx.Certificate.GetPublicKey());



            // SSL
            (string Private, string Public)certKeys = KeyPairToPem(certKeyPair);
            PfxFile.Create(@"obelix.pfx", sslCertificate, certKeyPair.Private, "");
            WriteCerAndCrt(sslCertificate, @"obelix");
            System.IO.File.WriteAllText(@"obelix_private.key", certKeys.Private, System.Text.Encoding.ASCII);
            // System.IO.File.WriteAllText(@"obelix_public.key", certKeys.Public, System.Text.Encoding.ASCII);

            string pemCert = ToPem(sslCertificate);

            System.IO.File.WriteAllText(@"obelix.pem", pemCert, System.Text.Encoding.ASCII);
        } // End Sub GenerateSslCertificate
        public static PfxData GenerateRootCertificate(Org.BouncyCastle.Security.SecureRandom random)
        {
            // string curveName = "curve25519"; curveName = "secp256k1";
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair rootKeyPair = KeyGenerator.GenerateEcKeyPair(curveName, random);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair rootKeyPair = KeyGenerator.GenerateRsaKeyPair(2048, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair rootKeyPair = KeyGenerator.GenerateDsaKeyPair(1024, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair rootKeyPair = KeyGenerator.GenerateDHKeyPair(1024, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair rootKeyPair = KeyGenerator.GenerateGostKeyPair(4096, random);

            Org.BouncyCastle.X509.X509Certificate rootCertificate = GenerateRootCertificate(rootKeyPair, random);

            // root
            (string Private, string Public)rootKeys = KeyPairToPem(rootKeyPair);
            PfxFile.Create(@"skynet.pfx", rootCertificate, rootKeyPair.Private, "");
            WriteCerAndCrt(rootCertificate, @"skynet");
            System.IO.File.WriteAllText(@"skynet_private.key", rootKeys.Private, System.Text.Encoding.ASCII);
            // System.IO.File.WriteAllText(@"ca_public.key", rootKeys.Public, System.Text.Encoding.ASCII);


            return(new PfxData(rootCertificate, rootKeyPair.Private));
        }
        public async Task UpdateCertificate(CertificateInfo input, string?site, string?host, string?username, string?password)
        {
            const string location     = "/nsconfig/ssl";
            var          pemFilesName = PfxFile.Filename(input.CommonName.Value, "");

            site ??= Path.GetFileNameWithoutExtension(pemFilesName);
            host ??= DefaultNitroHost;
            username ??= DefaultNitroUsername;
            password ??= new ProtectedString(DefaultNitroPasswordProtected, _log).Value ?? "";
            _log.Verbose($"CitrixAdcClient UpdateCertificate site {site} host {host} creds {username}/{new string('*', password?.Length ?? 1)}");
            var apiUrl = GetApiUrl(host);

            // initialize the HTTP client
            using var handler    = new HttpClientHandler();
            using var httpClient = NewHttpClient(handler, username, password);

            // send the private key and cert chain files
            var keyFilename = $"{pemFilesName}{PemFiles.KeyFilenameSuffix}{PemFiles.FilenameExtension}";

            keyFilename = await PostSystemFile(httpClient, apiUrl, location, site, keyFilename, key : true);

            if (keyFilename == null)
            {
                throw new Exception($"Failed to post {site} key pem.");
            }
            var chainFilename = $"{pemFilesName}{PemFiles.ChainFilenameSuffix}{PemFiles.FilenameExtension}";

            chainFilename = await PostSystemFile(httpClient, apiUrl, location, site, chainFilename, key : false);

            if (chainFilename == null)
            {
                throw new Exception($"Failed to post {site} chain pem.");
            }

            // update the cert
            var success = await PostSSLCertKey(httpClient, apiUrl, site, chainFilename, keyFilename, _pemFilesPassword);

            if (!success)
            {
                throw new Exception($"Failed to update {site} certificate.");
            }

            // verify the cert was successfully updated
            var verified = await VerifySSLCertKey(httpClient, apiUrl, site, chainFilename, keyFilename);

            if (!verified)
            {
                throw new Exception($"Verification failed for {site} cert update.");
            }

            // delete the private key and cert chain files
            var deletedKey = await DeleteSystemFile(httpClient, apiUrl, location, keyFilename);

            if (!deletedKey)
            {
                _log.Warning("Failed to delete {keyFilename}.", keyFilename);
            }
            var deletedCert = await DeleteSystemFile(httpClient, apiUrl, location, chainFilename);

            if (!deletedCert)
            {
                _log.Warning("Failed to delete {chainFilename}.", chainFilename);
            }
        }