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)); }
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)); }
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); }
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)); }
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); }
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); }
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; } }
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); }
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); }
/// <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())); } }
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); }