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