static byte[] GenerateCSR(CertificateProvider provider, string hostName, List <string> alternativeNames, out PrivateKey privateKey) { var csrDetails = new CsrDetails { CommonName = hostName }; if (alternativeNames.Count > 0) { csrDetails.AlternativeNames = alternativeNames; } privateKey = provider.GeneratePrivateKey(new RsaPrivateKeyParams() { NumBits = Program.GlobalConfiguration.RSAKeyBits }); var csr = provider.GenerateCsr(new CsrParams { Details = csrDetails, }, privateKey, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { provider.ExportCsr(csr, EncodingFormat.DER, bs); bs.Seek(0, SeekOrigin.Begin); derRaw = bs.ToArray(); } return(derRaw); }
public static Csr GenerateCsr(CsrDetails csrDetails, RsaKeyPair rsaKeyPair, string messageDigest = "SHA256") { var rsaKeys = CryptoKey.FromPrivateKey(rsaKeyPair.Pem, null); // Translate from our external form to our OpenSSL internal form // Ref: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_new.html var xn = new X509Name(); if (!string.IsNullOrEmpty(csrDetails.CommonName /**/)) xn.Common = csrDetails.CommonName; // CN; if (!string.IsNullOrEmpty(csrDetails.Country /**/)) xn.Common = csrDetails.Country; // C; if (!string.IsNullOrEmpty(csrDetails.StateOrProvince /**/)) xn.Common = csrDetails.StateOrProvince; // ST; if (!string.IsNullOrEmpty(csrDetails.Locality /**/)) xn.Common = csrDetails.Locality; // L; if (!string.IsNullOrEmpty(csrDetails.Organization /**/)) xn.Common = csrDetails.Organization; // O; if (!string.IsNullOrEmpty(csrDetails.OrganizationUnit /**/)) xn.Common = csrDetails.OrganizationUnit; // OU; if (!string.IsNullOrEmpty(csrDetails.Description /**/)) xn.Common = csrDetails.Description; // D; if (!string.IsNullOrEmpty(csrDetails.Surname /**/)) xn.Common = csrDetails.Surname; // S; if (!string.IsNullOrEmpty(csrDetails.GivenName /**/)) xn.Common = csrDetails.GivenName; // G; if (!string.IsNullOrEmpty(csrDetails.Initials /**/)) xn.Common = csrDetails.Initials; // I; if (!string.IsNullOrEmpty(csrDetails.Title /**/)) xn.Common = csrDetails.Title; // T; if (!string.IsNullOrEmpty(csrDetails.SerialNumber /**/)) xn.Common = csrDetails.SerialNumber; // SN; if (!string.IsNullOrEmpty(csrDetails.UniqueIdentifier /**/)) xn.Common = csrDetails.UniqueIdentifier; // UID; var xr = new X509Request(0, xn, rsaKeys); var md = MessageDigest.CreateByName(messageDigest); ; xr.Sign(rsaKeys, md); using (var bio = BIO.MemoryBuffer()) { xr.Write(bio); return new Csr(bio.ReadString()); } }
public static void GetCertificateAutoGen(CertificateGeneratorParam param) { if (param == null) { log.Info($" {nameof(param)} is null"); return; } param.domains = param.domains.Where(o => o.valid).ToList(); if (param.domains.Count == 0) { log.Info($" can't find a valid domain name."); return; } var dnsIdentifier = string.IsNullOrWhiteSpace(param.common_name) ? param.domains.FirstOrDefault().domain : param.common_name.Trim(); var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = dnsIdentifier, AlternativeNames = param.domains.Select(o => o.domain).ToList(), }; var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); log.Info($"\nRequesting Certificate"); var certRequ = param.client.RequestCertificate(derB64u); log.Info($" Request Status: {certRequ.StatusCode}"); //log.Info($"Refreshing Cert Request"); //client.RefreshCertificateRequest(certRequ); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(param.path, $"{dnsIdentifier}-gen-key.json"); var keyPemFile = Path.Combine(param.path, $"{dnsIdentifier}-key.pem"); var csrGenFile = Path.Combine(param.path, $"{dnsIdentifier}-gen-csr.json"); var csrPemFile = Path.Combine(param.path, $"{dnsIdentifier}-csr.pem"); var crtDerFile = Path.Combine(param.path, $"{dnsIdentifier}-crt.der"); var crtPemFile = Path.Combine(param.path, $"{dnsIdentifier}-crt.pem"); string crtPfxFile = null; crtPfxFile = Path.Combine(param.path, $"{dnsIdentifier}-all.pfx"); using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); log.Info($" Saving Certificate to {crtDerFile}"); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp, param.account); log.Info($" Saving Certificate to {crtPfxFile} (with no password set)"); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target); } cp.Dispose(); return; } throw new Exception($"Request status = {certRequ.StatusCode}"); }
private Csr GenerateCsr(CsrDetails csrDetails, RsaPrivateKey rsaKeyPair, string messageDigest = "SHA256") { var rsaKeys = CryptoKey.FromPrivateKey(rsaKeyPair.Pem, null); // Translate from our external form to our OpenSSL internal form // Ref: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_new.html var xn = new X509Name(); if (!string.IsNullOrEmpty(csrDetails.CommonName /**/)) { xn.Common = csrDetails.CommonName; // CN; } if (!string.IsNullOrEmpty(csrDetails.Country /**/)) { xn.Country = csrDetails.Country; // C; } if (!string.IsNullOrEmpty(csrDetails.StateOrProvince /**/)) { xn.StateOrProvince = csrDetails.StateOrProvince; // ST; } if (!string.IsNullOrEmpty(csrDetails.Locality /**/)) { xn.Locality = csrDetails.Locality; // L; } if (!string.IsNullOrEmpty(csrDetails.Organization /**/)) { xn.Organization = csrDetails.Organization; // O; } if (!string.IsNullOrEmpty(csrDetails.OrganizationUnit /**/)) { xn.OrganizationUnit = csrDetails.OrganizationUnit; // OU; } if (!string.IsNullOrEmpty(csrDetails.Description /**/)) { xn.Description = csrDetails.Description; // D; } if (!string.IsNullOrEmpty(csrDetails.Surname /**/)) { xn.Surname = csrDetails.Surname; // S; } if (!string.IsNullOrEmpty(csrDetails.GivenName /**/)) { xn.Given = csrDetails.GivenName; // G; } if (!string.IsNullOrEmpty(csrDetails.Initials /**/)) { xn.Initials = csrDetails.Initials; // I; } if (!string.IsNullOrEmpty(csrDetails.Title /**/)) { xn.Title = csrDetails.Title; // T; } if (!string.IsNullOrEmpty(csrDetails.SerialNumber /**/)) { xn.SerialNumber = csrDetails.SerialNumber; // SN; } if (!string.IsNullOrEmpty(csrDetails.UniqueIdentifier /**/)) { xn.UniqueIdentifier = csrDetails.UniqueIdentifier; // UID; } var xr = new X509Request(0, xn, rsaKeys); var md = MessageDigest.CreateByName(messageDigest); xr.Sign(rsaKeys, md); using (var bio = BIO.MemoryBuffer()) { xr.Write(bio); return(new Csr(bio.ReadString())); } }
public string RequestCertificateAndConvertToPfx(List <Binding> bindings) { var keyGenFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-gen-key.json"); var keyPemFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-key.pem"); var csrGenFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-gen-csr.json"); var csrPemFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-csr.pem"); var crtDerFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-crt.der"); var crtPemFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-crt.pem"); var chainPemFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-chain.pem"); var crtPfxFile = Path.Combine(Config.Path, $"{bindings[0].IPAddress}-all.pfx"); if (Globals.ShouldCreateCertificate()) { // TODOX Should check if the requested certificate (lowercase and sort hostnames) was issued in previous 10 days var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); try { if (Properties.Settings.Default.RSAKeyBits >= 2048) { rsaPkp.NumBits = Properties.Settings.Default.RSAKeyBits; } else { Globals.Log($"Requested key size of {Properties.Settings.Default.RSAKeyBits} is not secure. Using 2048."); rsaPkp.NumBits = 2048; } } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Globals.Log($"Unable to set RSA key size, letting ACMESharp select default. Error: {ex}"); Console.ResetColor(); } var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = bindings[0].Hostname, AlternativeNames = bindings.Select(x => x.Hostname).ToList(), }; var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); Globals.Log(); Globals.Log("Requesting Certificate"); var certRequ = _Client.RequestCertificate(derB64U); Globals.Log($" - Request Status: {certRequ.StatusCode}"); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Globals.Log($" - Saving DER certificate to {crtDerFile}"); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); using (FileStream intermediate = new FileStream(isuPemFile, FileMode.Open), certificate = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(chainPemFile, FileMode.Create)) { certificate.CopyTo(chain); intermediate.CopyTo(chain); } Globals.Log($" - Saving PFX certificate to {crtPfxFile}"); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, ""); } cp.Dispose(); // TODOX Should store that the requested certificate (lowercase and sort hostnames) was issued return(crtPfxFile); } else { throw new Exception($"Certificate request status = {certRequ.StatusCode}, uri = {certRequ.Uri}"); } } else { // Don't want to request a new cert, so return the filename to the last requested cert return(crtPfxFile); } }
public string GetCertificate(AcmeClient client) { IdnMapping idn = new IdnMapping(); var dnsIdentifier = idn.GetAscii(config.Host); CertificateProvider.RegisterProvider <BouncyCastleProvider>(BouncyCastleProvider.PROVIDER_NAME); var cp = CertificateProvider.GetProvider(BouncyCastleProvider.PROVIDER_NAME); var rsaPkp = new RsaPrivateKeyParams(); try { if (config.RSAKeyLength >= 1024) { rsaPkp.NumBits = config.RSAKeyLength; Trace.TraceInformation("RSAKeyBits: {0}", config.RSAKeyLength); } else { Trace.TraceWarning("RSA Key Bits less than 1024 is not secure. Letting ACMESharp default key bits. http://openssl.org/docs/manmaster/crypto/RSA_generate_key_ex.html"); } } catch (Exception ex) { Trace.TraceWarning("Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {0}", ex); Console.WriteLine($"Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {ex.Message.ToString()}"); } var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = dnsIdentifier, }; if (config.AlternateNames != null) { if (config.AlternateNames.Count > 0) { csrDetails.AlternativeNames = config.AlternateNames.Select(s => idn.GetAscii(s)); } } var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); Console.WriteLine($"\nRequesting Certificate"); Trace.TraceInformation("Requesting Certificate"); CertificateRequest certRequ = client.RequestCertificate(derB64u); Trace.TraceInformation("certRequ {0}", JsonConvert.SerializeObject(certRequ)); Console.WriteLine($" Request Status: {certRequ.StatusCode}"); Trace.TraceInformation("Request Status: {0}", certRequ.StatusCode); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(this.configPath, $"{dnsIdentifier}-gen-key.json"); var keyPemFile = Path.Combine(configPath, $"{dnsIdentifier}-key.pem"); var csrGenFile = Path.Combine(configPath, $"{dnsIdentifier}-gen-csr.json"); var csrPemFile = Path.Combine(configPath, $"{dnsIdentifier}-csr.pem"); var crtDerFile = Path.Combine(configPath, $"{dnsIdentifier}-crt.der"); var crtPemFile = Path.Combine(configPath, $"{dnsIdentifier}-crt.pem"); string crtPfxFile = null; crtPfxFile = Path.Combine(configPath, $"{dnsIdentifier}-all.pfx"); using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Console.WriteLine($" Saving Certificate to {crtDerFile}"); Trace.TraceInformation("Saving Certificate to {0}", crtDerFile); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); Console.WriteLine($" Saving Certificate to {crtPfxFile}"); Trace.TraceInformation("Saving Certificate to {0}", crtPfxFile); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, config.PFXPassword); } catch (Exception ex) { Trace.TraceError("Error exporting archive {0}", ex); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Error exporting archive: {ex.Message.ToString()}"); Console.ResetColor(); } } cp.Dispose(); return(crtPfxFile); } if ((int)certRequ.StatusCode == 429) { Trace.TraceError("Unable to request certificate, too many certificate requests to Let's Encrypt certificate servers for the domain within the last 7 days. Please try again later. (If you are testing, please use the staging enviroment where you can request unlimited number of certificates. During the beta period only 5 certificate requests per domain per week are allowed to the production environment.)"); throw new Exception("Unable to request certificate, too many certificate requests to Let's Encrypt certificate servers for the domain within the last 7 days. Please try again later. (If you are testing, please use the staging enviroment where you can request unlimited number of certificates. During the beta period only 5 certificate requests per domain per week are allowed to the production environment.)"); } Trace.TraceError("Request status = {0}", certRequ.StatusCode); throw new Exception($"Request status = {certRequ.StatusCode}"); }
public static string GetCertificate(Target binding) { var dnsIdentifier = binding.Host; var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = dnsIdentifier, }; var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); Console.WriteLine($"\nRequesting Certificate"); var certRequ = client.RequestCertificate(derB64u); Console.WriteLine($" Request Status: {certRequ.StatusCode}"); //Console.WriteLine($"Refreshing Cert Request"); //client.RefreshCertificateRequest(certRequ); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(configPath, $"{dnsIdentifier}-gen-key.json"); var keyPemFile = Path.Combine(configPath, $"{dnsIdentifier}-key.pem"); var csrGenFile = Path.Combine(configPath, $"{dnsIdentifier}-gen-csr.json"); var csrPemFile = Path.Combine(configPath, $"{dnsIdentifier}-csr.pem"); var crtDerFile = Path.Combine(configPath, $"{dnsIdentifier}-crt.der"); var crtPemFile = Path.Combine(configPath, $"{dnsIdentifier}-crt.pem"); string crtPfxFile = null; if (!CentralSSL) { crtPfxFile = Path.Combine(configPath, $"{dnsIdentifier}-all.pfx"); } else { crtPfxFile = Path.Combine(Options.CentralSSLStore, $"{dnsIdentifier}.pfx"); } using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Console.WriteLine($" Saving Certificate to {crtDerFile}"); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); Console.WriteLine($" Saving Certificate to {crtPfxFile} (with no password set)"); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target); } cp.Dispose(); return(crtPfxFile); } throw new Exception($"Request status = {certRequ.StatusCode}"); }
private string RequestCertificate() { var cp = CertificateProvider.GetProvider("BouncyCastle"); var rsaPkp = new RsaPrivateKeyParams { NumBits = this.keyLength }; var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = this.mainDomain, AlternativeNames = this.alternateNames.Except(new string[] { this.mainDomain }) }; var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); logger.Debug("Requesting Certificate"); var certRequ = client.RequestCertificate(derB64U); logger.Debug("Request Status: {0}", certRequ.StatusCode); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(certificatePath, $"{this.mainDomain}-gen-key.json"); var keyPemFile = Path.Combine(certificatePath, $"{this.mainDomain}-key.pem"); var csrGenFile = Path.Combine(certificatePath, $"{this.mainDomain}-gen-csr.json"); var csrPemFile = Path.Combine(certificatePath, $"{this.mainDomain}-csr.pem"); var crtDerFile = Path.Combine(certificatePath, $"{this.mainDomain}-crt.der"); var crtPemFile = Path.Combine(certificatePath, $"{this.mainDomain}-crt.pem"); string crtPfxFile = Path.Combine(certificatePath, $"{this.mainDomain}-all.pfx"); using (var fs = new FileStream(keyGenFile, FileMode.Create)) { cp.SavePrivateKey(rsaKeys, fs); } using (var fs = new FileStream(keyPemFile, FileMode.Create)) { cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); } using (var fs = new FileStream(csrGenFile, FileMode.Create)) { cp.SaveCsr(csr, fs); } using (var fs = new FileStream(csrPemFile, FileMode.Create)) { cp.ExportCsr(csr, EncodingFormat.PEM, fs); } logger.Info("Saving Certificate to {0}", crtDerFile); using (var file = File.Create(crtDerFile)) { certRequ.SaveCertificate(file); } Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); logger.Info($"Saving Certificate to {crtPfxFile}"); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target); } catch (Exception ex) { logger.Error("Error exporting archive: {0}", ex.Message); } } cp.Dispose(); return(crtPfxFile); } throw new Exception($"Request status = {certRequ.StatusCode}"); }
protected Csr GenerateCsr(CsrDetails csrDetails, RsaPrivateKey rsaKeyPair, string messageDigest = "SHA256") { var rsaKeys = CryptoKey.FromPrivateKey(rsaKeyPair.Pem, null); // Translate from our external form to our OpenSSL internal form // Ref: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_new.html var xn = new X509Name(); if (!string.IsNullOrEmpty(csrDetails.CommonName /**/)) { xn.Common = csrDetails.CommonName; // CN; } if (!string.IsNullOrEmpty(csrDetails.Country /**/)) { xn.Country = csrDetails.Country; // C; } if (!string.IsNullOrEmpty(csrDetails.StateOrProvince /**/)) { xn.StateOrProvince = csrDetails.StateOrProvince; // ST; } if (!string.IsNullOrEmpty(csrDetails.Locality /**/)) { xn.Locality = csrDetails.Locality; // L; } if (!string.IsNullOrEmpty(csrDetails.Organization /**/)) { xn.Organization = csrDetails.Organization; // O; } if (!string.IsNullOrEmpty(csrDetails.OrganizationUnit /**/)) { xn.OrganizationUnit = csrDetails.OrganizationUnit; // OU; } if (!string.IsNullOrEmpty(csrDetails.Description /**/)) { xn.Description = csrDetails.Description; // D; } if (!string.IsNullOrEmpty(csrDetails.Surname /**/)) { xn.Surname = csrDetails.Surname; // S; } if (!string.IsNullOrEmpty(csrDetails.GivenName /**/)) { xn.Given = csrDetails.GivenName; // G; } if (!string.IsNullOrEmpty(csrDetails.Initials /**/)) { xn.Initials = csrDetails.Initials; // I; } if (!string.IsNullOrEmpty(csrDetails.Title /**/)) { xn.Title = csrDetails.Title; // T; } if (!string.IsNullOrEmpty(csrDetails.SerialNumber /**/)) { xn.SerialNumber = csrDetails.SerialNumber; // SN; } if (!string.IsNullOrEmpty(csrDetails.UniqueIdentifier /**/)) { xn.UniqueIdentifier = csrDetails.UniqueIdentifier; // UID; } var xr = new X509Request(0, xn, rsaKeys); if (csrDetails.AlternativeNames != null) { // Format the common name as the first alternative name var commonName = $"{EXT_SAN_PREFIX_DNS}:{xn.Common}"; // Concat with all subsequent alternative names var altNames = commonName + string.Join("", csrDetails.AlternativeNames.Select( x => $",{EXT_SAN_PREFIX_DNS}:{x}")); // Assemble and add the SAN extension value var extensions = new OpenSSL.Core.Stack <X509Extension>(); extensions.Add(new X509Extension(xr, EXT_NAME_SAN, false, altNames)); xr.AddExtensions(extensions); } var md = MessageDigest.CreateByName(messageDigest); xr.Sign(rsaKeys, md); using (var bio = BIO.MemoryBuffer()) { xr.Write(bio); return(new Csr(bio.ReadString())); } }
public static string GetCertificate(Target binding) { List <string> identifiers = new List <string>(); if (!Options.San) { identifiers.Add(binding.Host); } identifiers.AddRange(binding.AlternativeNames); identifiers = identifiers.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToList(); if (identifiers.Count() == 0) { Log.Error("No DNS identifiers found."); throw new Exception("No DNS identifiers found."); } var identifier = identifiers.First(); var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); try { if (Properties.Settings.Default.RSAKeyBits >= 1024) { rsaPkp.NumBits = Properties.Settings.Default.RSAKeyBits; Log.Debug("RSAKeyBits: {RSAKeyBits}", Properties.Settings.Default.RSAKeyBits); } else { Log.Warning( "RSA Key Bits less than 1024 is not secure. Letting ACMESharp default key bits. http://openssl.org/docs/manmaster/crypto/RSA_generate_key_ex.html"); } } catch (Exception ex) { Log.Warning("Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {@ex}", ex); } var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails() { CommonName = identifiers.FirstOrDefault(), AlternativeNames = identifiers }; var csrParams = new CsrParams { Details = csrDetails }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); Log.Information("Requesting Certificate: {dnsIdentifier}"); var certRequ = _client.RequestCertificate(derB64U); Log.Debug("certRequ {@certRequ}", certRequ); Log.Information("Request Status: {StatusCode}", certRequ.StatusCode); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(_certificatePath, $"{identifier}-gen-key.json"); var keyPemFile = Path.Combine(_certificatePath, $"{identifier}-key.pem"); var csrGenFile = Path.Combine(_certificatePath, $"{identifier}-gen-csr.json"); var csrPemFile = Path.Combine(_certificatePath, $"{identifier}-csr.pem"); var crtDerFile = Path.Combine(_certificatePath, $"{identifier}-crt.der"); var crtPemFile = Path.Combine(_certificatePath, $"{identifier}-crt.pem"); var chainPemFile = Path.Combine(_certificatePath, $"{identifier}-chain.pem"); string crtPfxFile = null; if (!Options.CentralSsl) { crtPfxFile = Path.Combine(_certificatePath, $"{identifier}-all.pfx"); } else { crtPfxFile = Path.Combine(Options.CentralSslStore, $"{identifier}.pfx"); } using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Log.Information("Saving Certificate to {crtDerFile}", crtDerFile); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); using (FileStream intermediate = new FileStream(isuPemFile, FileMode.Open), certificate = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(chainPemFile, FileMode.Create)) { certificate.CopyTo(chain); intermediate.CopyTo(chain); } Log.Debug("CentralSsl {CentralSsl} San {San}", Options.CentralSsl.ToString(), Options.San.ToString()); if (Options.CentralSsl && Options.San) { foreach (var host in identifiers) { Console.WriteLine($"Host: {host}"); crtPfxFile = Path.Combine(Options.CentralSslStore, $"{host}.pfx"); Log.Information("Saving Certificate to {crtPfxFile}", crtPfxFile); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, Properties.Settings.Default.PFXPassword); } catch (Exception ex) { Log.Error("Error exporting archive {@ex}", ex); } } } } else //Central SSL and San need to save the cert for each hostname { Log.Information("Saving Certificate to {crtPfxFile}", crtPfxFile); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, Properties.Settings.Default.PFXPassword); } catch (Exception ex) { Log.Error("Error exporting archive {@ex}", ex); } } } cp.Dispose(); return(crtPfxFile); } Log.Error("Request status = {StatusCode}", certRequ.StatusCode); throw new Exception($"Request status = {certRequ.StatusCode}"); }
private string GetCertificate(string host) { Log("\t\t\tGetCertificate started"); var certificateProvider = CertificateProvider.GetProvider(); var rsaPrivateKeyParams = new RsaPrivateKeyParams() { NumBits = Properties.Settings.Default.RSAKeyBits, }; var rsaPrivateKey = certificateProvider.GeneratePrivateKey(rsaPrivateKeyParams); var csrDetails = new CsrDetails { CommonName = host, }; var csrParams = new CsrParams { Details = csrDetails, }; var csr = certificateProvider.GenerateCsr(csrParams, rsaPrivateKey, Crt.MessageDigest.SHA256); byte[] derBytes; using (var ms = new MemoryStream()) { certificateProvider.ExportCsr(csr, EncodingFormat.DER, ms); derBytes = ms.ToArray(); } CertificateRequest requestCertificate = null; var derBase64UrlEncoded = JwsHelper.Base64UrlEncode(derBytes); try { requestCertificate = this.client.RequestCertificate(derBase64UrlEncoded); } catch (Exception ex) { Log("\t\t\t\tGetCertificate error {0}", ex.InnerException.Message); certificateProvider.Dispose(); return(null); } var crtPfxFile = host + "-all.pfx"; if (requestCertificate.StatusCode != System.Net.HttpStatusCode.Created) { crtPfxFile = null; Log("\t\t\t\tGetCertificate certRequ.StatusCode {0}", requestCertificate.StatusCode); } else { var keyGenFile = host + "-gen-key.json"; var keyPemFile = host + "-key.pem"; var csrGenFile = host + "-gen-csr.json"; var csrPemFile = host + "-csr.pem"; var crtDerFile = host + "-crt.der"; var crtPemFile = host + "-crt.pem"; var chainPemFile = host + "-chain.pem"; using (var fs = new FileStream(keyGenFile, FileMode.Create)) certificateProvider.SavePrivateKey(rsaPrivateKey, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) certificateProvider.ExportPrivateKey(rsaPrivateKey, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) certificateProvider.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) certificateProvider.ExportCsr(csr, EncodingFormat.PEM, fs); using (var file = File.Create(crtDerFile)) requestCertificate.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = certificateProvider.ImportCertificate(EncodingFormat.DER, source); certificateProvider.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(requestCertificate, certificateProvider); using (FileStream intermediate = new FileStream(isuPemFile, FileMode.Open), certificate = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(chainPemFile, FileMode.Create)) { certificate.CopyTo(chain); intermediate.CopyTo(chain); } using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = certificateProvider.ImportCertificate(EncodingFormat.PEM, source); certificateProvider.ExportArchive(rsaPrivateKey, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, Properties.Settings.Default.PFXPassword); } catch (Exception ex) { Log("\t\t\t\tGetCertificate error {0}", ex.Message); } } } certificateProvider.Dispose(); Log("\t\t\tGetCertificate ended"); return(crtPfxFile); }
protected override void ProcessRecord() { using (var vlt = Util.VaultHelper.GetVault(VaultProfile)) { vlt.OpenStorage(); var v = vlt.LoadVault(); if (v.Registrations == null || v.Registrations.Count < 1) { throw new InvalidOperationException("No registrations found"); } var ri = v.Registrations[0]; var r = ri.Registration; if (v.Identifiers == null || v.Identifiers.Count < 1) { throw new InvalidOperationException("No identifiers found"); } var ii = v.Identifiers.GetByRef(IdentifierRef); if (ii == null) { throw new Exception("Unable to find an Identifier for the given reference"); } var ci = new CertificateInfo { Id = EntityHelper.NewId(), Alias = Alias, Label = Label, Memo = Memo, IdentifierRef = ii.Id, IdentifierDns = ii.Dns, }; if (Generate) { Func <string, string> csrDtlValue = x => null; Func <string, IEnumerable <string> > csrDtlValues = x => null; if (CsrDetails != null) { csrDtlValue = x => CsrDetails.ContainsKey(x) ? CsrDetails[x] as string : null; csrDtlValues = x => !string.IsNullOrEmpty(csrDtlValue(x)) ? Regex.Split(csrDtlValue(x).Trim(), "[\\s,;]+") : null; } var csrDetails = new CsrDetails { // Common Name is always pulled from associated Identifier CommonName = ii.Dns, // Remaining elements will be used if defined AlternativeNames /**/ = csrDtlValues(nameof(PKI.CsrDetails.AlternativeNames)), Country /**/ = csrDtlValue(nameof(PKI.CsrDetails.Country)), Description /**/ = csrDtlValue(nameof(PKI.CsrDetails.Description)), Email /**/ = csrDtlValue(nameof(PKI.CsrDetails.Email)), GivenName /**/ = csrDtlValue(nameof(PKI.CsrDetails.GivenName)), Initials /**/ = csrDtlValue(nameof(PKI.CsrDetails.Initials)), Locality /**/ = csrDtlValue(nameof(PKI.CsrDetails.Locality)), Organization /**/ = csrDtlValue(nameof(PKI.CsrDetails.Organization)), OrganizationUnit /**/ = csrDtlValue(nameof(PKI.CsrDetails.OrganizationUnit)), SerialNumber /**/ = csrDtlValue(nameof(PKI.CsrDetails.SerialNumber)), StateOrProvince /**/ = csrDtlValue(nameof(PKI.CsrDetails.StateOrProvince)), Surname /**/ = csrDtlValue(nameof(PKI.CsrDetails.Surname)), Title /**/ = csrDtlValue(nameof(PKI.CsrDetails.Title)), UniqueIdentifier /**/ = csrDtlValue(nameof(PKI.CsrDetails.UniqueIdentifier)), }; if (AlternativeIdentifierRefs != null) { if (csrDetails.AlternativeNames != null) { throw new Exception("Alternative names already specified manually") .With(nameof(csrDetails.AlternativeNames), string.Join(",", csrDetails.AlternativeNames)); } csrDetails.AlternativeNames = AlternativeIdentifierRefs.Select(alternativeIdentifierRef => { var altId = v.Identifiers.GetByRef($"{alternativeIdentifierRef}"); if (altId == null) { throw new Exception("Unable to find an Identifier for the given Alternative Identifier reference") .With(nameof(alternativeIdentifierRef), alternativeIdentifierRef) .With(nameof(AlternativeIdentifierRefs), string.Join(",", AlternativeIdentifierRefs)); } return(altId.Dns); }); ci.AlternativeIdentifierDns = csrDetails.AlternativeNames.ToArray(); } ci.GenerateDetailsFile = $"{ci.Id}-gen.json"; var asset = vlt.CreateAsset(VaultAssetType.CsrDetails, ci.GenerateDetailsFile); using (var s = vlt.SaveAsset(asset)) { JsonHelper.Save(s, csrDetails); } } else { if (!File.Exists(KeyPemFile)) { throw new FileNotFoundException("Missing specified RSA Key file path"); } if (!File.Exists(CsrPemFile)) { throw new FileNotFoundException("Missing specified CSR details file path"); } var keyPemFile = $"{ci.Id}-key.pem"; var csrPemFile = $"{ci.Id}-csr.pem"; var keyAsset = vlt.CreateAsset(VaultAssetType.KeyPem, keyPemFile, true); var csrAsset = vlt.CreateAsset(VaultAssetType.CsrPem, csrPemFile); using (Stream fs = new FileStream(KeyPemFile, FileMode.Open), s = vlt.SaveAsset(keyAsset)) { fs.CopyTo(s); } using (Stream fs = new FileStream(CsrPemFile, FileMode.Open), s = vlt.SaveAsset(csrAsset)) { fs.CopyTo(s); } ci.KeyPemFile = keyPemFile; ci.CsrPemFile = csrPemFile; } if (v.Certificates == null) { v.Certificates = new EntityDictionary <CertificateInfo>(); } v.Certificates.Add(ci); vlt.SaveVault(v); WriteObject(ci); } }
public string GetCertificate(TargetApplication targetApplication) { using (var pkiTool = PkiToolExtManager.GetPkiTool("BouncyCastle")) { var rsaKeyParams = new RsaPrivateKeyParams(); var rsaKeys = pkiTool.GeneratePrivateKey(rsaKeyParams); var certificateName = targetApplication.Hostnames.First(); var baseOutPutPath = _configuration.GetBaseOutPutPath(targetApplication); var certificateFolder = Path.Combine(baseOutPutPath, $"{DateTime.Now:yyyyMMdd_HHmmss}"); if (Directory.Exists(certificateFolder) == false) { Directory.CreateDirectory(certificateFolder); } var csrDetails = new CsrDetails { CommonName = certificateName, AlternativeNames = targetApplication.Hostnames, }; var certificateSigningRequest = pkiTool.GenerateCsr( new CsrParams { Details = csrDetails }, rsaKeys, Crt.MessageDigest.SHA256); byte[] certificateSigningRequestBytes; using (var bs = new MemoryStream()) { pkiTool.ExportCsr(certificateSigningRequest, EncodingFormat.DER, bs); certificateSigningRequestBytes = bs.ToArray(); } var certificateSigningRequestBytesBase64 = JwsHelper.Base64UrlEncode(certificateSigningRequestBytes); _logger.Information("Requesting a certificate"); var certificateRequest = _acmeClient.RequestCertificate(certificateSigningRequestBytesBase64); _logger.Debug("Result of certificate request {certificateRequest}", certificateRequest); _logger.Information("Certificate request status is {statusCode}", certificateRequest.StatusCode); if (certificateRequest.StatusCode == HttpStatusCode.Created) { var keyGenFile = Path.Combine(certificateFolder, $"{certificateName}-gen-key.json"); var keyPemFile = Path.Combine(certificateFolder, $"{certificateName}-key.pem"); var csrGenFile = Path.Combine(certificateFolder, $"{certificateName}-gen-csr.json"); var csrPemFile = Path.Combine(certificateFolder, $"{certificateName}-csr.pem"); var crtDerFile = Path.Combine(certificateFolder, $"{certificateName}-crt.der"); var crtPemFile = Path.Combine(certificateFolder, $"{certificateName}-crt.pem"); var chainPemFile = Path.Combine(certificateFolder, $"{certificateName}-chain.pem"); using (var fileStream = new FileStream(keyGenFile, FileMode.Create)) pkiTool.SavePrivateKey(rsaKeys, fileStream); using (var fileStream = new FileStream(keyPemFile, FileMode.Create)) pkiTool.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fileStream); using (var fileStream = new FileStream(csrGenFile, FileMode.Create)) pkiTool.SaveCsr(certificateSigningRequest, fileStream); using (var fileStream = new FileStream(csrPemFile, FileMode.Create)) pkiTool.ExportCsr(certificateSigningRequest, EncodingFormat.PEM, fileStream); _logger.Information("Saving certificate to {crtDerFile}", crtDerFile); using (var file = File.Create(crtDerFile)) certificateRequest.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = pkiTool.ImportCertificate(EncodingFormat.DER, source); pkiTool.ExportCertificate(crt, EncodingFormat.PEM, target); } var issuerCertificate = GetIssuerCertificate(certificateRequest, pkiTool, certificateFolder, targetApplication); using (FileStream intermediate = new FileStream(issuerCertificate, FileMode.Open), certificate = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(chainPemFile, FileMode.Create)) { certificate.CopyTo(chain); intermediate.CopyTo(chain); } var crtPfxFile = Path.Combine(certificateFolder, $"{targetApplication.Hostnames.First()}.pfx"); _logger.Information("Saving certificate for hostname {host} and alternative hostnames {@altHostNames} to {crtPfxFile}", targetApplication.Hostnames.First(), targetApplication.Hostnames.Skip(1), crtPfxFile); using (FileStream source = new FileStream(issuerCertificate, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var importCertificate = pkiTool.ImportCertificate(EncodingFormat.PEM, source); pkiTool.ExportArchive(rsaKeys, new[] { crt, importCertificate }, ArchiveFormat.PKCS12, target, targetApplication.CertificatePassword); } catch (Exception ex) { _logger.Error("Error exporting archive {@ex}", ex); } } pkiTool.Dispose(); return(crtPfxFile); } _logger.Error("Request status is {statusCode}", certificateRequest.StatusCode); throw new Exception($"Request status = {certificateRequest.StatusCode}"); } }
public static string GetCertificate(Target binding) { var dnsIdentifier = binding.Host; var SANList = binding.AlternativeNames; List <string> allDnsIdentifiers = new List <string>(); if (!Options.SAN) { allDnsIdentifiers.Add(binding.Host); } if (binding.AlternativeNames != null) { allDnsIdentifiers.AddRange(binding.AlternativeNames); } var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); try { if (Properties.Settings.Default.RSAKeyBits >= 1024) { rsaPkp.NumBits = Properties.Settings.Default.RSAKeyBits; Log.Debug("RSAKeyBits: {RSAKeyBits}", Properties.Settings.Default.RSAKeyBits); } else { Log.Warning("RSA Key Bits less than 1024 is not secure. Letting ACMESharp default key bits. http://openssl.org/docs/manmaster/crypto/RSA_generate_key_ex.html"); } } catch (Exception ex) { Log.Warning("Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {@ex}", ex); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {ex.Message.ToString()}"); Console.ResetColor(); } var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = allDnsIdentifiers[0], }; if (SANList != null) { if (SANList.Count > 0) { csrDetails.AlternativeNames = SANList; } } var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); Console.WriteLine($"\nRequesting Certificate"); Log.Information("Requesting Certificate"); var certRequ = client.RequestCertificate(derB64u); Log.Debug("certRequ {@certRequ}", certRequ); Console.WriteLine($" Request Status: {certRequ.StatusCode}"); Log.Information("Request Status: {StatusCode}", certRequ.StatusCode); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { var keyGenFile = Path.Combine(certificatePath, $"{dnsIdentifier}-gen-key.json"); var keyPemFile = Path.Combine(certificatePath, $"{dnsIdentifier}-key.pem"); var csrGenFile = Path.Combine(certificatePath, $"{dnsIdentifier}-gen-csr.json"); var csrPemFile = Path.Combine(certificatePath, $"{dnsIdentifier}-csr.pem"); var crtDerFile = Path.Combine(certificatePath, $"{dnsIdentifier}-crt.der"); var crtPemFile = Path.Combine(certificatePath, $"{dnsIdentifier}-crt.pem"); string crtPfxFile = null; if (!CentralSSL) { crtPfxFile = Path.Combine(certificatePath, $"{dnsIdentifier}-all.pfx"); } else { crtPfxFile = Path.Combine(Options.CentralSSLStore, $"{dnsIdentifier}.pfx"); } using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Console.WriteLine($" Saving Certificate to {crtDerFile}"); Log.Information("Saving Certificate to {crtDerFile}", crtDerFile); using (var file = File.Create(crtDerFile)) certRequ.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } // To generate a PKCS#12 (.PFX) file, we need the issuer's public certificate var isuPemFile = GetIssuerCertificate(certRequ, cp); Log.Debug("CentralSSL {CentralSSL} SAN {SAN}", CentralSSL.ToString(), Options.SAN.ToString()); if (CentralSSL && Options.SAN) { foreach (var host in allDnsIdentifiers) { Console.WriteLine($"Host: {host}"); crtPfxFile = Path.Combine(Options.CentralSSLStore, $"{host}.pfx"); Console.WriteLine($" Saving Certificate to {crtPfxFile}"); Log.Information("Saving Certificate to {crtPfxFile}", crtPfxFile); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, Properties.Settings.Default.PFXPassword); } catch (Exception ex) { Log.Error("Error exporting archive {@ex}", ex); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Error exporting archive: {ex.Message.ToString()}"); Console.ResetColor(); } } } } else //Central SSL and SAN need to save the cert for each hostname { Console.WriteLine($" Saving Certificate to {crtPfxFile}"); Log.Information("Saving Certificate to {crtPfxFile}", crtPfxFile); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(crtPfxFile, FileMode.Create)) { try { var isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, Properties.Settings.Default.PFXPassword); } catch (Exception ex) { Log.Error("Error exporting archive {@ex}", ex); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Error exporting archive: {ex.Message.ToString()}"); Console.ResetColor(); } } } cp.Dispose(); return(crtPfxFile); } Log.Error("Request status = {StatusCode}", certRequ.StatusCode); throw new Exception($"Request status = {certRequ.StatusCode}"); }
protected override void ProcessRecord() { using (var vp = InitializeVault.GetVaultProvider(VaultProfile)) { vp.OpenStorage(); var v = vp.LoadVault(); if (v.Registrations == null || v.Registrations.Count < 1) { throw new InvalidOperationException("No registrations found"); } var ri = v.Registrations[0]; var r = ri.Registration; if (v.Identifiers == null || v.Identifiers.Count < 1) { throw new InvalidOperationException("No identifiers found"); } var ii = v.Identifiers.GetByRef(Identifier); if (ii == null) { throw new Exception("Unable to find an Identifier for the given reference"); } var ci = new CertificateInfo { Id = EntityHelper.NewId(), Alias = Alias, Label = Label, Memo = Memo, IdentifierRef = ii.Id, }; if (Generate) { var csrDetails = new CsrDetails { CommonName = ii.Dns, }; ci.GenerateDetailsFile = $"{ci.Id}-gen.json"; var asset = vp.CreateAsset(VaultAssetType.CsrDetails, ci.GenerateDetailsFile); using (var s = vp.SaveAsset(asset)) { JsonHelper.Save(s, csrDetails); } } else { if (!File.Exists(KeyPemFile)) { throw new FileNotFoundException("Missing specified RSA Key file path"); } if (!File.Exists(CsrPemFile)) { throw new FileNotFoundException("Missing specified CSR details file path"); } var keyPemFile = $"{ci.Id}-key.pem"; var csrPemFile = $"{ci.Id}-csr.pem"; var keyAsset = vp.CreateAsset(VaultAssetType.KeyPem, keyPemFile, true); var csrAsset = vp.CreateAsset(VaultAssetType.CsrPem, csrPemFile); using (Stream fs = new FileStream(KeyPemFile, FileMode.Open), s = vp.SaveAsset(keyAsset)) { fs.CopyTo(s); } using (Stream fs = new FileStream(KeyPemFile, FileMode.Open), s = vp.SaveAsset(csrAsset)) { fs.CopyTo(s); } ci.KeyPemFile = keyPemFile; ci.CsrPemFile = csrPemFile; } if (v.Certificates == null) { v.Certificates = new EntityDictionary <CertificateInfo>(); } v.Certificates.Add(ci); vp.SaveVault(v); WriteObject(ci); } }
/// <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 (alternatehosts != null && alternatehosts.Any()) { throw new NotSupportedException("Alternate host provisioning not supported yet."); } List <string> allDnsIdentifiers = new List <string>() { mainhost }; if (alternatehosts != null) { allDnsIdentifiers.AddRange(alternatehosts); } // Tomado de app.config var rsaKeyBits = 2048; // 1024;// if (Environment.Is64BitProcess) { CertificateProvider.RegisterProvider(typeof(ACMESharp.PKI.Providers.OpenSslLib64Provider)); } else { CertificateProvider.RegisterProvider(typeof(ACMESharp.PKI.Providers.OpenSslLib32Provider)); } var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams(); try { if (rsaKeyBits >= 1024) { rsaPkp.NumBits = rsaKeyBits; // Log.Debug("RSAKeyBits: {RSAKeyBits}", Properties.Settings.Default.RSAKeyBits); } else { // Log.Warning( // "RSA Key Bits less than 1024 is not secure. Letting ACMESharp default key bits. http://openssl.org/docs/manmaster/crypto/RSA_generate_key_ex.html"); } } catch (Exception ex) { this.Logger.LogInfo(true, $"Unable to set RSA Key Bits, Letting ACMESharp default key bits, Error: {ex.Message.ToString()}"); } var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrDetails = new CsrDetails { CommonName = allDnsIdentifiers[0] }; if (alternatehosts != null) { if (alternatehosts.Count > 0) { csrDetails.AlternativeNames = alternatehosts; } } var csrParams = new CsrParams { Details = csrDetails, }; var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); this.Logger.LogInfo(true, $"Requesting Certificate"); // Log.Information("Requesting Certificate"); var certRequ = this.AcmeClient.RequestCertificate(derB64U); // Log.Debug("certRequ {@certRequ}", certRequ); this.Logger.LogInfo(true, $"Request Status: {certRequ.StatusCode}"); if (certRequ.StatusCode != System.Net.HttpStatusCode.Created) { throw new Exception($"Could not create certificate request, response code: = {certRequ.StatusCode}"); } var keyGenFile = Path.Combine(certificatePath, $"{certificatename}-gen-key.json"); var keyPemFile = Path.Combine(certificatePath, $"{certificatename}-key.pem"); var csrGenFile = Path.Combine(certificatePath, $"{certificatename}-gen-csr.json"); var csrPemFile = Path.Combine(certificatePath, $"{certificatename}-csr.pem"); var crtDerFile = Path.Combine(certificatePath, $"{certificatename}-crt.der"); var crtPemFile = Path.Combine(certificatePath, $"{certificatename}-crt.pem"); var chainPemFile = Path.Combine(certificatePath, $"{certificatename}-chain.pem"); var pfxPemFile = Path.Combine(certificatePath, $"{certificatename}.pfx"); using (var fs = new FileStream(keyGenFile, FileMode.Create)) { cp.SavePrivateKey(rsaKeys, fs); } using (var fs = new FileStream(keyPemFile, FileMode.Create)) { cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); } using (var fs = new FileStream(csrGenFile, FileMode.Create)) { cp.SaveCsr(csr, fs); } using (var fs = new FileStream(csrPemFile, FileMode.Create)) { cp.ExportCsr(csr, EncodingFormat.PEM, fs); } this.Logger.LogInfo(true, $"Saving Certificate to {crtDerFile}"); // Log.Information("Saving Certificate to {crtDerFile}", crtDerFile); using (var file = File.Create(crtDerFile)) { certRequ.SaveCertificate(file); } Crt crt; using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } cp.Dispose(); var ret = new CertificatePaths() { chainPemFile = chainPemFile, crtDerFile = crtDerFile, crtPemFile = crtPemFile, csrGenFile = csrGenFile, csrPemFile = csrPemFile, keyGenFile = keyGenFile, keyPemFile = keyPemFile, name = certificatename, pfxPemFile = pfxPemFile }; // Generate the PFX version manually UtilsCertificate.CreatePfXfromPem(ret.crtPemFile, ret.keyPemFile, ret.pfxPemFile, null); return(ret); }