Example #1
0
        public async Task <byte[]> GetCertificateAsync(Action <string> setDnsTxt)
        {
            IOrderContext order = await AcmeContext.NewOrder(new[] { Configuration.CertificateIdentifier });

            var authz        = (await order.Authorizations()).First();
            var dnsChallenge = await authz.Dns();

            var dnsTxt     = AcmeContext.AccountKey.DnsTxt(dnsChallenge.Token);
            var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);

            setDnsTxt(dnsTxt);
            Challenge challenge = null;

            for (int i = 0; challenge?.Status != ChallengeStatus.Valid && i < 10; i++)
            {
                challenge = await dnsChallenge.Validate();

                if (challenge.Status == ChallengeStatus.Valid)
                {
                    break;
                }
                Thread.Sleep(1000);
            }
            var cert = await order.Generate(Configuration.CsrInfo, privateKey);

            var pfxBuilder = cert.ToPfx(privateKey);

            return(pfxBuilder.Build(Configuration.CertificateName, Configuration.CertificatePassword));
        }
        /// <summary>
        /// 导出证书文件
        /// </summary>
        /// <param name="orderCtx">订单上下文</param>
        /// <param name="acmeConfig">ACME配置文件实体</param>
        /// <returns></returns>
        public static async Task ExportCertificateAsync(IOrderContext orderCtx, AcmeV2Config acmeConfig)
        {
            var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);
            var cert       = await orderCtx.Generate(new CsrInfo
            {
                CommonName       = acmeConfig.CommonName,
                CountryName      = acmeConfig.CountryName,
                State            = acmeConfig.State,
                Locality         = acmeConfig.Locality,
                Organization     = acmeConfig.Organization,
                OrganizationUnit = acmeConfig.OrganizationUnit
            }, privateKey);

            //导出整个证书链
            var certPem = cert.ToPem();

            File.WriteAllText(Path.Combine(acmeConfig.CertSavePath, acmeConfig.CertFullChainPemName), certPem);
            //导出PFX格式的证书
            var pfxBuilder = cert.ToPfx(privateKey);
            var pfx        = pfxBuilder.Build(acmeConfig.ServerCertDisplayName, acmeConfig.ServerCertPwd);

            using (FileStream fs = new FileStream(Path.Combine(acmeConfig.CertSavePath, acmeConfig.CertPfxName), FileMode.Create))
            {
                fs.Write(pfx, 0, pfx.Length);
            }
        }
        public static async Task <X509Certificate2> GetFinalCertificate(this IOrderContext orderContext, Options.CsrInfo csrInfo, string commonName, string friendlyName)
        {
            commonName.ArgNotNull(nameof(commonName));
            friendlyName.ArgNotNull(nameof(friendlyName));

            // Download final certificate
            var privateKey  = KeyFactory.NewKey(KeyAlgorithm.ES256);
            var certificate = await orderContext.Generate(new CsrInfo {
                CountryName      = csrInfo?.CountryName,
                State            = csrInfo?.State,
                Locality         = csrInfo?.Locality,
                Organization     = csrInfo?.Organization,
                OrganizationUnit = csrInfo?.OrganizationUnit,
                CommonName       = commonName
            }, privateKey);

            // Generate pfx and then load it into a X509Certificate2 class.
            // Havent found a conversion to X509Certificate2 without the need for a password...
            string tempPassword = Guid.NewGuid().ToString();

            byte[] pfx = certificate
                         .ToPfx(privateKey)
                         .Build(friendlyName, tempPassword);

            return(new X509Certificate2(pfx, tempPassword, X509KeyStorageFlags.Exportable));
        }
Example #4
0
        private async Task <byte[]> AcquireCertificateBytesFromOrderAsync(
            IOrderContext order,
            CsrInfo certificateSigningRequest,
            string certificateFriendlyName,
            string certificatePassword,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            _logger.LogInformation("Acquiring certificate through signing request.");

            var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);

            var certificateChain = await order.Generate(certificateSigningRequest, privateKey);

            var pfxBuilder = certificateChain.ToPfx(privateKey);

            pfxBuilder.FullChain = true;

            var pfxBytes = pfxBuilder.Build(certificateFriendlyName, certificatePassword);

            _logger.LogInformation("Certificate acquired.");

            return(pfxBytes);
        }
 private Task <CertificateChain> TryOrderGenerate(IOrderContext order, string dnsName, IKey privateKey)
 {
     return(order.Generate(new CsrInfo
     {
         CountryName = "RU",
         State = "Svr",
         Locality = "Yekaterinburg",
         Organization = "AutomaticCA",
         OrganizationUnit = "Dev",
         CommonName = dnsName,
     }, privateKey));
 }
Example #6
0
        private async Task <byte[]> CreateCertificate(IOrderContext order)
        {
            IKey privateKey = KeyFactory.NewKey(KeyAlgorithm.RS256);

            CertificateChain certificateChain = await order.Generate(new CsrInfo
            {
                CommonName = Hostname
            }, privateKey);

            PfxBuilder pfxBuilder = certificateChain.ToPfx(privateKey);

            byte[] pfx = pfxBuilder.Build(Hostname, string.Empty);

            return(pfx);
        }
Example #7
0
        public async Task <byte[]> GetPfxCertificateAsync(string password, string certificateCountryName, string certificateState, string certificateLocality,
                                                          string certificateOrganization, string certificateOrganizationUnit, string domainName, string friendlyName)
        {
            var privateKey = KeyFactory.NewKey(KeyAlgorithm.RS256);
            var cert       = await orderContext.Generate(new CsrInfo
            {
                CountryName      = certificateCountryName,
                State            = certificateState,
                Locality         = certificateLocality,
                Organization     = certificateOrganization,
                OrganizationUnit = certificateOrganizationUnit,
                CommonName       = domainName,
            }, privateKey);

            var pfxBuilder = cert.ToPfx(privateKey);

            return(pfxBuilder.Build(friendlyName, password));
        }
Example #8
0
        private async Task <byte[]> AcquireCertificateBytesFromOrderAsync(IOrderContext order)
        {
            _logger.LogInformation("Acquiring certificate through signing request.");

            var keyPair = KeyFactory.NewKey(_options.KeyAlgorithm);

            var certificateChain = await order.Generate(_options.CertificateSigningRequest, keyPair);

            var pfxBuilder = certificateChain.ToPfx(keyPair);

            pfxBuilder.FullChain = true;

            var pfxBytes = pfxBuilder.Build(CertificateFriendlyName, nameof(FluffySpoon));

            _logger.LogInformation("Certificate acquired.");

            return(pfxBytes);
        }
        private static async Task GenerateOrder(IOrderContext order)
        {
            Log(" 7. Generating Certificate...");
            var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);

            var cert = await order.Generate(new CsrInfo
            {
                CountryName      = _configuration.Country,
                State            = _configuration.State,
                Locality         = _configuration.Locality,
                Organization     = _configuration.Organization,
                OrganizationUnit = _configuration.Unit,
                CommonName       = _configuration.DomainName,
            }, privateKey);

            Log(" 8. Building PFX...");
            var pfxBuilder = cert.ToPfx(privateKey);
            var pfx        = pfxBuilder.Build(_configuration.DomainName, _configuration.CertificatePassword);

            File.WriteAllBytes(Path.Combine(_configuration.CertificatePath, $"{_configuration.DomainName}.pfx"), pfx);
        }
Example #10
0
        private async Task <X509Certificate2> CompleteCertificateRequestAsync(IOrderContext order, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var commonName = _options.Value.DomainNames[0];

            _logger.LogDebug("Creating cert for {commonName}", commonName);

            var csrInfo = new CsrInfo
            {
                CommonName = commonName,
            };
            var privateKey = KeyFactory.NewKey((Certes.KeyAlgorithm)_options.Value.KeyAlgorithm);
            var acmeCert   = await order.Generate(csrInfo, privateKey);

            _logger.LogAcmeAction("NewCertificate");

            var pfxBuilder = acmeCert.ToPfx(privateKey);
            var pfx        = pfxBuilder.Build("Let's Encrypt - " + _options.Value.DomainNames, string.Empty);

            return(new X509Certificate2(pfx, string.Empty, X509KeyStorageFlags.Exportable));
        }
        private async Task <byte[]> AcquireCertificateBytesFromOrderAsync(
            IOrderContext order,
            AcmeOrderOptions orderOptions,
            AcmeAccountOptions accountOptions,
            CertificateOptions certificateOptions)
        {
            _logger.LogInformation("[LetsEncrypt][Certificate] Acquiring certificate through signing request.");

            var privateKey = KeyFactory.NewKey((Certes.KeyAlgorithm)orderOptions.KeyAlgorithm);

            if (orderOptions?.CertificateSigningRequest == null)
            {
                var commonName = accountOptions.Domains[0];
                _logger.LogDebug("Creating cert for {commonName}", commonName);

                var csrInfo = new CsrInfo
                {
                    CommonName = commonName,
                };

                if (orderOptions != null)
                {
                    orderOptions.CertificateSigningRequest = csrInfo;
                }
            }

            var certificateChain = await order.Generate(orderOptions?.CertificateSigningRequest, privateKey);

            var pfxBuilder = certificateChain.ToPfx(privateKey);

            pfxBuilder.FullChain = true;

            var pfxBytes = pfxBuilder.Build(
                $"Let's Encrypt - {accountOptions.Domains[0]} ",
                certificateOptions?.CertificatePassword ?? string.Empty);

            _logger.LogInformation("[LetsEncrypt][Certificate] Certificate acquired.");

            return(pfxBytes);
        }
Example #12
0
        public async Task BuildCertificate(IOrderContext order, string hostName)
        {
            try
            {
                var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);

                var cert = await order.Generate(new CsrInfo
                {
                    CommonName = hostName
                }, privateKey);

                var pfxBuilder = cert.ToPfx(privateKey);
                var pfx        = pfxBuilder.Build(hostName, _options.EncryptionPassword);

                var x509Cert = new X509Certificate2(pfx, _options.EncryptionPassword);

                _certificateSelector.Use(hostName, x509Cert);

                if (!string.IsNullOrEmpty(_options.CacheFolder))
                {
                    var fileName = Path.Combine(_options.CacheFolder, hostName + ".pfx");

                    if (File.Exists(fileName))
                    {
                        File.Delete(fileName);
                    }

                    File.WriteAllBytes(fileName, pfx);
                }

                _logger.LogInformation($"New certificate generated for {hostName}");
            }
            catch (Exception e)
            {
                _logger.LogError(e.ToString());
                throw;
            }
        }
Example #13
0
        internal async Task <bool> Renew(AcmeConfig config, List <INotifyConfig> notificationsList)
        {
            Model.Config        = config;
            Model.Notifications = notificationsList;
            _log.LogInfo("Renewing certificate");
            var acme = _contextFactory(config);


            IOrderContext order = default(IOrderContext);

            bool validated = await _validators[config.Validation].Validate(acme, config, notificationsList, async(domainNames) => {
                _log.LogInfo("Acme: getting order");
                order = await acme.NewOrder(domainNames);
                return(order);
            });

            if (validated)
            {
                var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);
                var cert       = await order.Generate(new CsrInfo
                {
                    CountryName      = "BE",
                    State            = "Antwerp",
                    Locality         = "Belgium",
                    Organization     = "stovem",
                    OrganizationUnit = "stovem",
                    CommonName       = config.DNS.DomainNames.First(),
                }, privateKey);

                var certPem    = cert.ToPem();
                var privatePem = privateKey.ToPem();

                Model.Certificate = privatePem + certPem;
            }

            return(validated);
        }
Example #14
0
        public async Task <AcmeOrder> Complete()
        {
            if (_acmeOrder.Status != AcmeOrderStatus.Validating)
            {
                return(_acmeOrder);
            }

            foreach (var cc in _authChallengeContainers)
            {
                cc.AuthorizationTask = cc.AuthorizationContext.Resource();
            }

            var attempts = 5;

            do
            {
                // Kick off the authorization tasks for the tasks that haven't been run yet
                await Task.WhenAll(_authChallengeContainers
                                   .Where(x => !x.AuthorizationTask.IsCompleted)
                                   .Select(x => x.AuthorizationTask)
                                   .ToList());

                var incompletes = 0;
                // After running the tasks, find all incomplete authz
                foreach (var cc in _authChallengeContainers)
                {
                    var status    = cc.AuthorizationTask.Result.Status;
                    var completed = status == AuthorizationStatus.Valid ||
                                    status == AuthorizationStatus.Invalid;
                    if (!completed)
                    {
                        incompletes++;

                        // Update the task such that it's a new task and it will be awaited above
                        cc.AuthorizationTask = cc.AuthorizationContext.Resource();
                    }
                    else
                    {
                        cc.Authorization = cc.AuthorizationTask.Result;
                    }
                }

                // Find incomplete ones and try again
                _logger.LogDebug($"{incompletes} incomplete authorizations.");

                if (incompletes == 0)
                {
                    break;
                }

                await Task.Delay(5000);
            } while (attempts-- > 0);

            // All authorizations have completed, save the results
            foreach (var cc in _authChallengeContainers)
            {
                cc.Authorization = cc.AuthorizationTask.Result;
            }

            // At this point, they're all complete and need to see which are valid/invalid
            // and obtain the cert if possible.
            try
            {
                var invalidResp = _authChallengeContainers
                                  .SelectMany(x => x.Authorization.Challenges)
                                  .Where(x => x.Error != null)
                                  .ToList();

                var errors = string.Join("\r\n", invalidResp
                                         .Select(x => $"{x.Error.Status} {x.Error.Type} {x.Error.Detail}"));

                _acmeOrder.RequestCount         = _authChallengeContainers.Count;
                _acmeOrder.InvalidResponseCount = invalidResp.Count;
                _acmeOrder.Errors = errors;
                _acmeOrder.Status = AcmeOrderStatus.Completed;

                if (invalidResp.Count > 0)
                {
                    _acmeOrder.Status = AcmeOrderStatus.Invalid;
                    return(_acmeOrder);
                }

                var cert = await _order.Generate(
                    new CsrInfo
                {
                    CommonName       = _acmeCertificate.CsrCommonName,
                    CountryName      = _acmeCertificate.CsrCountryName,
                    Locality         = _acmeCertificate.CsrLocality,
                    Organization     = _acmeCertificate.CsrOrganization,
                    OrganizationUnit = _acmeCertificate.CsrOrganizationUnit,
                    State            = _acmeCertificate.CsrState
                }, KeyFactory.FromPem(_acmeCertificate.Key.RawData));

                var certBytes = cert.Certificate.ToDer();

                var xCert      = new X509Certificate2(certBytes);
                var domainCert = DomainCertificate.FromX509Certificate2(xCert, CertificateSource.AcmeCertificate);
                xCert.Dispose();

                _acmeOrder.RawDataPem        = cert.ToPem();
                _acmeOrder.DomainCertificate = domainCert;

                return(_acmeOrder);
            }
            catch (AcmeRequestException e)
            {
                _acmeOrder.Status = AcmeOrderStatus.Error;
                _acmeOrder.Errors = $"{e.Error.Status} {e.Error.Type} {e.Error.Detail}";
            }
            catch (Exception)
            {
                _acmeOrder.Status = AcmeOrderStatus.Error;
                _acmeOrder.Errors = "Unknown Error";
            }
            return(_acmeOrder);
        }
Example #15
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()));
            }
        }
Example #16
0
 public async Task <CertificateChain> GetCertificateAsync(CsrInfo csrInfo, IKey privateKey, IOrderContext order)
 {
     _logger.LogAcmeAction("GenerateCertificate", order);
     return(await order.Generate(csrInfo, privateKey));
 }
        public static void GetFirstCert(bool staging = true)
        {
            ContextAccountBundle bundle;

            if (staging)
            {
                bundle = GetStagingParameters();
            }
            else
            {
                bundle = GetNonStagingParameters();
            }

            var account = bundle.Account;
            var ctx     = bundle.Ctx;

            IOrderListContext    orders        = account.Orders().Result;
            List <IOrderContext> orderContexts = new List <IOrderContext>(orders.Orders().Result);
            IOrderContext        currentOrder  = null;

            if (orderContexts.Count == 0)
            {
                currentOrder = ctx.NewOrder(new[] { "jcf-ai.com" }).Result;
            }
            else
            {
                foreach (IOrderContext orderCtx in orderContexts)
                {
                    if (orderCtx.Resource().Result.Status != OrderStatus.Valid)
                    {
                        currentOrder = orderCtx;
                        break;
                    }
                }
                if (currentOrder == null)
                {
                    currentOrder = ctx.NewOrder(new[] { "jcf-ai.com" }).Result;
                }
            }
            Order order             = currentOrder.Resource().Result;
            var   authorizationList = currentOrder.Authorizations().Result;
            IAuthorizationContext currentAuthContext;
            IEnumerator <IAuthorizationContext> enumerator = authorizationList.GetEnumerator();

            while (enumerator.Current == null)
            {
                enumerator.MoveNext();
            }
            currentAuthContext = enumerator.Current;
            Authorization authResource = currentAuthContext.Resource().Result;


            IChallengeContext httpContext = currentAuthContext.Http().Result;

            if (httpContext.Resource().Result.Status != ChallengeStatus.Valid)
            {
                if (!System.IO.Directory.Exists("tokens"))
                {
                    System.IO.Directory.CreateDirectory("tokens");
                }
                StreamWriter writer = new StreamWriter("tokens/" + httpContext.Token);
                writer.Write(httpContext.KeyAuthz);
                writer.Close();
                Challenge httpChallenge = httpContext.Validate().Result;
            }

            //Everything should be good to go on the whole validate everything front.
            IKey privateKey = KeyFactory.NewKey(KeyAlgorithm.ES384);
            var  cert       = currentOrder.Generate(
                new CsrInfo()
            {
                CountryName = "US",
                State       = "Washington",
                Locality    = "Tacoma",
                CommonName  = "jcf-ai.com"
            }, privateKey).Result;

            byte[]     pfx          = cert.ToPfx(privateKey).Build("jcf-ai.com", "pass");
            FileStream pfxOutStream = new FileStream("jcf-ai.pfx", FileMode.Create, FileAccess.Write);

            pfxOutStream.Write(pfx, 0, pfx.Length);
            pfxOutStream.Close();

            ProcessStartInfo psi = new ProcessStartInfo("powershell", "-Command ./bindcert.ps1 jcf-ai.pfx pass");

            psi.CreateNoWindow = true;
            Process.Start(psi);
        }