/// <summary>
        /// can be used to check if the certificate is available in a specific File for CRL.
        /// </summary>
        /// <param name="cert"></param>
        /// <param name="CRLFilePath"></param>
        /// <returns></returns>
        internal bool IsCertificateInCrlFile(X509Certificate2 cert, string CRLFilePath)
        {
            CRLData = File.ReadAllBytes(CRLFilePath);
            if (!CheckCRLMessageSignature(CRLData))
            {
                return(false);
            }

            IntPtr   phCertStore = IntPtr.Zero;
            IntPtr   pvContext   = IntPtr.Zero;
            GCHandle hCrlData    = new GCHandle();
            GCHandle hCryptBlob  = new GCHandle();

            try
            {
                hCrlData = GCHandle.Alloc(CRLData, GCHandleType.Pinned);
                WinCrypt32.CRYPTOAPI_BLOB stCryptBlob;
                stCryptBlob.cbData = CRLData.Length;
                stCryptBlob.pbData = hCrlData.AddrOfPinnedObject();
                hCryptBlob         = GCHandle.Alloc(stCryptBlob, GCHandleType.Pinned);

                if (!WinCrypt32.CryptQueryObject(
                        WinCrypt32.CERT_QUERY_OBJECT_BLOB,
                        hCryptBlob.AddrOfPinnedObject(),
                        WinCrypt32.CERT_QUERY_CONTENT_FLAG_CRL,
                        WinCrypt32.CERT_QUERY_FORMAT_FLAG_BINARY,
                        0,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        ref phCertStore,
                        IntPtr.Zero,
                        ref pvContext
                        ))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                WinCrypt32.CRL_CONTEXT stCrlContext = (WinCrypt32.CRL_CONTEXT)Marshal.PtrToStructure(pvContext, typeof(WinCrypt32.CRL_CONTEXT));
                WinCrypt32.CRL_INFO    stCrlInfo    = (WinCrypt32.CRL_INFO)Marshal.PtrToStructure(stCrlContext.pCrlInfo, typeof(WinCrypt32.CRL_INFO));

                CRLNextUpdate = WinCrypt32.FiletimeToDateTime(stCrlInfo.NextUpdate);
                if (CRLNextUpdate < DateTime.Now)
                {
                    throw new CRLExpection("CRL has expired");
                }

                if (IsCertificateInCrl(cert, stCrlInfo))
                {
                    return(true);
                }
            }
            finally
            {
                if (hCrlData.IsAllocated)
                {
                    hCrlData.Free();
                }
                if (hCryptBlob.IsAllocated)
                {
                    hCryptBlob.Free();
                }
                if (!pvContext.Equals(IntPtr.Zero))
                {
                    WinCrypt32.CertFreeCRLContext(pvContext);
                }
            }

            return(false);
        }
        /// <summary>
        /// Check the signature of the CRL Message
        /// </summary>
        /// <param name="CRLData">CRL as byte array</param>
        /// <returns>true in case of success</returns>
        /// <exception cref="CRLExpection">Returns this exception in case of failure</exception>
        private bool CheckCRLMessageSignature(byte[] CRLData)
        {
            GCHandle pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned);

            //WinCrypt32.CRL_CONTEXT CrlCntxt = (WinCrypt32.CRL_CONTEXT)Marshal.PtrToStructure(CRLContext, typeof(WinCrypt32.CRL_CONTEXT));
            //WinCrypt32.CRL_INFO CrlInfo = (WinCrypt32.CRL_INFO)Marshal.PtrToStructure(CrlCntxt.pCrlInfo, typeof(WinCrypt32.CRL_INFO));
            try
            {
                IntPtr CRLContext = WinCrypt32.CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CRLData, CRLData.Length);

                if (IntPtr.Zero == CRLContext)
                {
                    throw new CRLExpection("Invalid CRL format");
                }
                //CRYPT_DATA_BLOB CRLBlob = new CRYPT_DATA_BLOB();
                //GCHandle pinnedArray = GCHandle.Alloc(CRLData, GCHandleType.Pinned);
                //CRLBlob.pbData = pinnedArray.AddrOfPinnedObject();
                //CRLBlob.cbData = CRLData.Length;
                WinCrypt32.CRYPT_VERIFY_MESSAGE_PARA VerifyParams = new WinCrypt32.CRYPT_VERIFY_MESSAGE_PARA();
                VerifyParams.cbSize = Marshal.SizeOf(VerifyParams);
                VerifyParams.dwMsgAndCertEncodingType = WinCrypt32.MY_TYPE;
                VerifyParams.hCryptProv = IntPtr.Zero;
                VerifyParams.pfnGetSignerCertificate = IntPtr.Zero;
                VerifyParams.pvGetArg = IntPtr.Zero;
                //int cbDecodedMessageBlob = 0;

                //#endif

                IntPtr IssuerCertContext = WinCrypt32.CertCreateCertificateContext(WinCrypt32.MY_TYPE, IssuerCertificate.RawData, IssuerCertificate.RawData.Length);
                bool   result            = WinCrypt32.CryptVerifyCertificateSignatureEx(IntPtr.Zero, WinCrypt32.MY_TYPE,
                                                                                        3, CRLContext, 2, IssuerCertContext, 1, IntPtr.Zero);

                //ref VerifyParams,      // Verify parameters.
                //0,              // Signer index.
                //CRLData,    // Pointer to signed BLOB.
                //CRLData.Length,    // Size of signed BLOB.
                //null,            // Buffer for decoded message.
                //ref cbDecodedMessageBlob,  // Size of buffer.
                //pCertContext.AddrOfPinnedObject()         // Pointer to signer certificate.
                //);
                /*if (!result)*/
                WinCrypt32.CertFreeCRLContext(CRLContext);
                WinCrypt32.CertFreeCertificateContext(IssuerCertContext);
                if (!result)
                {
                    throw new CRLExpection("CRL Signature Error - Error Number " + Marshal.GetLastWin32Error());
                }
                return(result);
            }
            catch (CRLExpection e)
            {
                throw e;
            }
            catch
            {
                return(false);
            }
            finally
            {
                pCertContext.Free();
            }
        }
        /// <summary>
        /// can be used to check if the certificate is available in a specific URL for CRL. A proxy can be optionally used.
        /// </summary>
        /// <param name="cert"></param>
        /// <param name="url"></param>
        /// <param name="proxy"></param>
        /// <returns></returns>
        internal bool IsCertificateInOnlineCRL(X509Certificate2 cert, string url, WebProxy proxy = null)
        {
            if (CRLNextUpdate < DateTime.Now /* is CRLNextupdate expired*/ || CRLDownloadedExpiry < DateTime.Now /*is Downloaded CRL expired*/)//check if locally cached CRL is still valid.
            {
                WebClient wc = new WebClient();
                if (proxy != null)
                {
                    wc.Proxy = proxy;
                }
                CRLData             = wc.DownloadData(url);
                CRLDownloadedExpiry = DateTime.Now.AddHours(1);
            }

            if (!CheckCRLMessageSignature(CRLData))
            {
                return(false);
            }

            IntPtr   phCertStore = IntPtr.Zero;
            IntPtr   pvContext   = IntPtr.Zero;
            GCHandle hCrlData    = new GCHandle();
            GCHandle hCryptBlob  = new GCHandle();

            try
            {
                hCrlData = GCHandle.Alloc(CRLData, GCHandleType.Pinned);
                WinCrypt32.CRYPTOAPI_BLOB stCryptBlob;
                stCryptBlob.cbData = CRLData.Length;
                stCryptBlob.pbData = hCrlData.AddrOfPinnedObject();
                hCryptBlob         = GCHandle.Alloc(stCryptBlob, GCHandleType.Pinned);

                if (!WinCrypt32.CryptQueryObject(
                        WinCrypt32.CERT_QUERY_OBJECT_BLOB,
                        hCryptBlob.AddrOfPinnedObject(),
                        WinCrypt32.CERT_QUERY_CONTENT_FLAG_CRL,
                        WinCrypt32.CERT_QUERY_FORMAT_FLAG_BINARY,
                        0,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        ref phCertStore,
                        IntPtr.Zero,
                        ref pvContext
                        ))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                WinCrypt32.CRL_CONTEXT stCrlContext = (WinCrypt32.CRL_CONTEXT)Marshal.PtrToStructure(pvContext, typeof(WinCrypt32.CRL_CONTEXT));
                WinCrypt32.CRL_INFO    stCrlInfo    = (WinCrypt32.CRL_INFO)Marshal.PtrToStructure(stCrlContext.pCrlInfo, typeof(WinCrypt32.CRL_INFO));

                CRLNextUpdate = WinCrypt32.FiletimeToDateTime(stCrlInfo.NextUpdate);

                if (CRLNextUpdate < DateTime.Now)
                {
                    throw new CRLExpection("CRL has expired");
                }

                if (IsCertificateInCrl(cert, stCrlInfo))
                {
                    return(true);
                }
                else
                {
                    url = GetDeltaCrlUrl(stCrlInfo);
                    if (!string.IsNullOrEmpty(url))
                    {
                        return(IsCertificateInOnlineCRL(cert, url));
                    }
                }
            }
            finally
            {
                if (hCrlData.IsAllocated)
                {
                    hCrlData.Free();
                }
                if (hCryptBlob.IsAllocated)
                {
                    hCryptBlob.Free();
                }
                if (!pvContext.Equals(IntPtr.Zero))
                {
                    WinCrypt32.CertFreeCRLContext(pvContext);
                }
            }

            return(false);
        }