.net调用WIN32 API 读取PKCS12格式数字证书

COPY FROM http://www.cnblogs.com/rainlake/archive/2005/09/15/237997.html

using System;
using System.Runtime.InteropServices;

namespace X509Cert
{

    public class WIN32
    {
        public const uint CRYPT_USER_KEYSET = 0x00001000;
        public const uint CERT_KEY_PROV_INFO_PROP_ID = 0x00000002;
        public const uint CRYPT_DELETEKEYSET   = 0x00000010;

        [DllImport("crypt32.dll", SetLastError=true)]   
        public static extern IntPtr PFXImportCertStore(ref CRYPT_DATA_BLOB pPfx,[MarshalAs(UnmanagedType.LPWStr)] String szPassword,uint dwFlags);

        [DllImport("CRYPT32.DLL", EntryPoint="CertEnumCertificatesInStore", CharSet=CharSet.Auto, SetLastError=true)]
        public static extern IntPtr CertEnumCertificatesInStore( IntPtr storeProvider, IntPtr prevCertContext);

        [DllImport("CRYPT32.DLL",CharSet=CharSet.Auto, SetLastError=true)]
        public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext,uint dwPropId,IntPtr pvData,ref uint pcbData);

        [DllImport("advapi32.dll",EntryPoint="CryptAcquireContext",CharSet=CharSet.Auto, SetLastError=true)]
        public static extern bool CryptAcquireContext(ref IntPtr phProv,string szContainer,string szProvider,uint dwProvType,uint dwFlags);

        [StructLayout(LayoutKind.Sequential)]
        public struct CRYPT_DATA_BLOB {
            public int cbData;
            public IntPtr pbData;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CRYPT_KEY_PROV_INFO {

            [MarshalAs(UnmanagedType.LPWStr)] 
            public String ContainerName;

            [MarshalAs(UnmanagedType.LPWStr)] 
            public String ProvName;

            public uint ProvType;

            public uint Flags;

            public uint ProvParam;

            public IntPtr rgProvParam;

            public uint KeySpec;

        }

        public WIN32()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }
    }
}

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;

namespace X509Cert
{
    /// <summary>
    /// Cert 的摘要说明。
    /// </summary>
    public class Cert
    {
        public Cert()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }
        public static System.Security.Cryptography.X509Certificates.X509Certificate[] Read(string filename,string password) {

            //打开证书文件,并读到一个字节数组中。
            FileStream stream = new FileStream(filename,FileMode.Open);
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer,0,buffer.Length);
            stream.Close();          

            //声明并实例化WIN32.CRYPT_DATA_BLOB 将读取到的字节数组拷贝到它的pbData属性中。将字节数组长度赋给cbData属性
            WIN32.CRYPT_DATA_BLOB cryptdata = new WIN32.CRYPT_DATA_BLOB();
            cryptdata.cbData = buffer.Length;
            cryptdata.pbData = Marshal.AllocHGlobal(cryptdata.cbData);
            Marshal.Copy(buffer,0,cryptdata.pbData,buffer.Length);
            IntPtr hMemStore = WIN32.PFXImportCertStore(ref cryptdata,"1234",WIN32.CRYPT_USER_KEYSET);
            Marshal.FreeHGlobal(cryptdata.pbData);

            uint provinfosize = 0;
            WIN32.CRYPT_KEY_PROV_INFO certinfo = new WIN32.CRYPT_KEY_PROV_INFO();

            System.Collections.ArrayList certs = new System.Collections.ArrayList();

            IntPtr certHandle = IntPtr.Zero;
            while((certHandle = WIN32.CertEnumCertificatesInStore(hMemStore,certHandle)) != IntPtr.Zero) {

                if(WIN32.CertGetCertificateContextProperty(certHandle,WIN32.CERT_KEY_PROV_INFO_PROP_ID,IntPtr.Zero,ref provinfosize)){

                    IntPtr info = Marshal.AllocHGlobal((int)provinfosize);

                    if(WIN32.CertGetCertificateContextProperty(certHandle,WIN32.CERT_KEY_PROV_INFO_PROP_ID,info,ref provinfosize)) {
                        certinfo = (WIN32.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(info,typeof(WIN32.CRYPT_KEY_PROV_INFO));    

                        certs.Add(new X509Certificate(certHandle));
                    }
                    Marshal.FreeHGlobal(info);

                }
            }

            Marshal.FreeHGlobal(hMemStore);

            IntPtr hCryptProv = IntPtr.Zero;
            if(!WIN32.CryptAcquireContext(ref hCryptProv,certinfo.ContainerName,certinfo.ProvName,certinfo.ProvType,WIN32.CRYPT_DELETEKEYSET))
                throw new Exception("释放内存错误");
            return (X509Certificate[])certs.ToArray(typeof(X509Certificate));
     
        }
    }
}

  

posted @ 2011-12-10 23:27  BinSys  阅读(572)  评论(0编辑  收藏  举报