public async Task <StatusMessage> RevokeCertificate(ILog log, ManagedCertificate managedCertificate) { // get current PFX, extract DER bytes try { var pkcs = new Org.BouncyCastle.Pkcs.Pkcs12Store(File.Open(managedCertificate.CertificatePath, FileMode.Open), "".ToCharArray()); var certAliases = pkcs.Aliases.GetEnumerator(); certAliases.MoveNext(); var certEntry = pkcs.GetCertificate(certAliases.Current.ToString()); var certificate = certEntry.Certificate; // revoke certificat var der = certificate.GetEncoded(); await _acme.RevokeCertificate(der, RevocationReason.Unspecified, null); } catch (Exception exp) { return(new StatusMessage { IsOK = false, Message = $"Failed to revoke certificate: {exp.Message}" }); } return(new StatusMessage { IsOK = true, Message = "Certificate revoked" }); }
public async Task <StatusMessage> RevokeCertificate(ILog log, ManagedCertificate managedCertificate) { try { var pkcs = new Org.BouncyCastle.Pkcs.Pkcs12Store(File.Open(managedCertificate.CertificatePath, FileMode.Open), "".ToCharArray()); var certAliases = pkcs.Aliases.GetEnumerator(); certAliases.MoveNext(); var certEntry = pkcs.GetCertificate(certAliases.Current.ToString()); var certificate = certEntry.Certificate; // revoke certificate var der = certificate.GetEncoded(); await _client.RevokeCertificateAsync(der, RevokeReason.Unspecified); return(new StatusMessage { IsOK = true, Message = $"Certificate revoke completed." }); } catch (Exception exp) { return(new StatusMessage { IsOK = false, Message = $"Failed to revoke certificate: {exp.Message}" }); } }
public string AddSignature(string PathSource, string PathTarget, string CertPath, string CertPass, int lx = 100, int ly = 100, int ux = 250, int uy = 150, int page = 1, bool Visible = true) { try { Org.BouncyCastle.Crypto.AsymmetricKeyParameter Akp = null; Org.BouncyCastle.X509.X509Certificate[] Chain = null; string alias = null; Org.BouncyCastle.Pkcs.Pkcs12Store pk12; pk12 = new Org.BouncyCastle.Pkcs.Pkcs12Store(new System.IO.FileStream(CertPath, System.IO.FileMode.Open, System.IO.FileAccess.Read), CertPass.ToCharArray()); IEnumerable aliases = pk12.Aliases; foreach (string aliasTemp in aliases) { alias = aliasTemp; if (pk12.IsKeyEntry(alias)) { break; } } Akp = pk12.GetKey(alias).Key; Org.BouncyCastle.Pkcs.X509CertificateEntry[] ce = pk12.GetCertificateChain(alias); Chain = new Org.BouncyCastle.X509.X509Certificate[ce.Length]; for (int k = 0; k < ce.Length; ++k) { Chain[k] = ce[k].Certificate; } iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(PathSource); iTextSharp.text.pdf.PdfStamper st = iTextSharp.text.pdf.PdfStamper.CreateSignature(reader, new System.IO.FileStream(PathTarget, System.IO.FileMode.Create, System.IO.FileAccess.Write), '\0', null, true); iTextSharp.text.pdf.PdfSignatureAppearance sap = st.SignatureAppearance; if (Visible == true) { page = (page <1 || page> reader.NumberOfPages) ? 1 : page; sap.SetVisibleSignature(new iTextSharp.text.Rectangle(lx, ly, ux, uy), page, null); } sap.CertificationLevel = iTextSharp.text.pdf.PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED; // digital signature - http://itextpdf.com/examples/iia.php?id=222 IExternalSignature es = new PrivateKeySignature(Akp, "SHA-256"); // "BC" MakeSignature.SignDetached(sap, es, new X509Certificate[] { pk12.GetCertificate(alias).Certificate }, null, null, null, 0, CryptoStandard.CMS); st.Close(); return(""); } catch (Exception e) { return(e.Message); } }
private (RsaPrivateCrtKeyParameters rsaPrivateKey, X509Certificate certificate) Extract(Stream stream, string password) { Org.BouncyCastle.Pkcs.Pkcs12Store p12Store = new Org.BouncyCastle.Pkcs.Pkcs12Store(stream, password.ToCharArray()); string keyEntryAlias = p12Store.Aliases.Cast <string>().FirstOrDefault(t => p12Store.IsKeyEntry(t)); Org.BouncyCastle.Pkcs.X509CertificateEntry x509CertEntry = p12Store.GetCertificate(keyEntryAlias); Org.BouncyCastle.Pkcs.AsymmetricKeyEntry keyEntry = p12Store.GetKey(keyEntryAlias); return(keyEntry.Key as RsaPrivateCrtKeyParameters, x509CertEntry.Certificate); }
public X509Crl GenerateCRL() { var coreCApkcs = new Org.BouncyCastle.Pkcs.Pkcs12Store( new FileStream(CAConfig.CoreCACertPath, FileMode.Open, FileAccess.Read), "".ToCharArray() ); string alias = System.Environment.MachineName; Org.BouncyCastle.X509.X509Certificate coreCaCert = coreCApkcs.GetCertificate(alias).Certificate; X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); DateTime now = DateTime.UtcNow; crlGen.SetIssuerDN(coreCaCert.SubjectDN); crlGen.SetThisUpdate(now); crlGen.SetNextUpdate(now.AddMinutes(Constants.CRLNextUpdatedIntervalMinutes)); var revokedPubCerts = _dbContext.PublicCertificates.Where(p => p.IsRevoked); foreach (PublicCertificate pubCert in revokedPubCerts) { crlGen.AddCrlEntry( new Org.BouncyCastle.Math.BigInteger(pubCert.GetSerialNumber().SerialNrBytes), now, Org.BouncyCastle.Asn1.X509.CrlReason.KeyCompromise ); } crlGen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier, false, new Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure( coreCaCert.GetPublicKey() ) ); X509Crl crl = crlGen.Generate( new Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory( "SHA512WITHRSA", coreCApkcs.GetKey(alias).Key ) ); _logger.LogInformation( string.Format( "Generated CRL at {0} valid for {1} minutes", now, Constants.CRLNextUpdatedIntervalMinutes ) ); return(crl); }
public static void Test() { string pfxLocation = @"D:\lol\certificate.pfx"; pfxLocation = @"D:\username\Desktop\DesktopArchiv\20180329_Desktop\CORMailService\CORMailService\CORMailService\CORMailService_TemporaryKey.pfx"; Org.BouncyCastle.Pkcs.Pkcs12Store store = null; using (System.IO.Stream pfxStream = System.IO.File.OpenRead(pfxLocation)) { store = new Org.BouncyCastle.Pkcs.Pkcs12Store(pfxStream, "".ToCharArray()); } System.Console.WriteLine(store); foreach (string alias in store.Aliases) { System.Console.WriteLine(alias); // https://7thzero.com/blog/bouncy-castle-convert-a-bouncycastle-asymmetrickeyentry-to-a-.ne if (store.IsKeyEntry((string)alias)) { Org.BouncyCastle.Pkcs.AsymmetricKeyEntry keyEntry = store.GetKey(alias); System.Console.WriteLine(keyEntry); AsymmetricKeyParameter privateKey = keyEntry.Key; System.Console.WriteLine(privateKey.IsPrivate); } // End if (store.IsKeyEntry((string)alias)) Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = store.GetCertificate(alias); Org.BouncyCastle.X509.X509Certificate cert = certEntry.Certificate; System.Console.WriteLine(cert); AsymmetricKeyParameter publicKey = cert.GetPublicKey(); System.Console.WriteLine(publicKey); // Org.BouncyCastle.Pkcs.X509CertificateEntry[] chain = store.GetCertificateChain(alias); // System.Security.Cryptography.X509Certificates.X509Certificate2 cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(cert.GetEncoded()); // Org.BouncyCastle.Security.DotNetUtilities.ToX509Certificate(cert); System.Security.Cryptography.X509Certificates.X509Certificate2 cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(pfxLocation); // cert2.PrivateKey = null; if (cert2.HasPrivateKey) { System.Console.WriteLine(cert2.PrivateKey); } } }
public static byte[] CreatePfxBytes( Org.BouncyCastle.X509.X509Certificate certificate , Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey , string password = "") { byte[] pfxBytes = null; // create certificate entry Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = new Org.BouncyCastle.Pkcs.X509CertificateEntry(certificate); Org.BouncyCastle.Asn1.X509.X509Name name = new Org.BouncyCastle.Asn1.X509.X509Name(certificate.SubjectDN.ToString()); string friendlyName = (string)name.GetValueList(Org.BouncyCastle.Asn1.X509.X509Name.O)[0]; if (System.StringComparer.InvariantCultureIgnoreCase.Equals("Skynet Earth Inc.", friendlyName)) { friendlyName = "Skynet Certification Authority"; } Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder builder = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder(); builder.SetUseDerEncoding(true); Org.BouncyCastle.Pkcs.Pkcs12Store store = builder.Build(); store.SetCertificateEntry(friendlyName, certEntry); // create store entry store.SetKeyEntry( friendlyName , new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(privateKey) , new Org.BouncyCastle.Pkcs.X509CertificateEntry[] { certEntry } ); using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { // Cert is contained in store // null: no password, "": an empty passwords // note: Linux needs empty password on null... store.Save(stream, password == null ? "".ToCharArray() : password.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom()); // stream.Position = 0; pfxBytes = Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(stream.ToArray()); } // End Using stream return(pfxBytes); } // End Function CreatePfxBytes
// DumpPfx(ee25519Cert, subject, caKey25519); public static void DumpPfx( Org.BouncyCastle.X509.X509Certificate bouncyCert , Org.BouncyCastle.Asn1.X509.X509Name subject , Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair pair) { Org.BouncyCastle.Pkcs.Pkcs12Store store = new Org.BouncyCastle.Pkcs.Pkcs12Store(); Org.BouncyCastle.Pkcs.X509CertificateEntry certificateEntry = new Org.BouncyCastle.Pkcs.X509CertificateEntry(bouncyCert); store.SetCertificateEntry(subject.ToString(), certificateEntry); store.SetKeyEntry(subject.ToString(), new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(pair.Private) , new[] { certificateEntry } ); Org.BouncyCastle.Security.SecureRandom random = new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ); using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { string tempPassword = "******"; store.Save(stream, tempPassword.ToCharArray(), random); using (System.Security.Cryptography.X509Certificates.X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2( stream.ToArray() , tempPassword , System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable) ) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); builder.AppendLine("-----BEGIN CERTIFICATE-----"); builder.AppendLine(System.Convert.ToBase64String( cert.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Cert) , System.Base64FormattingOptions.InsertLineBreaks) ); builder.AppendLine("-----END CERTIFICATE-----"); // PFX //builder.ToString().Dump("Self-signed Certificate"); } // End Using cert } // End Using stream } // End Sub DumpPfx
/// <summary> /// Imports certificates and private keys from the specified stream. /// </summary> /// <remarks> /// <para>Imports certificates and private keys from the specified pkcs12 stream.</para> /// </remarks> /// <param name="stream">The stream to import.</param> /// <param name="password">The password to unlock the stream.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="stream"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="password"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.IO.IOException"> /// An error occurred reading the stream. /// </exception> public void Import(System.IO.Stream stream, string password) { if (stream == null) { throw new System.ArgumentNullException(nameof(stream)); } if (password == null) { throw new System.ArgumentNullException(nameof(password)); } Org.BouncyCastle.Pkcs.Pkcs12Store pkcs12 = new Org.BouncyCastle.Pkcs.Pkcs12Store(stream, password.ToCharArray()); foreach (string alias in pkcs12.Aliases) { if (pkcs12.IsKeyEntry(alias)) { Org.BouncyCastle.Pkcs.X509CertificateEntry[] chain = pkcs12.GetCertificateChain(alias); Org.BouncyCastle.Pkcs.AsymmetricKeyEntry entry = pkcs12.GetKey(alias); for (int i = 0; i < chain.Length; i++) { if (unique.Add(chain[i].Certificate)) { certs.Add(chain[i].Certificate); } } if (entry.Key.IsPrivate) { keys.Add(chain[0].Certificate, entry.Key); } } else if (pkcs12.IsCertificateEntry(alias)) { Org.BouncyCastle.Pkcs.X509CertificateEntry entry = pkcs12.GetCertificate(alias); if (unique.Add(entry.Certificate)) { certs.Add(entry.Certificate); } } } }
private void importbutton_Click(object sender, EventArgs e) { OpenFileDialog opener = new OpenFileDialog(); opener.InitialDirectory = Environment.CurrentDirectory; opener.Filter = "公钥证书|*.cer|私钥证书|*.pfx"; opener.RestoreDirectory = true; opener.FilterIndex = 1; if (opener.ShowDialog() == DialogResult.OK) { var fname = opener.FileName; var cerin = File.OpenText(fname); var txtreader = cerin.ReadToEnd(); if (Path.GetExtension(fname) == ".cer") { certificate.Text = txtreader; txtreader = txtreader.Replace("-----BEGIN CERTIFICATE-----", ""); txtreader = txtreader.Replace("-----END CERTIFICATE-----", ""); txtreader = txtreader.Replace("\r\n", ""); var certb = Convert.FromBase64String(txtreader); var cholder = new X509CertificateParser(); bouncy = cholder.ReadCertificate(certb); cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certb); nametxt.Text = bouncy.IssuerDN.ToString(); pubtxt.Text = Convert.ToBase64String(cert.GetPublicKey()); //Subtxt.Text = cert.Subject; } else if (Path.GetExtension(fname) == ".pfx") { var pfxin = File.ReadAllBytes(fname); var store = new Org.BouncyCastle.Pkcs.Pkcs12Store(); var stream = new MemoryStream(pfxin); store.Load(stream, pswtxt.Text.ToCharArray()); foreach (string al in store.Aliases) { Castlekey = store.GetKey(al).Key; Castle = store.GetCertificate(al).Certificate; } } } }
public async Task Save(CertificateInfo input) { var dest = PathForIdentifier(input.CommonName.Value); _log.Information("Copying certificate to the pfx folder {dest}", dest); try { var collection = new X509Certificate2Collection { input.Certificate }; collection.AddRange(input.Chain.ToArray()); var ms = new MemoryStream(collection.Export(X509ContentType.Pfx) !); var bcPfx = new bc.Pkcs.Pkcs12Store(ms, Array.Empty <char>()); var aliases = bcPfx.Aliases.OfType <string>().ToList(); var key = default(bc.Pkcs.AsymmetricKeyEntry); var chain = default(bc.Pkcs.X509CertificateEntry[]); foreach (var alias in aliases) { if (bcPfx.IsKeyEntry(alias)) { key = bcPfx.GetKey(alias); chain = bcPfx.GetCertificateChain(alias); break; } } using var fs = new FileInfo(dest).OpenWrite(); bcPfx = new bc.Pkcs.Pkcs12Store(); bcPfx.SetKeyEntry(input.CommonName.Value, key, chain); bcPfx.Save(fs, _password?.ToCharArray(), new bc.Security.SecureRandom()); } catch (Exception ex) { _log.Error(ex, "Error copying certificate to pfx path"); } input.StoreInfo.TryAdd( GetType(), new StoreInfo() { Name = PfxFileOptions.PluginName, Path = _path }); }
public static X509Certificate2 OpenCertificate(string pfxPath, string contrasenia) { var ms = new MemoryStream(File.ReadAllBytes(pfxPath)); var st = new Org.BouncyCastle.Pkcs.Pkcs12Store(ms, contrasenia.ToCharArray()); var alias = st.Aliases.Cast <string>().FirstOrDefault(p => st.IsCertificateEntry(p)); var keyEntryX = st.GetCertificate(alias); var x509 = new X509Certificate2(DotNetUtilities.ToX509Certificate(keyEntryX.Certificate)); alias = st.Aliases.Cast <string>().FirstOrDefault(p => st.IsKeyEntry(p)); var keyEntry = st.GetKey(alias); var intermediateProvider = (RSACryptoServiceProvider)DotNetUtilities.ToRSA((Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)keyEntry.Key); x509.PrivateKey = intermediateProvider; return(x509); }
} // End Sub WithMsPfx public static PfxData Read(string pfxFilePath, string password = "") { Org.BouncyCastle.Pkcs.Pkcs12Store store = null; using (System.IO.Stream pfxStream = System.IO.File.OpenRead(pfxFilePath)) { store = new Org.BouncyCastle.Pkcs.Pkcs12Store(pfxStream, password.ToCharArray()); } // System.Console.WriteLine(store); foreach (string alias in store.Aliases) { Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = store.GetCertificate(alias); Org.BouncyCastle.X509.X509Certificate cert = certEntry.Certificate; // Org.BouncyCastle.Crypto.AsymmetricKeyParameter publicKey = cert.GetPublicKey(); // System.Console.WriteLine(publicKey); // https://7thzero.com/blog/bouncy-castle-convert-a-bouncycastle-asymmetrickeyentry-to-a-.ne if (store.IsKeyEntry(alias)) { Org.BouncyCastle.Pkcs.AsymmetricKeyEntry keyEntry = store.GetKey(alias); Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey = keyEntry.Key; if (privateKey.IsPrivate) { return new PfxData() { Certificate = cert, PrivateKey = privateKey } } ; } // End if (store.IsKeyEntry((string)alias)) } // Next alias return(null); } // End Sub Read
public static Org.BouncyCastle.X509.X509Certificate LoadPfx(string path, string password) { Org.BouncyCastle.X509.X509Certificate cert = null; Org.BouncyCastle.Pkcs.X509CertificateEntry ce = null; using (System.IO.FileStream fs = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) { Org.BouncyCastle.Pkcs.Pkcs12Store store = new Org.BouncyCastle.Pkcs.Pkcs12Store(fs, password.ToCharArray()); foreach (string thisAlias in store.Aliases) { System.Console.WriteLine(thisAlias); ce = store.GetCertificate(thisAlias); cert = ce.Certificate; break; } // Next thisAlias } // End Using fs System.Console.WriteLine(cert); return(cert); } // End Function LoadPfx
/// <summary> /// Parse bytes to a usable certificate /// </summary> /// <param name="bytes"></param> /// <param name="friendlyName"></param> /// <param name="pk"></param> /// <returns></returns> private X509Certificate2Collection ParseCertificate(byte[] bytes, string friendlyName, AsymmetricKeyParameter?pk) { // Build pfx archive including any intermediates provided _log.Verbose("Parsing certificate from {bytes} bytes received", bytes.Length); var text = Encoding.UTF8.GetString(bytes); var pfx = new bc.Pkcs.Pkcs12Store(); var startIndex = 0; const string startString = "-----BEGIN CERTIFICATE-----"; const string endString = "-----END CERTIFICATE-----"; while (true) { startIndex = text.IndexOf(startString, startIndex); if (startIndex < 0) { break; } var endIndex = text.IndexOf(endString, startIndex); if (endIndex < 0) { break; } endIndex += endString.Length; var pem = text[startIndex..endIndex];
/// <summary> /// Request certificate from the ACME server /// </summary> /// <param name="binding"></param> /// <returns></returns> public CertificateInfo RequestCertificate(ICsrPlugin csrPlugin, RunLevel runLevel, Renewal renewal, Target target, OrderDetails order) { // What are we going to get? var pfxFileInfo = new FileInfo(PfxFilePath(renewal)); // Determine/check the common name var identifiers = target.GetHosts(false); var commonNameUni = target.CommonName; var commonNameAscii = string.Empty; if (!string.IsNullOrWhiteSpace(commonNameUni)) { var idn = new IdnMapping(); commonNameAscii = idn.GetAscii(commonNameUni); if (!identifiers.Contains(commonNameAscii, StringComparer.InvariantCultureIgnoreCase)) { _log.Warning($"Common name {commonNameUni} provided is invalid."); commonNameAscii = identifiers.First(); commonNameUni = idn.GetUnicode(commonNameAscii); } } // Determine the friendly name var friendlyName = renewal.FriendlyName; if (string.IsNullOrEmpty(friendlyName)) { friendlyName = target.FriendlyName; } if (string.IsNullOrEmpty(friendlyName)) { friendlyName = commonNameUni; } // Try using cached certificate first to avoid rate limiting during // (initial?) deployment troubleshooting. Real certificate requests // will only be done once per day maximum unless the --force parameter // is used. var cache = CachedInfo(renewal); if (cache != null && cache.CacheFile.LastWriteTime > DateTime.Now.AddDays(Settings.Default.CertificateCacheDays * -1) && cache.Match(target)) { if (runLevel.HasFlag(RunLevel.IgnoreCache)) { _log.Warning("Cached certificate available but not used with --{switch}. Use 'Renew specific' or " + "'Renew all' in the main menu to run unscheduled renewals without hitting rate limits.", nameof(MainArguments.Force).ToLower()); } 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 --{switch} switch. " + "Be ware that you might run into rate limits doing so.", friendlyName, nameof(MainArguments.Force).ToLower()); return(cache); } } var csr = csrPlugin.GenerateCsr(commonNameAscii, identifiers); var csrBytes = csr.CreateSigningRequest(); order = _client.SubmitCsr(order, csrBytes); File.WriteAllText(GetPath(renewal, "-csr.pem"), _pemService.GetPem("CERTIFICATE REQUEST", csrBytes)); _log.Information("Requesting certificate {friendlyName}", friendlyName); var rawCertificate = _client.GetCertificate(order); if (rawCertificate == null) { throw new Exception($"Unable to get certificate"); } var certificate = new X509Certificate2(rawCertificate); var certificateExport = certificate.Export(X509ContentType.Cert); var crtPem = _pemService.GetPem("CERTIFICATE", certificateExport); // Get issuer certificate var issuerCertificate = new X509Certificate2(rawCertificate.Skip(certificateExport.Length).ToArray()); var issuerCertificateExport = issuerCertificate.Export(X509ContentType.Cert); var issuerPem = _pemService.GetPem("CERTIFICATE", issuerCertificateExport); // Build pfx archive var pfx = new bc.Pkcs.Pkcs12Store(); var bcCertificate = _pemService.ParsePem <bc.X509.X509Certificate>(crtPem); var bcCertificateEntry = new bc.Pkcs.X509CertificateEntry(bcCertificate); var bcCertificateAlias = bcCertificate.SubjectDN.ToString(); var bcPrivateKeyEntry = new bc.Pkcs.AsymmetricKeyEntry(csrPlugin.GetPrivateKey()); pfx.SetCertificateEntry(bcCertificateAlias, bcCertificateEntry); pfx.SetKeyEntry(bcCertificateAlias, bcPrivateKeyEntry, new[] { bcCertificateEntry }); var bcIssuer = _pemService.ParsePem <bc.X509.X509Certificate>(issuerPem); var bcIssuerEntry = new bc.Pkcs.X509CertificateEntry(bcIssuer); var bcIssuerAlias = bcIssuer.SubjectDN.ToString(); pfx.SetCertificateEntry(bcIssuerAlias, bcIssuerEntry); var pfxStream = new MemoryStream(); pfx.Save(pfxStream, null, new bc.Security.SecureRandom()); pfxStream.Position = 0; using (var pfxStreamReader = new BinaryReader(pfxStream)) { var tempPfx = new X509Certificate2( pfxStreamReader.ReadBytes((int)pfxStream.Length), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); if (csrPlugin.CanConvert()) { try { var converted = csrPlugin.Convert(tempPfx.PrivateKey); if (converted != null) { tempPfx.PrivateKey = converted; } } catch { _log.Warning("Private key conversion error."); } } tempPfx.FriendlyName = $"{friendlyName} {DateTime.Now.ToUserString()}"; File.WriteAllBytes(pfxFileInfo.FullName, tempPfx.Export(X509ContentType.Pfx, renewal.PfxPassword?.Value)); pfxFileInfo.Refresh(); } // Update LastFriendlyName so that the user sees // the most recently issued friendlyName in // the WACS GUI renewal.LastFriendlyName = friendlyName; // Recreate X509Certificate2 with correct flags for Store/Install return(new CertificateInfo() { Certificate = ReadForUse(pfxFileInfo, renewal.PfxPassword?.Value), CacheFile = pfxFileInfo, CacheFilePassword = renewal.PfxPassword?.Value }); }
void ValidateParameters(Common.ParametersValidation validationRequest, ref string logMessage, ref bool passed, XmlNode test) { foreach (Common.ValidationRule rule in validationRequest.ValidationRules) { string parameterPath = string.Format("RequestParameters/{0}", rule.ParameterPath); switch (rule.Type) { case ParameterType.String: CommonCompare.StringCompare(parameterPath, rule.ParameterName, (string)rule.Value, ref logMessage, ref passed, test); break; case ParameterType.Int: CommonCompare.IntCompare(parameterPath, rule.ParameterName, (int)rule.Value, ref logMessage, ref passed, test); break; case ParameterType.OptionalInt: int?value = (int?)rule.Value; if (CommonCompare.Exist2(parameterPath, rule.ParameterName, value.HasValue, ref logMessage, ref passed, test)) { CommonCompare.IntCompare(parameterPath, rule.ParameterName, value.Value, ref logMessage, ref passed, test); } break; case ParameterType.OptionalBool: if (rule.ValueSpecified) { CommonCompare.StringCompare(parameterPath, rule.ParameterName, ((bool)rule.Value).ToString(), ref logMessage, ref passed, test); } else { CommonCompare.Exist2(parameterPath, rule.ParameterName, rule.ValueSpecified, ref logMessage, ref passed, test); } break; case ParameterType.OptionalString: { string stringValue = (string)rule.Value; if (CommonCompare.Exist2(parameterPath, rule.ParameterName, stringValue != null, ref logMessage, ref passed, test)) { CommonCompare.StringCompare(parameterPath, rule.ParameterName, (string)rule.Value, ref logMessage, ref passed, test); } } break; case ParameterType.OptionalElement: { CommonCompare.Exist2(parameterPath, rule.ParameterName, rule.Value != null, ref logMessage, ref passed, test); } break; case ParameterType.OptionalElementBoolFlag: { CommonCompare.Exist2(parameterPath, rule.ParameterName, (bool)rule.Value, ref logMessage, ref passed, test); } break; case ParameterType.StringArray: { CommonCompare.StringArrayCompare(parameterPath, rule.ParameterName, (string[])rule.Value, ref logMessage, ref passed, test); } break; case ParameterType.Log: { if (rule.Value.GetType().ToString() == "System.Byte[]") { logMessage = logMessage + rule.ParameterName + " = [Check it manually!]"; } else { logMessage = logMessage + rule.ParameterName + " = " + rule.Value.ToString(); } } break; case ParameterType.OptionalQName: { XmlQualifiedName QNameValue = (XmlQualifiedName)rule.Value; if (CommonCompare.Exist2(parameterPath, rule.ParameterName, QNameValue != null, ref logMessage, ref passed, test)) { CommonCompare.StringCompare(parameterPath + "/Namespace", rule.ParameterName + "/Namespace", QNameValue.Namespace, ref logMessage, ref passed, test); CommonCompare.StringCompare(parameterPath + "/Name", rule.ParameterName + "/Name", QNameValue.Name, ref logMessage, ref passed, test); } } break; case ParameterType.X509Cert: { Org.BouncyCastle.X509.X509Certificate cert = (new Org.BouncyCastle.X509.X509CertificateParser()).ReadCertificate((byte[])rule.Value); logMessage = logMessage + "\r\n"; logMessage = logMessage + rule.ParameterName + ": " + "\r\n" + cert.ToString(); logMessage = logMessage + "\r\n"; //TextWriter textWriter = new StringWriter(); //Org.BouncyCastle.Utilities.IO.Pem.PemWriter pemWriter = new Org.BouncyCastle.Utilities.IO.Pem.PemWriter(textWriter); //pemWriter.WriteObject(cert.CertificateStructure.SubjectPublicKeyInfo.PublicKeyData); //pemWriter.Writer.Flush(); //string privateKey = textWriter.ToString(); logMessage = logMessage + rule.ParameterName + "(PubK): " + "\r\n" + cert.CertificateStructure.SubjectPublicKeyInfo.PublicKeyData.ToString(); logMessage = logMessage + "\r\n"; logMessage = logMessage + rule.ParameterName + "(SignatureAlgorithm): " + "\r\n" + cert.CertificateStructure.SignatureAlgorithm.ObjectID.ToString(); logMessage = logMessage + "\r\n"; } break; case ParameterType.PKCS10: { Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest pkcs10 = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest((byte[])rule.Value); logMessage = logMessage + "\r\n"; logMessage = logMessage + rule.ParameterName + ": " + "\r\n" + pkcs10.ToString(); logMessage = logMessage + "\r\n"; } break; case ParameterType.PKCS12WithoutPassphrase: { Org.BouncyCastle.Pkcs.Pkcs12Store pkcs12Store = new Org.BouncyCastle.Pkcs.Pkcs12Store(); pkcs12Store.Load(new MemoryStream((byte[])rule.Value), ("").ToArray()); logMessage = logMessage + rule.ParameterName + ": " + "\r\n"; foreach (string alias in pkcs12Store.Aliases) { logMessage = logMessage + "\r\n"; logMessage = logMessage + "Alias = " + alias + "\r\n"; logMessage = logMessage + "Certificate = " + pkcs12Store.GetCertificate(alias).Certificate.ToString(); } logMessage = logMessage + "\r\n"; } break; case ParameterType.CRL: { Org.BouncyCastle.X509.X509Crl crl = (new Org.BouncyCastle.X509.X509CrlParser()).ReadCrl((byte[])rule.Value); logMessage = logMessage + "\r\n"; logMessage = logMessage + rule.ParameterName + ": " + "\r\n" + crl.ToString(); logMessage = logMessage + "\r\n"; } break; case ParameterType.Float: { CommonCompare.FloatCompare(parameterPath, rule.ParameterName, (float)rule.Value, ref logMessage, ref passed, test); } break; case ParameterType.OptionalFloat: float?fvalue = (float?)rule.Value; if (CommonCompare.Exist2(parameterPath, rule.ParameterName, fvalue.HasValue, ref logMessage, ref passed, test)) { CommonCompare.FloatCompare(parameterPath, rule.ParameterName, (float)rule.Value, ref logMessage, ref passed, test); } break; } } }
/// <summary> /// Request certificate from the ACME server /// </summary> /// <param name="csrPlugin">Plugin used to generate CSR if it has not been provided in the target</param> /// <param name="runLevel"></param> /// <param name="renewal"></param> /// <param name="target"></param> /// <param name="order"></param> /// <returns></returns> public async Task <CertificateInfo> RequestCertificate(ICsrPlugin?csrPlugin, RunLevel runLevel, Order order) { if (order.Details == null) { throw new InvalidOperationException(); } // What are we going to get? var cacheKey = CacheKey(order); var pfxFileInfo = new FileInfo(GetPath(order.Renewal, $"-{cacheKey}{PfxPostFix}")); // Determine/check the common name var identifiers = order.Target.GetHosts(false); var commonNameUni = order.Target.CommonName; var commonNameAscii = string.Empty; if (!string.IsNullOrWhiteSpace(commonNameUni)) { var idn = new IdnMapping(); commonNameAscii = idn.GetAscii(commonNameUni); if (!identifiers.Contains(commonNameAscii, StringComparer.InvariantCultureIgnoreCase)) { _log.Warning($"Common name {commonNameUni} provided is invalid."); commonNameAscii = identifiers.First(); commonNameUni = idn.GetUnicode(commonNameAscii); } } // Determine the friendly name base (for the renewal) var friendlyNameBase = order.Renewal.FriendlyName; if (string.IsNullOrEmpty(friendlyNameBase)) { friendlyNameBase = order.Target.FriendlyName; } if (string.IsNullOrEmpty(friendlyNameBase)) { friendlyNameBase = commonNameUni; } // Determine the friendly name for this specific certificate var friendlyNameIntermediate = friendlyNameBase; if (!string.IsNullOrEmpty(order.FriendlyNamePart)) { friendlyNameIntermediate += $" [{order.FriendlyNamePart}]"; } var friendlyName = $"{friendlyNameIntermediate} @ {_inputService.FormatDate(DateTime.Now)}"; // Try using cached certificate first to avoid rate limiting during // (initial?) deployment troubleshooting. Real certificate requests // will only be done once per day maximum unless the --force parameter // is used. var cache = CachedInfo(order); if (cache != null && cache.CacheFile != null) { if (cache.CacheFile.LastWriteTime > DateTime.Now.AddDays(_settings.Cache.ReuseDays * -1)) { if (runLevel.HasFlag(RunLevel.IgnoreCache)) { _log.Warning("Cached certificate available on disk but not used due to --{switch} switch.", nameof(MainArguments.Force).ToLower()); } else { _log.Warning("Using cached certificate for {friendlyName}. To force a new request of the " + "certificate within {days} days, run with the --{switch} switch.", friendlyNameIntermediate, _settings.Cache.ReuseDays, nameof(MainArguments.Force).ToLower()); return(cache); } } } if (order.Details.Payload.Status != AcmeClient.OrderValid) { // Clear cache and write new cert ClearCache(order.Renewal, postfix: CsrPostFix); if (order.Target.CsrBytes == null) { if (csrPlugin == null) { throw new InvalidOperationException("Missing csrPlugin"); } // Backwards compatible with existing keys, which are not split per order yet. var keyFile = new FileInfo(GetPath(order.Renewal, $".keys")); if (!keyFile.Exists) { keyFile = new FileInfo(GetPath(order.Renewal, $"-{cacheKey}.keys")); } var csr = await csrPlugin.GenerateCsr(keyFile.FullName, commonNameAscii, identifiers); var keySet = await csrPlugin.GetKeys(); order.Target.CsrBytes = csr.GetDerEncoded(); order.Target.PrivateKey = keySet.Private; var csrPath = GetPath(order.Renewal, $"-{cacheKey}{CsrPostFix}"); File.WriteAllText(csrPath, _pemService.GetPem("CERTIFICATE REQUEST", order.Target.CsrBytes)); _log.Debug("CSR stored at {path} in certificate cache folder {folder}", Path.GetFileName(csrPath), Path.GetDirectoryName(csrPath)); } _log.Verbose("Submitting CSR"); order.Details = await _client.SubmitCsr(order.Details, order.Target.CsrBytes); if (order.Details.Payload.Status != AcmeClient.OrderValid) { _log.Error("Unexpected order status {status}", order.Details.Payload.Status); throw new Exception($"Unable to complete order"); } } _log.Information("Requesting certificate {friendlyName}", friendlyNameIntermediate); var rawCertificate = await _client.GetCertificate(order.Details); if (rawCertificate == null) { throw new Exception($"Unable to get certificate"); } // Build pfx archive including any intermediates provided var text = Encoding.UTF8.GetString(rawCertificate); var pfx = new bc.Pkcs.Pkcs12Store(); var startIndex = 0; var endIndex = 0; const string startString = "-----BEGIN CERTIFICATE-----"; const string endString = "-----END CERTIFICATE-----"; while (true) { startIndex = text.IndexOf(startString, startIndex); if (startIndex < 0) { break; } endIndex = text.IndexOf(endString, startIndex); if (endIndex < 0) { break; } endIndex += endString.Length; var pem = text[startIndex..endIndex];
// System.Security.Cryptography.X509Certificates.X509Certificate2.Import (string fileName); // https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.import?view=netframework-4.7.2 // https://gist.github.com/yutopio/a217a4af63cf6bcf0a530c14c074cf8f // https://gist.githubusercontent.com/yutopio/a217a4af63cf6bcf0a530c14c074cf8f/raw/42b2f8cb27f6d22b7e22d65da5bbd0f1ce9b2fff/cert.cs // https://stackoverflow.com/questions/44755155/store-pkcs12-container-pfx-with-bouncycastle // https://github.com/Worlaf/RSADemo/blob/328692e28e48db92340d55563480c8724d916384/RSADemo_WinForms/frmRsaDemo.cs public static void Create( string fileName , Org.BouncyCastle.X509.X509Certificate certificate , Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey , string password = "") { // create certificate entry Org.BouncyCastle.Pkcs.X509CertificateEntry certEntry = new Org.BouncyCastle.Pkcs.X509CertificateEntry(certificate); Org.BouncyCastle.Asn1.X509.X509Name name = new Org.BouncyCastle.Asn1.X509.X509Name(certificate.SubjectDN.ToString()); string friendlyName = name .GetValueList(Org.BouncyCastle.Asn1.X509.X509Name.O) .OfType <string>() .FirstOrDefault(); if (System.StringComparer.InvariantCultureIgnoreCase.Equals("Skynet Earth Inc.", friendlyName)) { friendlyName = "Skynet Certification Authority"; } // get bytes of private key. Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo keyInfo = Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey); //byte[] keyBytes = keyInfo.ToAsn1Object().GetEncoded(); Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder builder = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder(); builder.SetUseDerEncoding(true); Org.BouncyCastle.Pkcs.Pkcs12Store store = builder.Build(); store.SetCertificateEntry(friendlyName, certEntry); // create store entry store.SetKeyEntry( //keyFriendlyName friendlyName , new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(privateKey) , new Org.BouncyCastle.Pkcs.X509CertificateEntry[] { certEntry } ); byte[] pfxBytes = null; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { // Cert is contained in store // null: no password, "": an empty passwords // note: Linux needs empty password on null... store.Save(stream, password == null ? "".ToCharArray() : password.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom()); // stream.Position = 0; pfxBytes = stream.ToArray(); } // End Using stream #if WITH_MS_PFX WithMsPfx(pfxBytes, fileName, password); #else byte[] result = Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes); // this.StoreCertificate(System.Convert.ToBase64String(result)); using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(System.IO.File.Open(fileName, System.IO.FileMode.Create))) { writer.Write(result); } // End Using writer #endif } // End Sub Create
private void button1_Click(object sender, EventArgs e) { string signatureAlgorithm = algtxt.Text; var rsaGenerator = new RsaKeyPairGenerator(); var randomGenerator = new CryptoApiRandomGenerator(); var secureRandom = new SecureRandom(randomGenerator); var keyParameters = new KeyGenerationParameters(secureRandom, 1024); rsaGenerator.Init(keyParameters); var keyPair = rsaGenerator.GenerateKeyPair(); var attributes = new System.Collections.Hashtable(); attributes[X509Name.E] = emailtxt.Text; //设置dn信息的邮箱地址 attributes[X509Name.CN] = towhomtxt.Text; //设置证书的用户,也就是颁发给谁 attributes[X509Name.O] = Issuertxt.Text; //设置证书的办法者 attributes[X509Name.C] = "Zh"; //证书的语言 var ordering = new System.Collections.ArrayList(); ordering.Add(X509Name.E); ordering.Add(X509Name.CN); ordering.Add(X509Name.O); ordering.Add(X509Name.C); var generater = new X509V3CertificateGenerator(); //设置证书序列化号 generater.SetSerialNumber(BigInteger.ProbablePrime(120, new Random())); //设置颁发者dn信息 generater.SetIssuerDN(new X509Name(ordering, attributes)); //设置证书生效时间 generater.SetNotBefore(DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0))); //设置证书失效时间 generater.SetNotAfter(DateTime.Today.AddDays(365)); //设置接受者dn信息 generater.SetSubjectDN(new X509Name(ordering, attributes)); //设置证书的公钥 generater.SetPublicKey(keyPair.Public); //设置证书的加密算法 generater.SetSignatureAlgorithm(signatureAlgorithm); generater.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false)); generater.AddExtension(X509Extensions.AuthorityKeyIdentifier, true, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public))); // Key usage: Client authentication generater.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(new System.Collections.ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.2") })); Castle = generater.Generate(keyPair.Private); var store = new Org.BouncyCastle.Pkcs.Pkcs12Store(); string friendlyname = Castle.SubjectDN.ToString(); var ccentry = new Org.BouncyCastle.Pkcs.X509CertificateEntry(Castle); store.SetCertificateEntry(friendlyname, ccentry); store.SetKeyEntry(friendlyname, new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(keyPair.Private), new[] { ccentry }); certificate.Text = "-----BEGIN CERTIFICATE-----\r\n" + Convert.ToBase64String(Castle.GetEncoded()) + "\r\n-----END CERTIFICATE-----"; string password = pswtxt.Text; Castlekey = keyPair.Private; var stream = new MemoryStream(); store.Save(stream, password.ToCharArray(), secureRandom); nametxt.Text = Castle.IssuerDN.ToString(); TextWriter textWriter = new StringWriter(); PemWriter pemWriter = new PemWriter(textWriter); pemWriter.WriteObject(Castle.GetPublicKey()); pemWriter.Writer.Flush(); pubtxt.Text = textWriter.ToString(); SaveFileDialog output = new SaveFileDialog(); output.Filter = "pfx file|*.pfx"; output.RestoreDirectory = true; output.InitialDirectory = Environment.CurrentDirectory; output.FilterIndex = 1; if (output.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(output.FileName, stream.ToArray()); } else { MessageBox.Show("pfx证书不导出!"); } output.Filter = "cer file|*.cer"; if (output.ShowDialog() == DialogResult.OK) { File.WriteAllText(output.FileName, certificate.Text); } else { MessageBox.Show("cer证书没导出!"); } }
/// <summary> /// Request certificate from the ACME server /// </summary> /// <param name="binding"></param> /// <returns></returns> public CertificateInfo RequestCertificate(ICsrPlugin csrPlugin, Renewal renewal, Target target, OrderDetails order) { // What are we going to get? var pfxFileInfo = new FileInfo(PfxFilePath(renewal)); // Determine/check the common name var identifiers = target.GetHosts(false); var commonName = target.CommonName; if (!string.IsNullOrWhiteSpace(commonName)) { var idn = new IdnMapping(); commonName = idn.GetAscii(commonName); if (!identifiers.Contains(commonName, StringComparer.InvariantCultureIgnoreCase)) { _log.Warning($"Common name {commonName} provided is invalid."); commonName = identifiers.First(); } } // 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, renewal.PfxPassword), PfxFile = pfxFileInfo }; var idn = new IdnMapping(); if (cached.SubjectName == commonName && cached.HostNames.Count == identifiers.Count() && cached.HostNames.All(h => identifiers.Contains(idn.GetAscii(h)))) { if (_options.Force) { _log.Warning("Cached certificate available but not used with --{switch}. Use 'Renew specific' or 'Renew all' in the main menu to run unscheduled renewals without hitting rate limits.", nameof(MainArguments.Force).ToLower()); } 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 --{switch} switch. Be ware that you might run into rate limits doing so.", renewal.FriendlyName, nameof(MainArguments.Force).ToLower()); return(cached); } } } catch { // File corrupt or invalid password? _log.Warning("Unable to read from certificate cache"); } } var csr = csrPlugin.GenerateCsr(commonName, identifiers); var csrBytes = csr.CreateSigningRequest(); order = _client.SubmitCsr(order, csrBytes); if (Settings.Default.SavePrivateKeyPem) { File.WriteAllText(GetPath(renewal, "-key.pem"), GetPem(csrPlugin.GeneratePrivateKey())); } File.WriteAllText(GetPath(renewal, "-csr.pem"), GetPem("CERTIFICATE REQUEST", csrBytes)); _log.Information("Requesting certificate {friendlyName}", renewal.FriendlyName); var rawCertificate = _client.GetCertificate(order); if (rawCertificate == null) { throw new Exception($"Unable to get certificate"); } var certificate = new X509Certificate2(rawCertificate); var certificateExport = certificate.Export(X509ContentType.Cert); var crtDerFile = GetPath(renewal, $"-crt.der"); var crtPemFile = GetPath(renewal, $"-crt.pem"); var crtPem = GetPem("CERTIFICATE", certificateExport); _log.Information("Saving certificate to {crtDerFile}", _certificatePath); File.WriteAllBytes(crtDerFile, certificateExport); File.WriteAllText(crtPemFile, crtPem); // Get issuer certificate and save in DER and PEM formats var chain = new X509Chain(); chain.Build(certificate); X509Certificate2 issuerCertificate = chain.ChainElements[1].Certificate; var issuerCertificateExport = issuerCertificate.Export(X509ContentType.Cert); var issuerPem = GetPem("CERTIFICATE", issuerCertificateExport); File.WriteAllBytes(GetPath(renewal, "-crt.der", "ca-"), issuerCertificateExport); File.WriteAllText(GetPath(renewal, "-crt.pem", "ca-"), issuerPem); // Generate combined files File.WriteAllText(GetPath(renewal, "-chain.pem", "ca-"), crtPem + issuerPem); // Build pfx archive var pfx = new bc.Pkcs.Pkcs12Store(); var bcCertificate = ParsePem <bc.X509.X509Certificate>(crtPem); var bcCertificateEntry = new bc.Pkcs.X509CertificateEntry(bcCertificate); var bcCertificateAlias = bcCertificate.SubjectDN.ToString(); var bcPrivateKeyEntry = new bc.Pkcs.AsymmetricKeyEntry(csrPlugin.GeneratePrivateKey()); pfx.SetCertificateEntry(bcCertificateAlias, bcCertificateEntry); pfx.SetKeyEntry(bcCertificateAlias, bcPrivateKeyEntry, new[] { bcCertificateEntry }); var bcIssuer = ParsePem <bc.X509.X509Certificate>(issuerPem); var bcIssuerEntry = new bc.Pkcs.X509CertificateEntry(bcIssuer); var bcIssuerAlias = bcIssuer.SubjectDN.ToString(); pfx.SetCertificateEntry(bcIssuerAlias, bcIssuerEntry); using (var pfxStream = new MemoryStream()) { pfx.Save(pfxStream, null, new bc.Security.SecureRandom()); pfxStream.Position = 0; using (var pfxStreamReader = new BinaryReader(pfxStream)) { var tempPfx = new X509Certificate2( pfxStreamReader.ReadBytes((int)pfxStream.Length), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); if (csrPlugin.CanConvert()) { try { var converted = csrPlugin.Convert(tempPfx.PrivateKey); if (converted != null) { tempPfx.PrivateKey = converted; } } catch { _log.Warning("Private key conversion error."); } } tempPfx.FriendlyName = FriendlyName(renewal); File.WriteAllBytes(pfxFileInfo.FullName, tempPfx.Export(X509ContentType.Pfx, renewal.PfxPassword)); pfxFileInfo.Refresh(); } } // Recreate X509Certificate2 with correct flags for Store/Install return(new CertificateInfo() { Certificate = ReadForUse(pfxFileInfo, renewal.PfxPassword), PfxFile = pfxFileInfo }); }
/// <summary> /// Exports the specified stream and password to a pkcs12 encrypted file. /// </summary> /// <remarks> /// Exports the specified stream and password to a pkcs12 encrypted file. /// </remarks> /// <param name="stream">The output stream.</param> /// <param name="password">The password to use to lock the private keys.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="stream"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="password"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.IO.IOException"> /// An error occurred while writing to the stream. /// </exception> public void Export(System.IO.Stream stream, string password) { if (stream == null) { throw new System.ArgumentNullException(nameof(stream)); } if (password == null) { throw new System.ArgumentNullException(nameof(password)); } Org.BouncyCastle.Pkcs.Pkcs12Store store = new Org.BouncyCastle.Pkcs.Pkcs12Store(); foreach (Org.BouncyCastle.X509.X509Certificate certificate in certs) { if (keys.ContainsKey(certificate)) { continue; } string alias = GetCommonName(certificate); if (alias == null) { continue; } Org.BouncyCastle.Pkcs.X509CertificateEntry entry = new Org.BouncyCastle.Pkcs.X509CertificateEntry(certificate); store.SetCertificateEntry(alias, entry); } foreach ( System.Collections.Generic.KeyValuePair < Org.BouncyCastle.X509.X509Certificate, Org.BouncyCastle.Crypto.AsymmetricKeyParameter > kvp in keys) { string alias = GetCommonName(kvp.Key); if (alias == null) { continue; } Org.BouncyCastle.Pkcs.AsymmetricKeyEntry entry = new Org.BouncyCastle.Pkcs.AsymmetricKeyEntry(kvp.Value); Org.BouncyCastle.Pkcs.X509CertificateEntry cert = new Org.BouncyCastle.Pkcs.X509CertificateEntry(kvp.Key); System.Collections.Generic.List <Org.BouncyCastle.Pkcs.X509CertificateEntry> chain = new System.Collections.Generic.List <Org.BouncyCastle.Pkcs.X509CertificateEntry>(); chain.Add(cert); store.SetKeyEntry(alias, entry, chain.ToArray()); } store.Save(stream, password.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom()); }