private string ExportFullCertPEM(IKey csrKey, CertificateChain certificateChain, string certId, string primaryDomainPath)
        {
            var storePath = Path.GetFullPath(Path.Combine(new string[] { _settingsFolder, "..\\assets", primaryDomainPath }));

            if (!System.IO.Directory.Exists(storePath))
            {
                System.IO.Directory.CreateDirectory(storePath);
            }

            if (!System.IO.Directory.Exists(storePath))
            {
                System.IO.Directory.CreateDirectory(storePath);
            }

            var pemPath = Path.Combine(storePath, certId + ".pem");

            // write pem in order of Private .key, primary server .crt, intermediate .crt, issuer.crt
            // note:
            // nginx needs combined primary + intermediate.crt as pem (ssl_certificate), plus .key (ssl_certificate_key)
            // apache needs combined primary.crt (SSLCertificateFile), intermediate.crt (SSLCertificateChainFile), plus private .key (SSLCertificateKeyFile)
            var pem = certificateChain.ToPem(csrKey);

            System.IO.File.WriteAllText(pemPath, pem);

            return(pemPath);
        }
Beispiel #2
0
        public async Task <ICertificate> CreateCertificate()
        {
            try {
                _logger.Write("Generating certificate for {0}", domain.ZoneName);
                IKey privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);
                domain.Csr.CommonName = domain.DomainName;
                CertificateChain cert = await _orderContext.Generate(domain.Csr, privateKey);

                PfxBuilder pfxBuilder = cert.ToPfx(privateKey);
                byte[]     pfx        = pfxBuilder.Build(domain.ZoneName, "cert_password");

                FileWorker.WriteFile(pfx, string.Format(@"{0}{1}.pfx", _certDir, domain.ZoneName));
                FileWorker.WriteFile(cert.ToPem(certKey: privateKey), string.Format(@"{0}{1}.pem", _certDir, domain.ZoneName));
                FileWorker.WriteFile(cert.Certificate.ToDer( ), string.Format(@"{0}{1}.der", _certDir, domain.ZoneName));
                return(new Certificate {
                    status = true,
                    Cert = this.GetX509Certificate2(pfx),
                    isExpired = false
                });
            } catch (Exception e) {
                _logger.Write("Error occured while generating certificate for {0} :: error==>{1}", domain.ZoneName, e.Message);
                _logger.Write(e.StackTrace);
                return(new Certificate {
                    status = false,
                    errorDescription = e.Message
                });
            }
        }
Beispiel #3
0
        /// <summary>
        /// Retrieves the certificate from the ACME service. This method also generates the key and the CSR.
        /// </summary>
        /// <param name="commonName">the CN of the certificate to be requested</param>
        /// <param name="pathForPfx">Path where the resulting PFX/PKCS#12 file will be generated</param>
        /// <param name="pfxFriendlyName">Friendly name for the resulting PFX/PKCS#12</param>
        /// <returns>The name of the generated PFX/PKCS#12 file, or null in case of error</returns>
        public async Task <AuthenticatedPFX> RetrieveCertificate(IList <string> domains, string pathForPfx, string pfxFriendlyName)
        {
            try
            {
                if (_orderCtx == null)
                {
                    throw new Exception("Do not call RetrieveCertificate before RegisterNewOrderAndVerify");
                }
                if (!System.IO.Directory.Exists(pathForPfx))
                {
                    throw new Exception("Directory for PFX writing do not exists");
                }

                InitCertes();
                // Let's generate a new key (RSA is good enough IMHO)
                IKey certKey = KeyFactory.FromPem(Utils.GenerateRSAKeyAsPEM(_keySize));
                // Then let's generate the CSR
                var csr = await _orderCtx.CreateCsr(certKey);

                csr.AddName("CN", domains[0]);
                csr.SubjectAlternativeNames = domains;

                // and finalize the ACME order
                var finalOrder = await _orderCtx.Finalize(csr.Generate());

                // Now we can fetch the certificate
                CertificateChain cert = await _orderCtx.Download();

                // We build the PFX/PKCS#12 and the cert/key as PEM
                var pfx = cert.ToPfx(certKey);
                var cer = cert.ToPem();
                var key = certKey.ToPem();
                pfx.AddIssuers(GetCACertChainFromStore());
                var pfxBytes = pfx.Build(pfxFriendlyName, PfxPassword);
                var fileName = pathForPfx + "\\" + Guid.NewGuid().ToString();
                var pfxName  = fileName + ".pfx";
                var cerPath  = fileName + ".cer";
                var keyPath  = fileName + ".key";

                // We write the PFX/PKCS#12 to file
                System.IO.File.WriteAllBytes(pfxName, pfxBytes);
                logger.Info($"Retrieved certificate from the CA. The certificate is in {pfxName}");

                // We write the PEMs to corresponding files
                System.IO.File.WriteAllText(cerPath, cer);
                System.IO.File.WriteAllText(keyPath, key);

                AuthenticatedPFX authPFX = new AuthenticatedPFX(pfxName, PfxPassword, cerPath, keyPath);

                return(authPFX);
            }
            catch (Exception exp)
            {
                logger.Error($"Failed to retrieve certificate from CA: {ProcessCertesException(exp)}");
                return(null);
            }
        }
        private string ExportFullCertPEM(IKey csrKey, CertificateChain certificateChain, string certId)
        {
            var pemFolderPath = _settingsFolder + "\\assets\\pem";

            if (!System.IO.Directory.Exists(pemFolderPath))
            {
                System.IO.Directory.CreateDirectory(pemFolderPath);
            }

            var pemPath = pemFolderPath + "\\" + certId + ".pem";

            // write pem in order of Private .key, primary server .crt, intermediate .crt, issuer.crt
            // note:
            // nginx needs combined primary + intermediate.crt as pem (ssl_certificate), plus .key (ssl_certificate_key)
            // apache needs combined primary.crt (SSLCertificateFile), intermediate.crt (SSLCertificateChainFile), plus private .key (SSLCertificateKeyFile)
            var pem = certificateChain.ToPem(csrKey);

            System.IO.File.WriteAllText(pemPath, pem);

            return(pemPath);
        }
Beispiel #5
0
        /// <summary>
        /// Generate a certificate request
        /// </summary>
        /// <param name="certificatename"></param>
        /// <param name="mainhost">Main host: www.google.com</param>
        /// <param name="certificatePath">Path to store the generated certificates</param>
        /// <param name="alternatehosts">Alterante hosts: list of alterante hosts for this certificate</param>
        /// <returns></returns>
        public CertificatePaths DownloadCertificate(
            string certificatename,
            string mainhost,
            string certificatePath,
            List <string> alternatehosts = null)
        {
            if (this.OrderContext == null)
            {
                throw new Exception("Do not call RetrieveCertificate before RegisterNewOrderAndVerify");
            }

            // Let's generate a new key (RSA is good enough IMHO)
            IKey certKey = KeyFactory.NewKey(KeyAlgorithm.RS256);

            // Then let's generate the CSR
            var csr = this.OrderContext.CreateCsr(certKey).Result;

            csr.AddName("CN", mainhost);

            if (alternatehosts != null)
            {
                csr.SubjectAlternativeNames = alternatehosts;
            }

            // and finalize the ACME order
            var finalOrder = this.OrderContext.Finalize(csr.Generate()).Result;

            // Now we can fetch the certificate
            CertificateChain cert = this.OrderContext.Download().Result;

            // We build the PFX/PKCS#12 and the cert/key as PEM
            var pfx = cert.ToPfx(certKey);
            var cer = cert.ToPem();
            var key = certKey.ToPem();

            // pfx.AddIssuers(this.GetCACertChainFromStore()); Remote certificate already has information
            var fileName = Path.Combine(certificatePath, Guid.NewGuid().ToString());
            var pfxName  = fileName + ".pfx";
            var cerPath  = fileName + ".cer";
            var keyPath  = fileName + ".key";

            var authenticatedPfx = new AuthenticatedPFX(pfxName, cerPath, keyPath);
            var pfxBytes         = pfx.Build(certificatename, authenticatedPfx.PfxPassword);

            // We write the PFX/PKCS#12 to file
            File.WriteAllBytes(pfxName, pfxBytes);
            this.Logger.LogInfo(true, $"Retrieved certificate from the CA. The certificate is in {pfxName}");

            // We write the PEMs to corresponding files
            File.WriteAllText(cerPath, cer);
            File.WriteAllText(keyPath, key);

            return(new CertificatePaths()
            {
                chainPemFile = string.Empty,
                crtDerFile = string.Empty,
                crtPemFile = cerPath,
                csrGenFile = string.Empty,
                csrPemFile = string.Empty,
                keyGenFile = string.Empty,
                keyPemFile = keyPath,
                name = certificatename,
                pfxPemFile = pfxName
            });
        }
Beispiel #6
0
        /// <summary>
        /// HTTP-01 challenge.
        /// </summary>
        /// <exception cref="LetsEncryptMikroTikException"/>
        public async Task <LetsEncryptCert> GetCertAsync(string?accountPemKey = null)
        {
            AcmeContext     acme;
            IAccountContext account;

            //Uri knownServer = _letsEncryptAddress;

            if (accountPemKey != null)
            {
                // Load the saved account key
                var accountKey = KeyFactory.FromPem(accountPemKey);
                acme = new AcmeContext(_letsEncryptAddress, accountKey);
                Log.Information("Авторизация в Let's Encrypt.");
                account = await acme.Account().ConfigureAwait(false);
            }
            else
            {
                acme = new AcmeContext(_letsEncryptAddress);
                Log.Information("Авторизация в Let's Encrypt.");
                account = await acme.NewAccount(_config.Email, termsOfServiceAgreed : true).ConfigureAwait(false);

                // Save the account key for later use
                //string pemKey = acme.AccountKey.ToPem();
            }

            Log.Information("Заказываем новый сертификат.");
            IOrderContext order = await acme.NewOrder(new[] { _config.DomainName }).ConfigureAwait(false);

            // Get the token and key authorization string.
            Log.Information("Получаем способы валидации заказа.");
            var authz = (await order.Authorizations().ConfigureAwait(false)).First();

            if (_config.UseAlpn)
            {
                Log.Information("Выбираем TLS-ALPN-01 способ валидации.");
                IChallengeContext challenge = await authz.TlsAlpn().ConfigureAwait(false);

                string keyAuthz = challenge.KeyAuthz;
                string token    = challenge.Token;

                await ChallengeAlpnAsync(challenge, keyAuthz).ConfigureAwait(false);
            }
            else
            {
                Log.Information("Выбираем HTTP-01 способ валидации.");
                IChallengeContext challenge = await authz.Http().ConfigureAwait(false);

                string keyAuthz = challenge.KeyAuthz;

                await HttpChallengeAsync(challenge, keyAuthz).ConfigureAwait(false);
            }

            Log.Information("Загружаем сертификат.");

            // Download the certificate once validation is done
            IKey privateKey = KeyFactory.NewKey(KeyAlgorithm.RS256);

            CertificateChain cert = await order.Generate(new CsrInfo
            {
                CommonName       = _config.DomainName,
                CountryName      = "CA",
                State            = "Ontario",
                Locality         = "Toronto",
                Organization     = "Certes",
                OrganizationUnit = "Dev",
            }, privateKey)
                                    .ConfigureAwait(false);

            // Export full chain certification.
            string certPem = cert.ToPem();
            string keyPem  = privateKey.ToPem();

            // Export PFX
            PfxBuilder pfxBuilder = cert.ToPfx(privateKey);

            byte[] pfx = pfxBuilder.Build(friendlyName: _config.DomainName, password: "");

            //await acme.RevokeCertificate(pfx, RevocationReason.Superseded, privateKey);

            using (var cert2 = new X509Certificate2(pfx))
            {
                return(new LetsEncryptCert(cert2.NotAfter, certPem, keyPem, cert2.GetCommonName(), cert2.GetSha2Thumbprint()));
            }
        }