/// <summary>
        /// Create a certificate
        /// </summary>
        /// <param name="request">A request to generate certificate</param>
        /// <returns>Returns a pointer to the signed certificate</returns>
        internal static unsafe IntPtr CreateSelfSignedCertificatePtr(CertificateGenerationRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (string.IsNullOrWhiteSpace(request.Subject))
            {
                throw new ArgumentException("request.Subject is null");
            }

            NativeMethods.CERT_NAME_BLOB pSubjectIssuerBlob = new NativeMethods.CERT_NAME_BLOB(0, null);

            IntPtr extensionsPtr = IntPtr.Zero;

            var subjectName = request.Subject;
            var extensions  = request.Extensions;

            var parameters = request.Parameters;

            if (parameters == null)
            {
                parameters = new CspParameters()
                {
                    ProviderName     = MS_ENH_RSA_AES_PROV,
                    ProviderType     = PROV_RSA_AES,
                    KeyContainerName = Guid.NewGuid().ToString(),
                    KeyNumber        = (int)KeyNumber.Exchange,
                    Flags            = CspProviderFlags.UseMachineKeyStore
                }
            }
            ;

            var keySize = request.KeySize;

            if (keySize <= 0)
            {
                keySize = MINIMUM_SELF_SIGNED_CERTIFICATE_KEYSIZE;
            }

            var expirationLength = request.ExpirationLength;

            if (expirationLength <= TimeSpan.MinValue)
            {
                expirationLength = TimeSpan.FromDays(365);
            }

            var durationInMinutes = expirationLength.TotalMinutes;

            var signatureAlgo = request.SignatureAlgorithm;

            if (string.IsNullOrWhiteSpace(signatureAlgo))
            {
                signatureAlgo = NativeMethods.OID_RSA_SHA256RSA;
            }

            string container = Guid.NewGuid().ToString();

            try
            {
                uint pcbEncoded = 0;

                if (!NativeMethods.CertStrToName(NativeMethods.X509_ASN_ENCODING, subjectName, NativeMethods.CERT_X500_NAME_STR, IntPtr.Zero, null, ref pcbEncoded, IntPtr.Zero) && pcbEncoded <= 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                byte[] pbEncoded = new byte[pcbEncoded];

                if (!NativeMethods.CertStrToName(NativeMethods.X509_ASN_ENCODING, subjectName, NativeMethods.CERT_X500_NAME_STR, IntPtr.Zero, pbEncoded, ref pcbEncoded, IntPtr.Zero))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                using (new RSACryptoServiceProvider(keySize, parameters))
                {
                    pSubjectIssuerBlob.CopyData(pbEncoded);

                    NativeMethods.CRYPT_KEY_PROV_INFO pKeyProvInfo = new NativeMethods.CRYPT_KEY_PROV_INFO
                    {
                        pwszProvName      = parameters.ProviderName,
                        pwszContainerName = parameters.KeyContainerName,
                        dwProvType        = (uint)parameters.ProviderType,
                        dwFlags           = 0x20, //(uint)parameters.Flags,
                        dwKeySpec         = (uint)parameters.KeyNumber
                    };

                    NativeMethods.CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm = new NativeMethods.CRYPT_ALGORITHM_IDENTIFIER
                    {
                        pszObjId = signatureAlgo
                    };

                    pSignatureAlgorithm.parameters.cbData = 0;
                    pSignatureAlgorithm.parameters.pbData = IntPtr.Zero;

                    NativeMethods.SYSTEM_TIME pStartTime = new NativeMethods.SYSTEM_TIME(DateTime.UtcNow);
                    NativeMethods.SYSTEM_TIME pEndTime   = new NativeMethods.SYSTEM_TIME(DateTime.UtcNow.AddMinutes((double)durationInMinutes));

                    extensionsPtr = CertUtil.ConvertExtensions(extensions)[0];

                    IntPtr handle = NativeMethods.CertCreateSelfSignCertificate(IntPtr.Zero, ref pSubjectIssuerBlob, 0, ref pKeyProvInfo, ref pSignatureAlgorithm, ref pStartTime, ref pEndTime, extensionsPtr);

                    if (handle == IntPtr.Zero)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    return(handle);
                }
            }
            finally
            {
                if (IntPtr.Zero != extensionsPtr)
                {
                    Marshal.FreeHGlobal(extensionsPtr);
                    extensionsPtr = IntPtr.Zero;
                }

                pSubjectIssuerBlob.Dispose();
            }
        }
    }
        /// <summary>
        /// Create a self signed certificate
        /// </summary>
        /// <param name="request">A request to generate certificate</param>
        /// <returns>Returns a self signed certificate</returns>
        public static X509Certificate2 CreateSelfSignedCertificate(CertificateGenerationRequest request)
        {
            var ptr = CreateSelfSignedCertificatePtr(request);

            return(new X509Certificate2(ptr));
        }