public void TestPfxFromPem() { BindingRedirectHandler.DoBindingRedirects(AppDomain.CurrentDomain); string pfxFilePath = Path.GetTempPath() + "ssl-pfx-test-" + Guid.NewGuid() + ".pfx"; string certificatePassword = null; string crtFilePath = UtilsSystem.GetResourceFileAsPath("certificate_files_example\\a0e8efb7cca4452ed304b1d9614ec89d-crt.pem"); string keyFilePath = UtilsSystem.GetResourceFileAsPath("certificate_files_example\\a0e8efb7cca4452ed304b1d9614ec89d-key.pem"); UtilsCertificate.CreatePfXfromPem(crtFilePath, keyFilePath, pfxFilePath, certificatePassword); // Make sure that the certificate file is valid and works X509Certificate2Collection collection = new X509Certificate2Collection(); collection.Import(pfxFilePath, certificatePassword, X509KeyStorageFlags.EphemeralKeySet); var originalCert = collection[0]; Assert.Equal("033679B39C0CDA50C745ABD173FB0DD381A1", originalCert.SerialNumber); File.Delete(pfxFilePath); }
/// <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); }