public void TestExportArchive() { using (var cp = CertificateProvider.GetProvider()) { var testPk = "CertificateProviderTests.key.json"; var testCert = "CertificateProviderTests-Certificate.pem"; var testIcaCert = "CertificateProviderTests-ICA-Certificate.pem"; PrivateKey pk; using (var s = new FileStream(testPk, FileMode.Open)) { pk = cp.LoadPrivateKey(s); } Crt cert; using (var s = new FileStream(testCert, FileMode.Open)) { cert = cp.ImportCertificate(EncodingFormat.PEM, s); } Crt icaCert; using (var s = new FileStream(testIcaCert, FileMode.Open)) { icaCert = cp.ImportCertificate(EncodingFormat.PEM, s); } using (var s = new MemoryStream()) { var certs = new[] { cert, icaCert }; cp.ExportArchive(pk, certs, ArchiveFormat.PKCS12, s); } } }
static void RetrieveCertificates(AcmeClient client, string api, string domain, string certificatesFolder, int certBits) { var cp = CertificateProvider.GetProvider(); var rsaPkp = new RsaPrivateKeyParams() { NumBits = certBits }; var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csrParams = new CsrParams { Details = new CsrDetails { CommonName = domain } }; var derRaw = default(byte[]); var csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); var certRequ = client.RequestCertificate(derB64U); if (certRequ.StatusCode == HttpStatusCode.Created) { GenerateCertFiles(cp, rsaKeys, csr, certRequ, certificatesFolder, domain); } }
private static CertificateProvider GetCP() { CertificateProvider.RegisterProvider <ACMESharp.PKI.Providers.OpenSslCliProvider>(); //CertificateProvider.RegisterProvider<ACMESharp.PKI.Providers.CertEnrollProvider>(); return(CertificateProvider.GetProvider()); }
private void TestImportCertificate(EncodingFormat fmt, string filePath) { using (var cp = CertificateProvider.GetProvider()) { using (var source = new FileStream(filePath, FileMode.Open)) { var crt = cp.ImportCertificate(fmt, source); } } }
public static void GetCertificateUseCSR(CertificateGeneratorParam param) { if (param == null) { log.Info($" {nameof(param)} is null"); return; } var dnsIdentifier = DateTime.Now.ToString("yyyyMMddHHmmss"); var cp = CertificateProvider.GetProvider(); MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(param.csr)); var csr = cp.ImportCsr(EncodingFormat.PEM, ms); ms.Dispose(); 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}"); if (certRequ.StatusCode == System.Net.HttpStatusCode.Created) { 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"); 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); } cp.Dispose(); return; } throw new Exception($"Request status = {certRequ.StatusCode}"); }
private void TestExportCertificate(EncodingFormat fmt, string filePath) { using (var cp = CertificateProvider.GetProvider()) { using (var source = new FileStream(filePath, FileMode.Open)) { var crt = cp.ImportCertificate(fmt, source); using (var target = new MemoryStream()) { cp.ExportCertificate(crt, fmt, target); } } } }
private void TestImportRsaCsr(EncodingFormat fmt) { using (var cp = CertificateProvider.GetProvider()) { var pkp = new RsaPrivateKeyParams(); var pk = cp.GeneratePrivateKey(pkp); var crp = new CsrParams { Details = new CsrDetails { CommonName = "TEST CERT", } }; var csr = cp.GenerateCsr(crp, pk, Crt.MessageDigest.SHA256); byte[] bytes; using (var target = new MemoryStream()) { cp.ExportCsr(csr, fmt, target); bytes = target.ToArray(); } var imp = csr; using (var source = new MemoryStream(bytes)) { imp = cp.ImportCsr(fmt, source); } using (MemoryStream save1 = new MemoryStream(), save2 = new MemoryStream()) { cp.SaveCsr(csr, save1); cp.SaveCsr(imp, save2); var bytes1 = save1.ToArray(); var bytes2 = save2.ToArray(); CollectionAssert.AreEqual(bytes1, bytes2); } } }
public void TestLoadAndSavePrivateKey() { using (var cp = CertificateProvider.GetProvider()) { var testPk = "CertificateProviderTests.key.json"; PrivateKey pk; using (var s = new FileStream(testPk, FileMode.Open)) { pk = cp.LoadPrivateKey(s); } using (var s = new MemoryStream()) { cp.SavePrivateKey(pk, s); var bytes = File.ReadAllBytes(testPk); CollectionAssert.AreEqual(bytes, s.ToArray()); } } }
private void TestExportRsaCsr(EncodingFormat fmt) { using (var cp = CertificateProvider.GetProvider()) { var pkp = new RsaPrivateKeyParams(); var pk = cp.GeneratePrivateKey(pkp); var crp = new CsrParams { Details = new CsrDetails { CommonName = "TEST CERT", } }; var csr = cp.GenerateCsr(crp, pk, Crt.MessageDigest.SHA256); using (var target = new MemoryStream()) { cp.ExportCsr(csr, fmt, target); } } }
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 void GetCertificate() { Log.Information("Requesting Certificate"); using (CertificateProvider cp = CertificateProvider.GetProvider()) { RsaPrivateKeyParams rsaPkp = new RsaPrivateKeyParams(); PrivateKey rsaKeys = cp.GeneratePrivateKey(rsaPkp); CsrParams csrParams = new CsrParams { Details = new CsrDetails { CommonName = _options.HostName, }, }; Csr csr = cp.GenerateCsr(csrParams, rsaKeys, Crt.MessageDigest.SHA256); byte[] derRaw; using (MemoryStream bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } string derB64U = JwsHelper.Base64UrlEncode(derRaw); CertificateRequest certReq = _acmeClient.RequestCertificate(derB64U); if (certReq.StatusCode != HttpStatusCode.Created) { throw new Exception($"Request status = {certReq.StatusCode}"); } using (FileStream fs = new FileStream(_options.WellKnownFilePaths[WellKnownFile.KeyGen], FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (FileStream fs = new FileStream(_options.WellKnownFilePaths[WellKnownFile.KeyPem], FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (FileStream fs = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CsrGen], FileMode.Create)) cp.SaveCsr(csr, fs); using (FileStream fs = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CsrPem], FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); Log.Information($"Saving Certificate to {_options.WellKnownFilePaths[WellKnownFile.CrtDer]}"); using (FileStream file = File.Create(_options.WellKnownFilePaths[WellKnownFile.CrtDer])) certReq.SaveCertificate(file); Crt crt; using (FileStream source = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CrtDer], FileMode.Open), target = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CrtPem], 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 string isuPemFile = GetIssuerCertificate(certReq, cp); using (FileStream intermediate = new FileStream(isuPemFile, FileMode.Open), certificate = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CrtPem], FileMode.Open), chain = new FileStream(_options.WellKnownFilePaths[WellKnownFile.ChainPem], FileMode.Create)) { certificate.CopyTo(chain); intermediate.CopyTo(chain); } Log.Information($"Saving Certificate to {_options.WellKnownFilePaths[WellKnownFile.CrtPfx]}"); using (FileStream source = new FileStream(isuPemFile, FileMode.Open), target = new FileStream(_options.WellKnownFilePaths[WellKnownFile.CrtPfx], FileMode.Create)) { Crt isuCrt = cp.ImportCertificate(EncodingFormat.PEM, source); cp.ExportArchive(rsaKeys, new[] { crt, isuCrt }, ArchiveFormat.PKCS12, target, _options.PfxPassword); } } }
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}"); }
public void Test0170_GenCsrAndRequestCertificate() { using (var cp = CertificateProvider.GetProvider()) { var rsaKeyParams = new RsaPrivateKeyParams(); var rsaKey = cp.GeneratePrivateKey(rsaKeyParams); _testGenCsr_RsaKeysFile = $"{_baseLocalStore}\\TestGenCsr-rsaKeys.txt"; using (var fs = new FileStream(_testGenCsr_RsaKeysFile, FileMode.Create)) { cp.SavePrivateKey(rsaKey, fs); } var csrParams = new CsrParams { Details = new CsrDetails { CommonName = TEST_CN1 } }; var csr = cp.GenerateCsr(csrParams, rsaKey, Crt.MessageDigest.SHA256); _testGenCsr_CsrDetailsFile = $"{_baseLocalStore}\\TestGenCsr-csrDetails.txt"; using (var fs = new FileStream(_testGenCsr_CsrDetailsFile, FileMode.Create)) { cp.SaveCsrParams(csrParams, fs); } _testGenCsr_CsrFile = $"{_baseLocalStore}\\TestGenCsr-csr.txt"; using (var fs = new FileStream(_testGenCsr_CsrFile, FileMode.Create)) { cp.SaveCsr(csr, fs); } using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream(_testRegister_AcmeSignerFile, FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream(_testRegister_AcmeRegFile, FileMode.Open)) { reg = AcmeRegistration.Load(fs); } byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); using (var client = BuildClient(testTagHeader: nameof(Test0170_GenCsrAndRequestCertificate))) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); var certRequ = client.RequestCertificate(derB64u); _testCertRequ_AcmeCertRequFile = $"{_baseLocalStore}\\TestCertRequ.acmeCertRequ"; using (var fs = new FileStream(_testCertRequ_AcmeCertRequFile, FileMode.Create)) { certRequ.Save(fs); } } } } }
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.Certificates == null || v.Certificates.Count < 1) { throw new InvalidOperationException("No certificates found"); } var ci = v.Certificates.GetByRef(Ref); if (ci == null) { throw new Exception("Unable to find a Certificate for the given reference"); } if (!LocalOnly) { if (ci.CertificateRequest == null) { throw new Exception("Certificate has not been submitted yet; cannot update status"); } using (var c = ClientHelper.GetClient(v, ri)) { c.Init(); c.GetDirectory(true); c.RefreshCertificateRequest(ci.CertificateRequest, UseBaseUri); } if ((Repeat || string.IsNullOrEmpty(ci.CrtPemFile)) && !string.IsNullOrEmpty(ci.CertificateRequest.CertificateContent)) { var crtDerFile = $"{ci.Id}-crt.der"; var crtPemFile = $"{ci.Id}-crt.pem"; var crtDerAsset = vp.ListAssets(crtDerFile, VaultAssetType.CrtDer).FirstOrDefault(); var crtPemAsset = vp.ListAssets(crtPemFile, VaultAssetType.CrtPem).FirstOrDefault(); if (crtDerAsset == null) { crtDerAsset = vp.CreateAsset(VaultAssetType.CrtDer, crtDerFile); } if (crtPemAsset == null) { crtPemAsset = vp.CreateAsset(VaultAssetType.CrtPem, crtPemFile); } using (var cp = CertificateProvider.GetProvider()) { var bytes = ci.CertificateRequest.GetCertificateContent(); using (Stream source = new MemoryStream(bytes), derTarget = vp.SaveAsset(crtDerAsset), pemTarget = vp.SaveAsset(crtPemAsset)) { var crt = cp.ImportCertificate(EncodingFormat.DER, source); // We're saving the DER format cert "through" // the CP in order to validate its content cp.ExportCertificate(crt, EncodingFormat.DER, derTarget); ci.CrtDerFile = crtDerFile; cp.ExportCertificate(crt, EncodingFormat.PEM, pemTarget); ci.CrtPemFile = crtPemFile; } } var x509 = new X509Certificate2(ci.CertificateRequest.GetCertificateContent()); ci.SerialNumber = x509.SerialNumber; ci.Thumbprint = x509.Thumbprint; ci.SignatureAlgorithm = x509.SignatureAlgorithm?.FriendlyName; ci.Signature = x509.GetCertHashString(); } if (Repeat || string.IsNullOrEmpty(ci.IssuerSerialNumber)) { var linksEnum = ci.CertificateRequest.Links; if (linksEnum != null) { var links = new LinkCollection(linksEnum); var upLink = links.GetFirstOrDefault("up"); if (upLink != null) { // We need to save the ICA certificate to a local // temp file so that we can read it in and store // it properly as a vault asset through a stream var tmp = Path.GetTempFileName(); try { using (var web = new WebClient()) { if (v.Proxy != null) { web.Proxy = v.Proxy.GetWebProxy(); } var uri = new Uri(new Uri(v.BaseUri), upLink.Uri); web.DownloadFile(uri, tmp); } var cacert = new X509Certificate2(tmp); var sernum = cacert.GetSerialNumberString(); var tprint = cacert.Thumbprint; var sigalg = cacert.SignatureAlgorithm?.FriendlyName; var sigval = cacert.GetCertHashString(); if (v.IssuerCertificates == null) { v.IssuerCertificates = new OrderedNameMap <IssuerCertificateInfo>(); } if (Repeat || !v.IssuerCertificates.ContainsKey(sernum)) { var cacertDerFile = $"ca-{sernum}-crt.der"; var cacertPemFile = $"ca-{sernum}-crt.pem"; var issuerDerAsset = vp.ListAssets(cacertDerFile, VaultAssetType.IssuerDer).FirstOrDefault(); var issuerPemAsset = vp.ListAssets(cacertPemFile, VaultAssetType.IssuerPem).FirstOrDefault(); if (Repeat || issuerDerAsset == null) { if (issuerDerAsset == null) { issuerDerAsset = vp.CreateAsset(VaultAssetType.IssuerDer, cacertDerFile); } using (Stream fs = new FileStream(tmp, FileMode.Open), s = vp.SaveAsset(issuerDerAsset)) { fs.CopyTo(s); } } if (Repeat || issuerPemAsset == null) { if (issuerPemAsset == null) { issuerPemAsset = vp.CreateAsset(VaultAssetType.IssuerPem, cacertPemFile); } using (var cp = CertificateProvider.GetProvider()) { using (Stream source = vp.LoadAsset(issuerDerAsset), target = vp.SaveAsset(issuerPemAsset)) { var crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.PEM, target); } } } v.IssuerCertificates[sernum] = new IssuerCertificateInfo { SerialNumber = sernum, Thumbprint = tprint, SignatureAlgorithm = sigalg, Signature = sigval, CrtDerFile = cacertDerFile, CrtPemFile = cacertPemFile, }; } ci.IssuerSerialNumber = sernum; } finally { if (File.Exists(tmp)) { File.Delete(tmp); } } } } } } v.Alias = StringHelper.IfNullOrEmpty(Alias); v.Label = StringHelper.IfNullOrEmpty(Label); v.Memo = StringHelper.IfNullOrEmpty(Memo); vp.SaveVault(v); WriteObject(ci); } }
/// <summary> /// Request certificate from Let's Encrypt /// </summary> /// <param name="binding"></param> /// <returns></returns> public X509Certificate2 RequestCertificate(Target binding) { // What are we going to get? var identifiers = binding.GetHosts(false); var fileName = FileNamePart(binding); var friendlyName = FriendlyName(binding); using (var cp = CertificateProvider.GetProvider("BouncyCastle")) { // Generate the private key and CSR var rsaPkp = GetRsaKeyParameters(); var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csr = GetCsr(cp, identifiers, rsaKeys); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); // Save request parameters to disk var keyGenFile = Path.Combine(_certificatePath, $"{fileName}-gen-key.json"); using (var fs = new FileStream(keyGenFile, FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); var keyPemFile = Path.Combine(_certificatePath, $"{fileName}-key.pem"); using (var fs = new FileStream(keyPemFile, FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); var csrGenFile = Path.Combine(_certificatePath, $"{fileName}-gen-csr.json"); using (var fs = new FileStream(csrGenFile, FileMode.Create)) cp.SaveCsr(csr, fs); var csrPemFile = Path.Combine(_certificatePath, $"{fileName}-csr.pem"); using (var fs = new FileStream(csrPemFile, FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); // Request the certificate from Let's Encrypt _log.Information("Requesting certificate {friendlyName}", friendlyName); var certificateRequest = _client.RequestCertificate(derB64U); if (certificateRequest.StatusCode != HttpStatusCode.Created) { throw new Exception($"Request status {certificateRequest.StatusCode}"); } // Main certicate and issuer certificate Crt certificate; Crt issuerCertificate; // Certificate request was successful, save the certificate itself var crtDerFile = Path.Combine(_certificatePath, $"{fileName}-crt.der"); _log.Information("Saving certificate to {crtDerFile}", _certificatePath); using (var file = File.Create(crtDerFile)) certificateRequest.SaveCertificate(file); // Save certificate in PEM format too var crtPemFile = Path.Combine(_certificatePath, $"{fileName}-crt.pem"); using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { certificate = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(certificate, EncodingFormat.PEM, target); } // Get issuer certificate and save in DER and PEM formats issuerCertificate = GetIssuerCertificate(certificateRequest, cp); var issuerDerFile = Path.Combine(_certificatePath, $"ca-{fileName}-crt.der"); using (var target = new FileStream(issuerDerFile, FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.DER, target); var issuerPemFile = Path.Combine(_certificatePath, $"ca-{fileName}-crt.pem"); using (var target = new FileStream(issuerPemFile, FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.PEM, target); // Save chain in PEM format var chainPemFile = Path.Combine(_certificatePath, $"{fileName}-chain.pem"); using (FileStream intermediate = new FileStream(issuerPemFile, FileMode.Open), certificateStrean = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(chainPemFile, FileMode.Create)) { certificateStrean.CopyTo(chain); intermediate.CopyTo(chain); } // All raw data has been saved, now generate the PFX file var pfxFile = PfxFilePath(binding); var pfxPassword = Properties.Settings.Default.PFXPassword; using (FileStream target = new FileStream(pfxFile, FileMode.Create)) { try { cp.ExportArchive(rsaKeys, new[] { certificate, issuerCertificate }, ArchiveFormat.PKCS12, target, pfxPassword); } catch (Exception ex) { _log.Error("Error exporting archive {@ex}", ex); } } X509KeyStorageFlags flags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet; if (Properties.Settings.Default.PrivateKeyExportable) { _log.Debug("Set private key exportable"); flags |= X509KeyStorageFlags.Exportable; } // See http://paulstovell.com/blog/x509certificate2 var res = new X509Certificate2(pfxFile, pfxPassword, flags); var privateKey = (RSACryptoServiceProvider)res.PrivateKey; res.PrivateKey = Convert(privateKey); res.FriendlyName = friendlyName; File.WriteAllBytes(pfxFile, res.Export(X509ContentType.Pfx, pfxPassword)); return(res); } }
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}"); }
/// <summary> /// Request certificate from Let's Encrypt /// </summary> /// <param name="binding"></param> /// <returns></returns> public CertificateInfo RequestCertificate(Target binding) { // What are we going to get? var identifiers = binding.GetHosts(false); var friendlyName = FriendlyName(binding); var pfxPassword = Properties.Settings.Default.PFXPassword; var pfxFileInfo = new FileInfo(PfxFilePath(binding)); // Try using cached certificate first to avoid rate limiting during // (initial?) deployment troubleshooting. Real certificate requests // will only be done once per day maximum. if (pfxFileInfo.Exists && pfxFileInfo.LastWriteTime > DateTime.Now.AddDays(-1)) { _log.Warning("Using cached certificate for {friendlyName}", friendlyName); return(new CertificateInfo() { Certificate = new X509Certificate2(pfxFileInfo.FullName, pfxPassword), PfxFile = pfxFileInfo }); } using (var cp = CertificateProvider.GetProvider("BouncyCastle")) { // Generate the private key and CSR var rsaPkp = GetRsaKeyParameters(); var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csr = GetCsr(cp, identifiers, rsaKeys); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); // Save request parameters to disk using (var fs = new FileStream(GetPath(binding, "-gen-key.json"), FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(GetPath(binding, "-key.pem"), FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(GetPath(binding, "-gen-csr.json"), FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(GetPath(binding, "-csr.pem"), FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); // Request the certificate from Let's Encrypt _log.Information("Requesting certificate {friendlyName}", friendlyName); var certificateRequest = _client.Acme.RequestCertificate(derB64U); if (certificateRequest.StatusCode != HttpStatusCode.Created) { throw new Exception($"Request status {certificateRequest.StatusCode}"); } // Main certicate and issuer certificate Crt certificate; Crt issuerCertificate; // Certificate request was successful, save the certificate itself var crtDerFile = GetPath(binding, $"-crt.der"); _log.Information("Saving certificate to {crtDerFile}", _certificatePath); using (var file = File.Create(crtDerFile)) certificateRequest.SaveCertificate(file); // Save certificate in PEM format too var crtPemFile = GetPath(binding, $"-crt.pem"); using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { certificate = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(certificate, EncodingFormat.PEM, target); } // Get issuer certificate and save in DER and PEM formats issuerCertificate = GetIssuerCertificate(certificateRequest, cp); using (var target = new FileStream(GetPath(binding, "-crt.der", "ca-"), FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.DER, target); var issuerPemFile = GetPath(binding, "-crt.pem", "ca-"); using (var target = new FileStream(issuerPemFile, FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.PEM, target); // Save chain in PEM format using (FileStream intermediate = new FileStream(issuerPemFile, FileMode.Open), certificateStrean = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(GetPath(binding, "-chain.pem"), FileMode.Create)) { certificateStrean.CopyTo(chain); intermediate.CopyTo(chain); } // All raw data has been saved, now generate the PFX file using (FileStream target = new FileStream(pfxFileInfo.FullName, FileMode.Create)) { try { cp.ExportArchive(rsaKeys, new[] { certificate, issuerCertificate }, ArchiveFormat.PKCS12, target, pfxPassword); } catch (Exception ex) { _log.Error("Error exporting archive {@ex}", ex); } } X509KeyStorageFlags flags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet; if (Properties.Settings.Default.PrivateKeyExportable) { _log.Debug("Set private key exportable"); flags |= X509KeyStorageFlags.Exportable; } // See http://paulstovell.com/blog/x509certificate2 try { var res = new X509Certificate2(pfxFileInfo.FullName, pfxPassword, flags); var privateKey = (RSACryptoServiceProvider)res.PrivateKey; res.PrivateKey = Convert(privateKey); res.FriendlyName = friendlyName; File.WriteAllBytes(pfxFileInfo.FullName, res.Export(X509ContentType.Pfx, pfxPassword)); return(new CertificateInfo() { Certificate = res, PfxFile = pfxFileInfo }); } catch { // If we couldn't convert the private key that // means we're left with a pfx generated with the // 'wrong' Crypto provider therefor delete it to // make sure it's retried on the next run. pfxFileInfo.Delete(); return(null); } } }
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}"); }
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 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}"); }
/// <summary> /// Request certificate from the ACME server /// </summary> /// <param name="binding"></param> /// <returns></returns> public CertificateInfo RequestCertificate(Target binding) { // What are we going to get? var identifiers = binding.GetHosts(false); var friendlyName = FriendlyName(binding); var pfxPassword = Properties.Settings.Default.PFXPassword; var pfxFileInfo = new FileInfo(PfxFilePath(binding)); // Try using cached certificate first to avoid rate limiting during // (initial?) deployment troubleshooting. Real certificate requests // will only be done once per day maximum. if (pfxFileInfo.Exists && pfxFileInfo.LastWriteTime > DateTime.Now.AddDays(-1)) { try { var cached = new CertificateInfo() { Certificate = ReadForUse(pfxFileInfo, pfxPassword), PfxFile = pfxFileInfo }; var idn = new IdnMapping(); if (cached.SubjectName == identifiers.First() && cached.HostNames.Count == identifiers.Count && cached.HostNames.All(h => identifiers.Contains(idn.GetAscii(h)))) { if (_options.ForceRenewal) { _log.Warning("Cached certificate available but not used with --forcerenewal. Use 'Renew specific' or 'Renew all' in the main menu to run unscheduled renewals without hitting rate limits."); } else { _log.Warning("Using cached certificate for {friendlyName}. To force issue of a new certificate within 24 hours, delete the .pfx file from the CertificatePath or run with the --forcerenewal switch. Be ware that you might run into rate limits doing so.", friendlyName); return(cached); } } } catch { // File corrupt or invalid password? _log.Warning("Unable to read from certificate cache"); } } using (var cp = CertificateProvider.GetProvider("BouncyCastle")) { // Generate the private key and CSR var rsaPkp = GetRsaKeyParameters(); var rsaKeys = cp.GeneratePrivateKey(rsaPkp); var csr = GetCsr(cp, identifiers, rsaKeys, binding.CommonName); byte[] derRaw; using (var bs = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, bs); derRaw = bs.ToArray(); } var derB64U = JwsHelper.Base64UrlEncode(derRaw); // Save request parameters to disk using (var fs = new FileStream(GetPath(binding, "-gen-key.json"), FileMode.Create)) cp.SavePrivateKey(rsaKeys, fs); using (var fs = new FileStream(GetPath(binding, "-key.pem"), FileMode.Create)) cp.ExportPrivateKey(rsaKeys, EncodingFormat.PEM, fs); using (var fs = new FileStream(GetPath(binding, "-gen-csr.json"), FileMode.Create)) cp.SaveCsr(csr, fs); using (var fs = new FileStream(GetPath(binding, "-csr.pem"), FileMode.Create)) cp.ExportCsr(csr, EncodingFormat.PEM, fs); // Request the certificate from the ACME server _log.Information("Requesting certificate {friendlyName}", friendlyName); var certificateRequest = _client.Acme.RequestCertificate(derB64U); if (certificateRequest.StatusCode != HttpStatusCode.Created) { throw new Exception($"Request status {certificateRequest.StatusCode}"); } // Main certicate and issuer certificate Crt certificate; Crt issuerCertificate; // Certificate request was successful, save the certificate itself var crtDerFile = GetPath(binding, $"-crt.der"); _log.Information("Saving certificate to {crtDerFile}", _certificatePath); using (var file = File.Create(crtDerFile)) certificateRequest.SaveCertificate(file); // Save certificate in PEM format too var crtPemFile = GetPath(binding, $"-crt.pem"); using (FileStream source = new FileStream(crtDerFile, FileMode.Open), target = new FileStream(crtPemFile, FileMode.Create)) { certificate = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(certificate, EncodingFormat.PEM, target); } // Get issuer certificate and save in DER and PEM formats issuerCertificate = GetIssuerCertificate(certificateRequest, cp); using (var target = new FileStream(GetPath(binding, "-crt.der", "ca-"), FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.DER, target); var issuerPemFile = GetPath(binding, "-crt.pem", "ca-"); using (var target = new FileStream(issuerPemFile, FileMode.Create)) cp.ExportCertificate(issuerCertificate, EncodingFormat.PEM, target); // Save chain in PEM format using (FileStream intermediate = new FileStream(issuerPemFile, FileMode.Open), certificateStrean = new FileStream(crtPemFile, FileMode.Open), chain = new FileStream(GetPath(binding, "-chain.pem"), FileMode.Create)) { certificateStrean.CopyTo(chain); intermediate.CopyTo(chain); } // All raw data has been saved, now generate the PFX file using (var target = new FileStream(pfxFileInfo.FullName, FileMode.Create)) { try { cp.ExportArchive(rsaKeys, new[] { certificate, issuerCertificate }, ArchiveFormat.PKCS12, target, pfxPassword); } catch (Exception ex) { _log.Error("Error exporting archive {@ex}", ex); } } // Flags used for the internally cached certificate var internalFlags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable; // See http://paulstovell.com/blog/x509certificate2 try { // Convert Private Key to different CryptoProvider _log.Verbose("Converting private key..."); var res = new X509Certificate2(pfxFileInfo.FullName, pfxPassword, internalFlags); var privateKey = (RSACryptoServiceProvider)res.PrivateKey; res.PrivateKey = Convert(privateKey); res.FriendlyName = friendlyName; File.WriteAllBytes(pfxFileInfo.FullName, res.Export(X509ContentType.Pfx, pfxPassword)); pfxFileInfo.Refresh(); } catch (Exception ex) { // If we couldn't convert the private key that // means we're left with a pfx generated with the // 'wrong' Crypto provider therefor delete it to // make sure it's retried on the next run. _log.Warning("Error converting private key to Microsoft RSA SChannel Cryptographic Provider, which means it might not be usable for Exchange."); _log.Verbose("{ex}", ex); } // Recreate X509Certificate2 with correct flags for Store/Install return(new CertificateInfo() { Certificate = ReadForUse(pfxFileInfo, pfxPassword), PfxFile = pfxFileInfo }); } }
int Execute(RequestNewCertificateOptions options) { int errorCode; if (OptionsInBadFormat(options, out errorCode)) { return(errorCode); } var requestContext = InitializeRequestContext(options); if (requestContext == null) { return(210); } Console.Write("Initializing..."); CertificateProvider certProvider = null; var client = ClientHelper.CreateAcmeClient(requestContext.Signer, requestContext.Registration); try { Console.WriteLine("Done."); string toplevel; if (IsSubDomainName(options.CommonName, out toplevel)) { Console.Write("Authorizing top level domain name {0}...", toplevel); DnsAuthorizer.Authorize(client, requestContext.DnsProvider, toplevel); Console.WriteLine("Done."); } Console.Write("Authorizing domain name {0}...", options.CommonName); DnsAuthorizer.Authorize(client, requestContext.DnsProvider, options.CommonName); Console.WriteLine("Done."); Console.Write("Requesting a new certificate for common name {0}...", options.CommonName); certProvider = CertificateProvider.GetProvider(); var cert = CertificateClient.RequestCertificate(client, certProvider, options.CommonName); Console.WriteLine("Done."); Console.WriteLine("Exporting certificate to file..."); var outTypeString = options.OutputType.ToString().ToLowerInvariant(); if (string.IsNullOrWhiteSpace(options.OutputFile)) { options.OutputFile = Path.Combine(AppliationPath, string.Concat(options.CommonName, '-', DateTime.Now.ToString("yyyyMMddHHmm"), '.', outTypeString)); } string dir; options.OutputFile = PrepareOutputFilePath(options.OutputFile, out dir); CertificateExporter.Export(certProvider, cert, options.OutputType, options.OutputFile); Console.WriteLine("Certificate has been exported as {0} format at {1}.", outTypeString, options.OutputFile); } finally { client.Dispose(); certProvider?.Dispose(); requestContext.Signer.Dispose(); requestContext.DnsProvider.Dispose(); } return(0); }
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.Certificates == null || v.Certificates.Count < 1) { throw new InvalidOperationException("No certificates found"); } var ci = v.Certificates.GetByRef(CertificateRef); if (ci == null) { throw new Exception("Unable to find a Certificate for the given reference"); } using (var cp = CertificateProvider.GetProvider()) { if (!string.IsNullOrEmpty(ci.GenerateDetailsFile)) { // Generate a private key and CSR: // Key: RSA 2048-bit // MD: SHA 256 // CSR: Details pulled from CSR Details JSON file CsrDetails csrDetails; var csrDetailsAsset = vlt.GetAsset(VaultAssetType.CsrDetails, ci.GenerateDetailsFile); using (var s = vlt.LoadAsset(csrDetailsAsset)) { csrDetails = JsonHelper.Load <CsrDetails>(s); } var keyGenFile = $"{ci.Id}-gen-key.json"; var keyPemFile = $"{ci.Id}-key.pem"; var csrGenFile = $"{ci.Id}-gen-csr.json"; var csrPemFile = $"{ci.Id}-csr.pem"; var keyGenAsset = vlt.CreateAsset(VaultAssetType.KeyGen, keyGenFile, getOrCreate: Force); var keyPemAsset = vlt.CreateAsset(VaultAssetType.KeyPem, keyPemFile, isSensitive: true, getOrCreate: Force); var csrGenAsset = vlt.CreateAsset(VaultAssetType.CsrGen, csrGenFile, getOrCreate: Force); var csrPemAsset = vlt.CreateAsset(VaultAssetType.CsrPem, csrPemFile, getOrCreate: Force); var genKeyParams = new RsaPrivateKeyParams(); var genKey = cp.GeneratePrivateKey(genKeyParams); using (var s = vlt.SaveAsset(keyGenAsset)) { cp.SavePrivateKey(genKey, s); } using (var s = vlt.SaveAsset(keyPemAsset)) { cp.ExportPrivateKey(genKey, EncodingFormat.PEM, s); } // TODO: need to surface details of the CSR params up higher var csrParams = new CsrParams { Details = csrDetails }; var genCsr = cp.GenerateCsr(csrParams, genKey, Crt.MessageDigest.SHA256); using (var s = vlt.SaveAsset(csrGenAsset)) { cp.SaveCsr(genCsr, s); } using (var s = vlt.SaveAsset(csrPemAsset)) { cp.ExportCsr(genCsr, EncodingFormat.PEM, s); } ci.KeyPemFile = keyPemFile; ci.CsrPemFile = csrPemFile; } byte[] derRaw; var asset = vlt.GetAsset(VaultAssetType.CsrPem, ci.CsrPemFile); // Convert the stored CSR in PEM format to DER using (var source = vlt.LoadAsset(asset)) { var csr = cp.ImportCsr(EncodingFormat.PEM, source); using (var target = new MemoryStream()) { cp.ExportCsr(csr, EncodingFormat.DER, target); derRaw = target.ToArray(); } } var derB64u = JwsHelper.Base64UrlEncode(derRaw); try { using (var c = ClientHelper.GetClient(v, ri)) { c.Init(); c.GetDirectory(true); ci.CertificateRequest = c.RequestCertificate(derB64u); } } catch (AcmeClient.AcmeWebException ex) { ThrowTerminatingError(PoshHelper.CreateErrorRecord(ex, ci)); return; } if (!string.IsNullOrEmpty(ci.CertificateRequest.CertificateContent)) { var crtDerFile = $"{ci.Id}-crt.der"; var crtPemFile = $"{ci.Id}-crt.pem"; var crtDerBytes = ci.CertificateRequest.GetCertificateContent(); var crtDerAsset = vlt.CreateAsset(VaultAssetType.CrtDer, crtDerFile); var crtPemAsset = vlt.CreateAsset(VaultAssetType.CrtPem, crtPemFile); using (Stream source = new MemoryStream(crtDerBytes), derTarget = vlt.SaveAsset(crtDerAsset), pemTarget = vlt.SaveAsset(crtPemAsset)) { var crt = cp.ImportCertificate(EncodingFormat.DER, source); cp.ExportCertificate(crt, EncodingFormat.DER, derTarget); ci.CrtDerFile = crtDerFile; cp.ExportCertificate(crt, EncodingFormat.PEM, pemTarget); ci.CrtPemFile = crtPemFile; } // Extract a few pieces of info from the issued // cert that we like to have quick access to var x509 = new X509Certificate2(ci.CertificateRequest.GetCertificateContent()); ci.SerialNumber = x509.SerialNumber; ci.Thumbprint = x509.Thumbprint; ci.SignatureAlgorithm = x509.SignatureAlgorithm?.FriendlyName; ci.Signature = x509.GetCertHashString(); } } vlt.SaveVault(v); WriteObject(ci); } }
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 (string.IsNullOrEmpty(CertificateRef)) { int seq = 0; WriteObject(v.Certificates.Values.Select(x => new { Seq = seq++, x.Id, x.Alias, x.Label, x.IdentifierDns, x.Thumbprint, x.SerialNumber, x.IssuerSerialNumber, x.CertificateRequest, x.CertificateRequest?.StatusCode, }), true); } else { if (v.Certificates == null || v.Certificates.Count < 1) { throw new InvalidOperationException("No certificates found"); } var ci = v.Certificates.GetByRef(CertificateRef); if (ci == null) { throw new ItemNotFoundException("Unable to find a Certificate for the given reference"); } var mode = Overwrite ? FileMode.Create : FileMode.CreateNew; if (!string.IsNullOrEmpty(ExportKeyPEM)) { if (string.IsNullOrEmpty(ci.KeyPemFile)) { throw new InvalidOperationException("Cannot export private key; it hasn't been imported or generated"); } CopyTo(vlt, VaultAssetType.KeyPem, ci.KeyPemFile, ExportKeyPEM, mode); } if (!string.IsNullOrEmpty(ExportCsrPEM)) { if (string.IsNullOrEmpty(ci.CsrPemFile)) { throw new InvalidOperationException("Cannot export CSR; it hasn't been imported or generated"); } CopyTo(vlt, VaultAssetType.CsrPem, ci.CsrPemFile, ExportCsrPEM, mode); } if (!string.IsNullOrEmpty(ExportCertificatePEM)) { if (ci.CertificateRequest == null || string.IsNullOrEmpty(ci.CrtPemFile)) { throw new InvalidOperationException("Cannot export CRT; CSR hasn't been submitted or CRT hasn't been retrieved"); } CopyTo(vlt, VaultAssetType.CrtPem, ci.CrtPemFile, ExportCertificatePEM, mode); } if (!string.IsNullOrEmpty(ExportCertificateDER)) { if (ci.CertificateRequest == null || string.IsNullOrEmpty(ci.CrtDerFile)) { throw new InvalidOperationException("Cannot export CRT; CSR hasn't been submitted or CRT hasn't been retrieved"); } CopyTo(vlt, VaultAssetType.CrtDer, ci.CrtDerFile, ExportCertificateDER, mode); } if (!string.IsNullOrEmpty(ExportIssuerPEM)) { if (ci.CertificateRequest == null || string.IsNullOrEmpty(ci.CrtPemFile)) { throw new InvalidOperationException("Cannot export CRT; CSR hasn't been submitted or CRT hasn't been retrieved"); } if (string.IsNullOrEmpty(ci.IssuerSerialNumber) || !v.IssuerCertificates.ContainsKey(ci.IssuerSerialNumber)) { throw new InvalidOperationException("Issuer certificate hasn't been resolved"); } CopyTo(vlt, VaultAssetType.IssuerPem, v.IssuerCertificates[ci.IssuerSerialNumber].CrtPemFile, ExportIssuerPEM, mode); } if (!string.IsNullOrEmpty(ExportIssuerDER)) { if (ci.CertificateRequest == null || string.IsNullOrEmpty(ci.CrtDerFile)) { throw new InvalidOperationException("Cannot export CRT; CSR hasn't been submitted or CRT hasn't been retrieved"); } if (string.IsNullOrEmpty(ci.IssuerSerialNumber) || !v.IssuerCertificates.ContainsKey(ci.IssuerSerialNumber)) { throw new InvalidOperationException("Issuer certificate hasn't been resolved"); } CopyTo(vlt, VaultAssetType.IssuerDer, v.IssuerCertificates[ci.IssuerSerialNumber].CrtDerFile, ExportIssuerDER, mode); } if (!string.IsNullOrEmpty(ExportPkcs12)) { if (string.IsNullOrEmpty(ci.KeyPemFile)) { throw new InvalidOperationException("Cannot export PKCS12; private hasn't been imported or generated"); } if (string.IsNullOrEmpty(ci.CrtPemFile)) { throw new InvalidOperationException("Cannot export PKCS12; CSR hasn't been submitted or CRT hasn't been retrieved"); } if (string.IsNullOrEmpty(ci.IssuerSerialNumber) || !v.IssuerCertificates.ContainsKey(ci.IssuerSerialNumber)) { throw new InvalidOperationException("Cannot export PKCS12; Issuer certificate hasn't been resolved"); } var keyPemAsset = vlt.GetAsset(VaultAssetType.KeyPem, ci.KeyPemFile); var crtPemAsset = vlt.GetAsset(VaultAssetType.CrtPem, ci.CrtPemFile); var isuPemAsset = vlt.GetAsset(VaultAssetType.IssuerPem, v.IssuerCertificates[ci.IssuerSerialNumber].CrtPemFile); using (var cp = CertificateProvider.GetProvider()) { using (Stream keyStream = vlt.LoadAsset(keyPemAsset), crtStream = vlt.LoadAsset(crtPemAsset), isuStream = vlt.LoadAsset(isuPemAsset), fs = new FileStream(ExportPkcs12, mode)) { var pk = cp.ImportPrivateKey <RsaPrivateKey>(EncodingFormat.PEM, keyStream); var crt = cp.ImportCertificate(EncodingFormat.PEM, crtStream); var isu = cp.ImportCertificate(EncodingFormat.PEM, isuStream); var certs = new[] { crt, isu }; var password = string.IsNullOrWhiteSpace(CertificatePassword) ? string.Empty : CertificatePassword; cp.ExportArchive(pk, certs, ArchiveFormat.PKCS12, fs, password); } } } WriteObject(ci); } } }
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); }
/// <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); }