Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
                }
            }
        }
Beispiel #3
0
        } // End Sub GenerateRootCertificate

        public static void BouncyCert()
        {
            string pemOrDerFile = "";

            Org.BouncyCastle.X509.X509CertificateParser kpp  = new Org.BouncyCastle.X509.X509CertificateParser();
            Org.BouncyCastle.X509.X509Certificate       cert = kpp.ReadCertificate(System.IO.File.OpenRead(pemOrDerFile));
            Org.BouncyCastle.Security.DotNetUtilities.ToX509Certificate(cert);
            System.Security.Cryptography.X509Certificates.X509Certificate  msCert = Org.BouncyCastle.Security.DotNetUtilities.ToX509Certificate(cert);
            System.Security.Cryptography.X509Certificates.X509Certificate2 ms2    = new System.Security.Cryptography.X509Certificates.X509Certificate2(msCert);

            Org.BouncyCastle.Pkcs.AsymmetricKeyEntry       keyEntry   = null; //store.GetKey(alias);
            Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey = keyEntry.Key;

            ms2.PrivateKey = Org.BouncyCastle.Security.DotNetUtilities.ToRSA((Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)keyEntry.Key);
        }
        /// <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);
                    }
                }
            }
        }
Beispiel #5
0
        } // 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
Beispiel #6
0
        /// <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
            });
        }
Beispiel #7
0
        /// <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());
        }