private static byte[] CreatePfxFile(Org.BouncyCastle.X509.X509Certificate certificate, AsymmetricKeyParameter privateKey, string password = null)
        {
            // create certificate entry
            var    certEntry    = new X509CertificateEntry(certificate);
            string friendlyName = certificate.SubjectDN.ToString();

            // get bytes of private key.
            PrivateKeyInfo keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);

            byte[] keyBytes = keyInfo.ToAsn1Object().GetEncoded();

            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var store = builder.Build();

            // create store entry
            store.SetKeyEntry("", new AsymmetricKeyEntry(privateKey), new X509CertificateEntry[] { certEntry });
            byte[] pfxBytes = null;
            using (MemoryStream stream = new MemoryStream())
            {
                store.Save(stream, password?.ToCharArray(), new SecureRandom());
                pfxBytes = stream.ToArray();
            }
            var result = Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes);

            return(result);
        }
Beispiel #2
0
        private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
        {
            const string password = "******";
            Pkcs12Store  store;

            if (RunTime.IsRunningOnMono)
            {
                var builder = new Pkcs12StoreBuilder();
                builder.SetUseDerEncoding(true);
                store = builder.Build();
            }
            else
            {
                store = new Pkcs12Store();
            }

            var entry = new X509CertificateEntry(certificate);

            store.SetCertificateEntry(certificate.SubjectDN.ToString(), entry);

            store.SetKeyEntry(certificate.SubjectDN.ToString(), new AsymmetricKeyEntry(privateKey), new[] { entry });
            using (var ms = new MemoryStream())
            {
                store.Save(ms, password.ToCharArray(), new SecureRandom(new CryptoApiRandomGenerator()));

                return(new X509Certificate2(ms.ToArray(), password, X509KeyStorageFlags.Exportable));
            }
        }
    /// <summary>
    /// Create a X509Certificate2 with a private key by combining
    /// a bouncy castle X509Certificate and a private key
    /// </summary>
    private static X509Certificate2 CreateCertificateWithPrivateKey(
        Org.BouncyCastle.X509.X509Certificate certificate,
        string friendlyName,
        AsymmetricKeyParameter privateKey,
        SecureRandom random)
    {
        // create pkcs12 store for cert and private key
        using (MemoryStream pfxData = new MemoryStream())
        {
            Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder();
            builder.SetUseDerEncoding(true);
            Pkcs12Store            pkcsStore = builder.Build();
            X509CertificateEntry[] chain     = new X509CertificateEntry[1];
            string passcode = Guid.NewGuid().ToString();
            chain[0] = new X509CertificateEntry(certificate);
            if (string.IsNullOrEmpty(friendlyName))
            {
                friendlyName = GetCertificateCommonName(certificate);
            }
            pkcsStore.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(privateKey), chain);
            pkcsStore.Save(pfxData, passcode.ToCharArray(), random);

            // merge into X509Certificate2
            return(CreateCertificateFromPKCS12(pfxData.ToArray(), passcode));
        }
    }
Beispiel #4
0
        public static X509Certificate2 Load(Stream stream, string password)
        {
            var loadStore = new Pkcs12Store();

            loadStore.Load(stream, password?.ToCharArray());

            string keyAlias = loadStore.Aliases.Cast <string> ().FirstOrDefault(loadStore.IsKeyEntry);

            if (keyAlias == null)
            {
                throw new NotImplementedException("Alias");
            }

            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var saveStore = builder.Build();

            var chain = new X509CertificateEntry(loadStore.GetCertificate(keyAlias).Certificate);

            saveStore.SetCertificateEntry("Alias", chain);
            saveStore.SetKeyEntry("Alias", new AsymmetricKeyEntry((RsaPrivateCrtKeyParameters)loadStore.GetKey(keyAlias).Key), new [] { chain });

            using (var saveStream = new MemoryStream())
            {
                saveStore.Save(saveStream, new char[0], new SecureRandom());
                return(new X509Certificate2(Pkcs12Utilities.ConvertToDefiniteLength(saveStream.ToArray())));
            }
        }
        /// <summary>
        /// Genera el archivo pfx y devuelve el resultado con su contraseña
        /// </summary>
        /// <param name="rutaArchivoCer"></param>
        /// <param name="rutaArchivoKey"></param>
        /// <param name="secretArchivoKey"></param>
        /// <param name="rutaGuardado"></param>
        /// <param name="nombreArchivoPfx"></param>
        /// <param name="secretArchivoPfx"></param>
        /// <param name="conservarArchivo"></param>
        /// <returns>Pfx</returns>
        public static CfdiPfx generarArchivoPfx(string rutaArchivoCer, string rutaArchivoKey, string secretArchivoKey, string rutaGuardado, string nombreArchivoPfx, string secretArchivoPfx, Boolean conservarArchivo)
        {
            try
            {
                string rutaArchivoPfx = Path.Combine(rutaGuardado, nombreArchivoPfx);

                if (!Directory.Exists(rutaGuardado))
                {
                    Directory.CreateDirectory(rutaGuardado);
                }

                if (File.Exists(rutaArchivoPfx))
                {
                    File.Delete(rutaArchivoPfx);
                }

                X509Certificate2 certificado = new X509Certificate2(rutaArchivoCer);
                Org.BouncyCastle.X509.X509Certificate certificate = DotNetUtilities.FromX509Certificate(certificado);

                byte[] bytesArchivoKey            = File.ReadAllBytes(rutaArchivoKey);
                AsymmetricKeyParameter privateKey = PrivateKeyFactory.DecryptKey(secretArchivoKey.ToCharArray(), bytesArchivoKey);

                var    certEntry    = new X509CertificateEntry(certificate);
                string friendlyName = certificate.SubjectDN.ToString();

                PrivateKeyInfo keyInfo  = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
                byte[]         keyBytes = keyInfo.ToAsn1Object().GetEncoded();

                var builder = new Pkcs12StoreBuilder();
                builder.SetUseDerEncoding(true);
                var store = builder.Build();

                store.SetKeyEntry("PrivateKeyAlias", new AsymmetricKeyEntry(privateKey), new X509CertificateEntry[] { certEntry });

                byte[] pfxBytes = null;

                using (MemoryStream stream = new MemoryStream())
                {
                    store.Save(stream, secretArchivoPfx.ToCharArray(), new SecureRandom());
                    pfxBytes = stream.ToArray(); // Este sirve para la cancelacion
                }

                var result = Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes);

                if (conservarArchivo)
                {
                    File.WriteAllBytes(rutaArchivoPfx, result);
                }

                return(new CfdiPfx(result, secretArchivoPfx));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Beispiel #6
0
        public static X509Certificate2 LoadFromUnencryptedPEM(string pem)
        {
            //Extract certificate
            var pattern     = new Regex(@"^[-]{5}BEGIN CERTIFICATE[-]{5}(?<certificate>([^-]*))[-]{5}END CERTIFICATE[-]{5}", RegexOptions.Multiline);
            var pvk_pattern = new Regex(@"[-]{5}BEGIN(?<encrypted>( ENCRYPTED)?) PRIVATE KEY[-]{5}(?<key>([^-]*))[-]{5}END( ENCRYPTED)? PRIVATE KEY[-]{5}", RegexOptions.Multiline);

            if (!pattern.IsMatch(pem))
            {
                throw new ArgumentException("Certificate malformed. (No certitficates found)");
            }
            if (!pvk_pattern.IsMatch(pem))
            {
                throw new ArgumentException("Certificate malformed. (No private key found)");
            }

            //Read all certificates to a jagged byte array
            MatchCollection mc           = pattern.Matches(pem);
            var             certificates = new byte[mc.Count][];
            var             index        = 0;

            foreach (Match match in mc)
            {
                certificates[index] = Convert.FromBase64String(match.Groups["certificate"].ToString().Trim(Environment.NewLine.ToCharArray()));
                index++;
            }
            //If the private key is encrypted (check on "encrypted" group) then that need to be handled in future, probably never.
            Match  pvk_match = pvk_pattern.Match(pem);
            string pvk       = pvk_match.Groups["key"].ToString();

            var parser            = new X509CertificateParser();
            var parsedCertificate = parser.ReadCertificate(Combine(certificates));

            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var inputKeyStore = builder.Build();

            inputKeyStore.SetCertificateEntry("Alias", new X509CertificateEntry(parsedCertificate));
            inputKeyStore.SetKeyEntry("Alias", new AsymmetricKeyEntry((RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pvk))), new [] { new X509CertificateEntry(parsedCertificate) });

            string keyAlias = inputKeyStore.Aliases.Cast <string> ().FirstOrDefault(inputKeyStore.IsKeyEntry);

            if (keyAlias == null)
            {
                throw new InvalidKeyException("Alias");
            }

            using (var stream = new MemoryStream())
            {
                //There is no password
                inputKeyStore.Save(stream, new char[0], new SecureRandom());
                return(new X509Certificate2(Pkcs12Utilities.ConvertToDefiniteLength(stream.ToArray())));
            }
        }
Beispiel #7
0
        private static byte[] CreatePfxFile(X509Certificate certificate, AsymmetricKeyParameter privateKey, string name, string password)
        {
            var certEntry = new X509CertificateEntry(certificate);

            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var store = builder.Build();

            store.SetKeyEntry(name, new AsymmetricKeyEntry(privateKey), new X509CertificateEntry[] { certEntry });

            using MemoryStream stream = new MemoryStream();
            store.Save(stream, password.ToCharArray(), new SecureRandom());
            var pfxBytes = stream.ToArray();
            var result   = Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes);

            return(result);
        }
Beispiel #8
0
        public static byte[] CreatePKCS12(X509Certificate certificate, AsymmetricKeyParameter privateKey, string password)
        {
            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var store = builder.Build();

            var certEntry = new X509CertificateEntry(certificate);

            store.SetKeyEntry("some_alias",
                              new AsymmetricKeyEntry(privateKey),
                              new X509CertificateEntry[] { certEntry });

            byte[] pfxBytes;
            using (MemoryStream stream = new MemoryStream()) {
                store.Save(stream, password.ToCharArray(), new SecureRandom());
                pfxBytes = stream.ToArray();
            }

            return(Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes));
        }
        /// <summary>
        /// Create pfx
        /// </summary>
        /// <param name="certificate"></param>
        /// <param name="privateKey"></param>
        /// <param name="password"></param>
        internal static byte[] ToPfx(this X509Certificate certificate,
                                     AsymmetricKeyParameter privateKey, string password = null)
        {
            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var store = builder.Build();

            // create store entry
            var friendlyName = certificate.SubjectDN.ToString();

            store.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(privateKey),
                              new X509CertificateEntry[] {
                new X509CertificateEntry(certificate)
            });
            using (var stream = new MemoryStream()) {
                using (var cfrg = new RandomGeneratorAdapter()) {
                    store.Save(stream, (password ?? string.Empty).ToCharArray(),
                               new SecureRandom(cfrg));
                }
                return(Pkcs12Utilities.ConvertToDefiniteLength(stream.ToArray()));
            }
        }
Beispiel #10
0
        private byte[] CreatePfxFile(Org.BouncyCastle.X509.X509Certificate cert, AsymmetricKeyParameter privateKey, string password, string keyFriendlyName)
        {
            var certEntry    = new X509CertificateEntry(cert);
            var friendlyName = cert.SubjectDN.ToString();

            var keyInfo  = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
            var keyBytes = keyInfo.ToAsn1Object().GetEncoded();

            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            var store = builder.Build();

            store.SetKeyEntry(keyFriendlyName, new AsymmetricKeyEntry(privateKey), new[] { certEntry });
            byte[] pfxBytes;

            using (var ms = new MemoryStream())
            {
                store.Save(ms, password.ToCharArray(), new SecureRandom());
                pfxBytes = ms.ToArray();
            }

            return(Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes));
        }
Beispiel #11
0
        /// <summary>
        /// Static method used to create a certificate and return as a .net object
        /// </summary>
        public static X509Certificate2 Create(string name, DateTime start, DateTime end, string userPassword,
                                              bool addtoStore = false)
        {
            // generate a key pair using RSA
            var generator = new RsaKeyPairGenerator();

            // keys have to be a minimum of 2048 bits for Azure
            generator.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 2048));
            AsymmetricCipherKeyPair cerKp = generator.GenerateKeyPair();
            // get a copy of the private key
            AsymmetricKeyParameter privateKey = cerKp.Private;

            // create the CN using the name passed in and create a unique serial number for the cert
            var        certName = new X509Name("CN=" + name);
            BigInteger serialNo = BigInteger.ProbablePrime(120, new Random());

            // start the generator and set CN/DN and serial number and valid period
            var x509Generator = new X509V3CertificateGenerator();

            x509Generator.SetSerialNumber(serialNo);
            x509Generator.SetSubjectDN(certName);
            x509Generator.SetIssuerDN(certName);
            x509Generator.SetNotBefore(start);
            x509Generator.SetNotAfter(end);
            // add the server authentication key usage
            var keyUsage = new KeyUsage(KeyUsage.KeyEncipherment);

            x509Generator.AddExtension(X509Extensions.KeyUsage, false, keyUsage.ToAsn1Object());
            var extendedKeyUsage = new ExtendedKeyUsage(new[] { KeyPurposeID.IdKPServerAuth });

            x509Generator.AddExtension(X509Extensions.ExtendedKeyUsage, true, extendedKeyUsage.ToAsn1Object());
            // algorithm can only be SHA1 ??
            x509Generator.SetSignatureAlgorithm("sha1WithRSA");
            // Set the key pair
            x509Generator.SetPublicKey(cerKp.Public);
            X509Certificate certificate = x509Generator.Generate(cerKp.Private);

            // export the certificate bytes
            byte[] certStream = DotNetUtilities.ToX509Certificate(certificate).Export(X509ContentType.Pkcs12,
                                                                                      userPassword);

            // build the key parameter and the certificate entry
            var keyEntry = new AsymmetricKeyEntry(privateKey);
            var entry    = new X509CertificateEntry(certificate);
            // build the PKCS#12 store to encapsulate the certificate
            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            builder.SetCertAlgorithm(PkcsObjectIdentifiers.Sha1WithRsaEncryption);
            builder.SetKeyAlgorithm(PkcsObjectIdentifiers.Sha1WithRsaEncryption);
            builder.Build();
            // create a memorystream to hold the output
            var stream = new MemoryStream(2000);
            // create the individual store and set two entries for cert and key
            var store = new Pkcs12Store();

            store.SetCertificateEntry("Elastacloud Test Certificate", entry);
            store.SetKeyEntry("Elastacloud Test Certificate", keyEntry, new[] { entry });
            store.Save(stream, userPassword.ToCharArray(), new SecureRandom());

            // Create the equivalent C# representation
            var cert = new X509Certificate2(stream.GetBuffer(), userPassword, X509KeyStorageFlags.Exportable);

            // if specified then this add this certificate to the store
            if (addtoStore)
            {
                AddToMyStore(cert);
            }

            return(cert);
        }
        /// <summary>
        /// Creates a cert with the connectionstring (token) and stores it in the given cert store.
        /// </summary>
        public async static Task WriteAsync(string name, string connectionString, string storeType, string storePath)
        {
            if (string.IsNullOrEmpty(connectionString))
            {
                throw new ArgumentException("Token not found in X509Store and no new token provided!");
            }

            SecureRandom            random = new SecureRandom();
            KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048);
            RsaKeyPairGenerator     keyPairGenerator        = new RsaKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);
            AsymmetricCipherKeyPair keys = keyPairGenerator.GenerateKeyPair();

            ArrayList nameOids = new ArrayList();

            nameOids.Add(X509Name.CN);
            ArrayList nameValues = new ArrayList();

            nameValues.Add(name);
            X509Name subjectDN = new X509Name(nameOids, nameValues);
            X509Name issuerDN  = subjectDN;

            X509V3CertificateGenerator cg = new X509V3CertificateGenerator();

            cg.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));
            cg.SetIssuerDN(issuerDN);
            cg.SetSubjectDN(subjectDN);
            cg.SetNotBefore(DateTime.Now);
            cg.SetNotAfter(DateTime.Now.AddMonths(12));
            cg.SetPublicKey(keys.Public);
            cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment));

            // encrypt the token with the public key so only the owner of the assoc. private key can decrypt it and
            // "hide" it in the instruction code cert extension
            RSA              rsa       = RSA.Create();
            RSAParameters    rsaParams = new RSAParameters();
            RsaKeyParameters keyParams = (RsaKeyParameters)keys.Public;

            rsaParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length];
            keyParams.Modulus.ToByteArrayUnsigned().CopyTo(rsaParams.Modulus, 0);

            rsaParams.Exponent = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length];
            keyParams.Exponent.ToByteArrayUnsigned().CopyTo(rsaParams.Exponent, 0);

            rsa.ImportParameters(rsaParams);
            if (rsa != null)
            {
                byte[] bytes = rsa.Encrypt(Encoding.ASCII.GetBytes(connectionString), RSAEncryptionPadding.OaepSHA1);
                if (bytes != null)
                {
                    cg.AddExtension(X509Extensions.InstructionCode, false, bytes);
                }
                else
                {
                    RsaUtils.RSADispose(rsa);
                    throw new CryptographicException("Can not encrypt IoTHub security token using generated public key!");
                }
            }
            RsaUtils.RSADispose(rsa);

            // sign the cert with the private key
            ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", keys.Private, random);

            Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

            // create a PKCS12 store for the cert and its private key
            X509Certificate2 certificate = null;

            using (MemoryStream pfxData = new MemoryStream())
            {
                Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder();
                builder.SetUseDerEncoding(true);
                Pkcs12Store            pkcsStore = builder.Build();
                X509CertificateEntry[] chain     = new X509CertificateEntry[1];
                string passcode = Guid.NewGuid().ToString();
                chain[0] = new X509CertificateEntry(x509);
                pkcsStore.SetKeyEntry(name, new AsymmetricKeyEntry(keys.Private), chain);
                pkcsStore.Save(pfxData, passcode.ToCharArray(), random);

                // create X509Certificate2 object from PKCS12 file
                certificate = CertificateFactory.CreateCertificateFromPKCS12(pfxData.ToArray(), passcode);

                // handle each store type differently
                switch (storeType)
                {
                case CertificateStoreType.Directory:
                {
                    // Add to DirectoryStore
                    using (DirectoryCertificateStore store = new DirectoryCertificateStore())
                    {
                        store.Open(storePath);
                        X509CertificateCollection certificates = await store.Enumerate();

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                await store.Delete(cert.Thumbprint);
                            }
                        }

                        // add new one
                        await store.Add(certificate);
                    }
                    break;
                }

                case CertificateStoreType.X509Store:
                {
                    // Add to X509Store
                    using (X509Store store = new X509Store(storePath, StoreLocation.CurrentUser))
                    {
                        store.Open(OpenFlags.ReadWrite);

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in store.Certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                store.Remove(cert);
                            }
                        }

                        // add new cert to store
                        try
                        {
                            store.Add(certificate);
                        }
                        catch (Exception e)
                        {
                            throw new Exception($"Not able to add cert to the requested store type '{storeType}' (exception message: '{e.Message}'.");
                        }
                    }
                    break;
                }

                default:
                {
                    throw new Exception($"The requested store type '{storeType}' is not supported. Please change.");
                }
                }
                return;
            }
        }
Beispiel #13
0
        /// <summary>
        /// Static method used to create a certificate and return as a .net object
        /// </summary>

        public static X509Certificate2 Create(string name, DateTime start, DateTime end, string userPassword, bool addtoStore = false, string exportDirectory = @"Models\Encryption\Certificates\")
        {
            // generate a key pair using RSA
            var generator = new RsaKeyPairGenerator();

            // keys have to be a minimum of 2048 bits for Azure
            generator.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 2048));
            AsymmetricCipherKeyPair cerKp = generator.GenerateKeyPair();
            // get a copy of the private key
            AsymmetricKeyParameter privateKey = cerKp.Private;


            // create the CN using the name passed in and create a unique serial number for the cert
            var        certName = new X509Name("CN=" + name);
            BigInteger serialNo = BigInteger.ProbablePrime(120, new Random());

            // start the generator and set CN/DN and serial number and valid period
            var x509Generator = new X509V3CertificateGenerator();

            x509Generator.SetSerialNumber(serialNo);
            x509Generator.SetSubjectDN(certName);
            x509Generator.SetIssuerDN(certName);
            x509Generator.SetNotBefore(start);
            x509Generator.SetNotAfter(end);
            // add the server authentication key usage
            var keyUsage = new KeyUsage(KeyUsage.KeyEncipherment);

            x509Generator.AddExtension(X509Extensions.KeyUsage, false, keyUsage.ToAsn1Object());
            var extendedKeyUsage = new ExtendedKeyUsage(new[] { KeyPurposeID.IdKPServerAuth });

            x509Generator.AddExtension(X509Extensions.ExtendedKeyUsage, true, extendedKeyUsage.ToAsn1Object());
            // algorithm can only be SHA1 ??


            ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", cerKp.Private);

            // Set the key pair
            x509Generator.SetPublicKey(cerKp.Public);
            X509Certificate certificate = x509Generator.Generate(signatureFactory);


            // export the certificate bytes
            byte[] certStream = DotNetUtilities.ToX509Certificate(certificate).Export(X509ContentType.Pkcs12, userPassword);

            // build the key parameter and the certificate entry
            var keyEntry = new AsymmetricKeyEntry(privateKey);
            var entry    = new X509CertificateEntry(certificate);
            // build the PKCS#12 store to encapsulate the certificate
            var builder = new Pkcs12StoreBuilder();

            builder.SetUseDerEncoding(true);
            builder.SetCertAlgorithm(PkcsObjectIdentifiers.Sha256WithRsaEncryption);
            builder.SetKeyAlgorithm(PkcsObjectIdentifiers.Sha256WithRsaEncryption);
            builder.Build();
            // create a memorystream to hold the output
            var stream = new MemoryStream(10000);
            // create the individual store and set two entries for cert and key
            var store = new Pkcs12Store();

            store.SetCertificateEntry("Created by Blockchain", entry);
            store.SetKeyEntry("Created by Blockchain", keyEntry, new[] { entry });
            store.Save(stream, userPassword.ToCharArray(), new SecureRandom());

            // Create the equivalent C# representation
            var cert = new X509Certificate2(stream.GetBuffer(), userPassword, X509KeyStorageFlags.Exportable);

            // set up the PEM writer too
            if (exportDirectory != null)
            {
                var textWriter = new StringWriter();
                var pemWriter  = new PemWriter(textWriter);
                pemWriter.WriteObject(cerKp.Private, "DESEDE", userPassword.ToCharArray(), new SecureRandom());

                pemWriter.Writer.Flush();
                string privateKeyPem = textWriter.ToString();
                using (var writer = new StreamWriter(Path.Combine(exportDirectory, cert.Thumbprint + ".pem")))
                {
                    writer.WriteLine(privateKeyPem);
                }
                // also export the certs - first the .pfx
                byte[] privateKeyBytes = cert.Export(X509ContentType.Pfx, userPassword);
                using (var writer = new FileStream(Path.Combine(exportDirectory, cert.Thumbprint + ".pfx"), FileMode.OpenOrCreate, FileAccess.Write))
                {
                    writer.Write(privateKeyBytes, 0, privateKeyBytes.Length);
                }
                // also export the certs - then the .cer
                byte[] publicKeyBytes = cert.Export(X509ContentType.Cert);
                using (var writer = new FileStream(Path.Combine(exportDirectory, cert.Thumbprint + ".cer"), FileMode.OpenOrCreate, FileAccess.Write))
                {
                    writer.Write(publicKeyBytes, 0, publicKeyBytes.Length);
                }
            }

            // if specified then this add this certificate to the store
            if (addtoStore)
            {
                AddToMyStore(cert);
            }

            return(cert);
        }