public static extern IntPtr CertCreateSelfSignCertificate(
     IntPtr providerHandle,
     [In] ref CryptoApiBlob subjectIssuerBlob,
     int flags,
     [In] ref CryptKeyProviderInformation keyProviderInformation,
     [In] ref CryptAlgorithmIdentifier signatureAlgorithm,
     [In] ref SystemTime startTime,
     [In] ref SystemTime endTime,
     IntPtr extensions);
        public static X509Certificate2 GenerateSelfSignedCertificate(String name = "", DateTime?startTime = null, DateTime?endTime = null)
        {
            if (startTime == null || (DateTime)startTime < DateTime.FromFileTimeUtc(0))
            {
                startTime = DateTime.FromFileTimeUtc(0);
            }
            var startSystemTime = ((DateTime)startTime).ToSystemTime();

            if (endTime == null)
            {
                endTime = DateTime.MaxValue;
            }
            var      endSystemTime      = ((DateTime)endTime).ToSystemTime();
            string   containerName      = Guid.NewGuid().ToString();
            GCHandle dataHandle         = new GCHandle();
            IntPtr   providerContext    = IntPtr.Zero;
            IntPtr   cryptKey           = IntPtr.Zero;
            IntPtr   certificateContext = IntPtr.Zero;
            IntPtr   algorithmPointer   = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                MarshalHelper.CheckReturnValue(CryptAcquireContextW(out providerContext, containerName, null, 0x18, 0x8));
                MarshalHelper.CheckReturnValue(CryptGenKey(providerContext, 0x6610, 0x4000001, out cryptKey));
                IntPtr errorStringPtr;
                int    nameDataLength = 0;
                byte[] nameData;
                dataHandle = GCHandle.Alloc(name, GCHandleType.Pinned);
                if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, null, ref nameDataLength, out errorStringPtr))
                {
                    string error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }
                nameData = new byte[nameDataLength];
                if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, nameData, ref nameDataLength, out errorStringPtr))
                {
                    string error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }
                dataHandle.Free();
                dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);
                CryptoApiBlob nameBlob = new CryptoApiBlob {
                    cbData = (uint)nameData.Length, pbData = dataHandle.AddrOfPinnedObject()
                };
                dataHandle.Free();
                CryptKeyProviderInformation keyProvider = new CryptKeyProviderInformation {
                    pwszContainerName = containerName, dwProvType = 0x18, dwKeySpec = 1
                };
                CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier {
                    pszObjId = "1.2.840.113549.1.1.13", Parameters = new CryptoApiBlob()
                };
                algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm));
                Marshal.StructureToPtr(algorithm, algorithmPointer, false);
                certificateContext = CertCreateSelfSignCertificate(providerContext, ref nameBlob, 0, ref keyProvider, algorithmPointer, ref startSystemTime, ref endSystemTime, IntPtr.Zero);
                MarshalHelper.CheckReturnValue(certificateContext != IntPtr.Zero);
                return(new X509Certificate2(certificateContext));
            }
            finally
            {
                if (dataHandle.IsAllocated)
                {
                    dataHandle.Free();
                }
                if (certificateContext != IntPtr.Zero)
                {
                    CertFreeCertificateContext(certificateContext);
                }
                if (cryptKey != IntPtr.Zero)
                {
                    CryptDestroyKey(cryptKey);
                }
                if (providerContext != IntPtr.Zero)
                {
                    CryptReleaseContext(providerContext, 0);
                }
                if (algorithmPointer != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(algorithmPointer, typeof(CryptAlgorithmIdentifier));
                    Marshal.FreeHGlobal(algorithmPointer);
                }
            }
        }
        public static byte[] CreateSelfSignedPfx(string subject, DateTime startTime, DateTime endTime, SecureString password)
        {
            if (subject == null)
            {
                throw new ArgumentNullException("Subject is null");
            }

            var startSystemTime = ToSystemTime(startTime);
            var endSystemTime   = ToSystemTime(endTime);
            var containerName   = Guid.NewGuid().ToString();

            var dataHandle       = new GCHandle();
            var providerContext  = IntPtr.Zero;
            var cryptKey         = IntPtr.Zero;
            var certContext      = IntPtr.Zero;
            var certStore        = IntPtr.Zero;
            var storeCertContext = IntPtr.Zero;
            var passwordPtr      = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                Check(NativeMethods.CryptAcquireContextW(out providerContext, containerName, null, ProviderType.RsaAes, 8 /*CRYPT_NEWKEYSET*/));
                Check(NativeMethods.CryptGenKey(providerContext, 1 /*AT_KEYEXCHANGE*/, 0x08000001 /*RSA2048BIT_KEY | CRYPT_EXPORTABLE*/, out cryptKey));

                // errorStringPtr gets a pointer into the middle of the subject string,
                // so subject needs to be pinned until after we've copied the value
                // of errorStringPtr.
                dataHandle = GCHandle.Alloc(subject, GCHandleType.Pinned);
                var nameDataLength = 0;

                if (!NativeMethods.CertStrToNameW(
                        0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
                        dataHandle.AddrOfPinnedObject(),
                        3,          // CERT_X500_NAME_STR = 3
                        IntPtr.Zero,
                        null,
                        ref nameDataLength,
                        out IntPtr errorStringPtr))
                {
                    var error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }

                var subjectData = new byte[nameDataLength];
                if (!NativeMethods.CertStrToNameW(
                        0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
                        dataHandle.AddrOfPinnedObject(),
                        3,          // CERT_X500_NAME_STR = 3
                        IntPtr.Zero,
                        subjectData,
                        ref nameDataLength,
                        out errorStringPtr))
                {
                    var error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }

                dataHandle.Free();

                dataHandle = GCHandle.Alloc(subjectData, GCHandleType.Pinned);
                var subjectBlob = new CryptoApiBlob(subjectData.Length, dataHandle.AddrOfPinnedObject());

                var kpi = new CryptKeyProviderInformation
                {
                    ContainerName = containerName,
                    ProviderType  = ProviderType.RsaAes,
                    KeySpec       = 1 // AT_KEYEXCHANGE
                };

                var ai = new CryptAlgorithmIdentifier
                {
                    pszObjId   = "1.2.840.113549.1.1.13", // SHA512RSA
                    Parameters = IntPtr.Zero
                };

                certContext = NativeMethods.CertCreateSelfSignCertificate(providerContext, ref subjectBlob, 0, ref kpi, ref ai, ref startSystemTime, ref endSystemTime, IntPtr.Zero);
                Check(certContext != IntPtr.Zero);
                dataHandle.Free();

                certStore = NativeMethods.CertOpenStore("Memory" /*sz_CERT_STORE_PROV_MEMORY*/, 0, IntPtr.Zero, 0x2000 /*CERT_STORE_CREATE_NEW_FLAG*/, IntPtr.Zero);
                Check(certStore != IntPtr.Zero);

                Check(NativeMethods.CertAddCertificateContextToStore(certStore, certContext, 1, /*CERT_STORE_ADD_NEW*/ out storeCertContext));
                NativeMethods.CertSetCertificateContextProperty(storeCertContext, 2 /* CERT_KEY_PROV_INFO_PROP_ID */, 0, ref kpi);

                if (password != null)
                {
                    passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password);
                }

                var pfxBlob = new CryptoApiBlob();
                Check(NativeMethods.PFXExportCertStoreEx(certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY

                var pfxData = new byte[pfxBlob.DataLength];
                dataHandle   = GCHandle.Alloc(pfxData, GCHandleType.Pinned);
                pfxBlob.Data = dataHandle.AddrOfPinnedObject();
                Check(NativeMethods.PFXExportCertStoreEx(certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
                dataHandle.Free();

                return(pfxData);
            }
            finally
            {
                if (passwordPtr != IntPtr.Zero)
                {
                    Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr);
                }

                if (dataHandle.IsAllocated)
                {
                    dataHandle.Free();
                }

                if (certContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(certContext);
                }

                if (storeCertContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(storeCertContext);
                }

                if (certStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(certStore, 0);
                }

                if (cryptKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(cryptKey);
                }

                if (providerContext != IntPtr.Zero)
                {
                    NativeMethods.CryptReleaseContext(providerContext, 0);
                    NativeMethods.CryptAcquireContextW(
                        out providerContext,
                        containerName,
                        null,
                        ProviderType.RsaAes,
                        0x10); // CRYPT_DELETEKEYSET
                }
            }
        }
        public static X509Certificate2 GenerateSelfSignedCertificate(string issuerDN, DateTime?startTime = null, DateTime?endTime = null)
        {
            if (issuerDN == null)
            {
                issuerDN = String.Empty;
            }
            var startSystemTime = default(SystemTime);

            if (startTime == null || (DateTime)startTime < DateTime.FromFileTimeUtc(0))
            {
                startTime       = DateTime.FromFileTimeUtc(0);
                startSystemTime = SystemTime.Create((DateTime)startTime);
            }
            if (endTime == null)
            {
                endTime = DateTime.MaxValue;
            }
            var    endSystemTime      = SystemTime.Create((DateTime)endTime);
            string containerName      = Guid.NewGuid().ToString();
            IntPtr providerContext    = IntPtr.Zero;
            IntPtr cryptKey           = IntPtr.Zero;
            IntPtr certificateContext = IntPtr.Zero;
            IntPtr algorithmPointer   = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                providerContext = Externs.CryptAcquireContextW(containerName, null, 1, 0x8);
                cryptKey        = Externs.CryptGenKey(providerContext, 1, 0x8000001);
                CryptoApiBlob    nameBlob    = CryptoApiBlob.Create(issuerDN);
                CryptKeyProvInfo keyProvider = new CryptKeyProvInfo
                {
                    pwszContainerName = containerName,
                    dwProvType        = 1,
                    dwKeySpec         = 1
                };
                CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier
                {
                    pszObjId   = "1.2.840.113549.1.1.13",
                    Parameters = new CryptoApiBlob()
                };
                algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm));
                Marshal.StructureToPtr(algorithm, algorithmPointer, false);
                certificateContext = Externs.CertCreateSelfSignCertificate(providerContext, nameBlob, 0, keyProvider, algorithmPointer,
                                                                           startSystemTime, endSystemTime, IntPtr.Zero);
                return(new X509Certificate2(certificateContext));
            }
            finally
            {
                if (certificateContext != IntPtr.Zero)
                {
                    Externs.CertFreeCertificateContext(certificateContext);
                }
                if (cryptKey != IntPtr.Zero)
                {
                    Externs.CryptDestroyKey(cryptKey);
                }
                if (providerContext != IntPtr.Zero)
                {
                    Externs.CryptReleaseContext(providerContext, 0);
                }
                if (algorithmPointer != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(algorithmPointer, typeof(CryptAlgorithmIdentifier));
                    Marshal.FreeHGlobal(algorithmPointer);
                }
            }
        }