使用.net讀取PKCS12格式數位憑證

來源:互聯網
上載者:User

隨著《電子簽名法》的頒布,數位憑證應用越來越廣泛,在一般的應用中,我們都是在系統中安裝pkcs12格式的認證。在訪問應用(一般是網頁、電子郵件等)時,選擇合適的認證。我們也可以使用編程來直接讀取認證檔案。下面我們就介紹如何使用.net讀取數位憑證。

 

要讀取pkcs12格式的認證,我們需要調用API,在WIN32類中,我們聲明這些API的引用:

using System;
 2using System.Runtime.InteropServices;
 3
 4namespace X509Cert
 5{
 6
 7    public class WIN32
 8    {
 9        public const uint CRYPT_USER_KEYSET = 0x00001000;
10        public const uint CERT_KEY_PROV_INFO_PROP_ID = 0x00000002;
11        public const uint CRYPT_DeleteKEYSET   = 0x00000010;
12
13        [DllImport("crypt32.dll", SetLastError=true)]  
14        public static extern IntPtr PFXImportCertStore(ref CRYPT_DATA_BLOB pPfx,[MarshalAs(UnmanagedType.LPWStr)] String szPassword,uint dwFlags);
15
16        [DllImport("CRYPT32.DLL", EntryPoint="CertEnumCertificatesInStore", CharSet=CharSet.Auto, SetLastError=true)]
17        public static extern IntPtr CertEnumCertificatesInStore( IntPtr storeProvider, IntPtr prevCertContext);
18
19        [DllImport("CRYPT32.DLL",CharSet=CharSet.Auto, SetLastError=true)]
20        public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext,uint dwPropId,IntPtr pvData,ref uint pcbData);
21
22        [DllImport("advapi32.dll",EntryPoint="CryptAcquireContext",CharSet=CharSet.Auto, SetLastError=true)]
23        public static extern bool CryptAcquireContext(ref IntPtr phProv,string szContainer,string szProvider,uint dwProvType,uint dwFlags);
24
25        [StructLayout(LayoutKind.Sequential)]
26        public struct CRYPT_DATA_BLOB {
27            public int cbData;
28            public IntPtr pbData;
29        }
30
31        [StructLayout(LayoutKind.Sequential)]
32        public struct CRYPT_KEY_PROV_INFO {
33
34            [MarshalAs(UnmanagedType.LPWStr)]
35            public String ContainerName;
36
37            [MarshalAs(UnmanagedType.LPWStr)]
38            public String ProvName;
39
40            public uint ProvType;
41
42            public uint Flags;
43
44            public uint ProvParam;
45
46            public IntPtr rgProvParam;
47
48            public uint KeySpec;
49
50        }
51
52        public WIN32()
53        {
54            //
55            // TODO: 在此處添加建構函式邏輯
56            //
57        }
58    }
59}
60
 

 

然後在Cert類中寫一個Read方法讀取其中的認證。注意:pfx檔案有可能包含幾個認證

 

 

 

 1using System;
 2using System.IO;
 3using System.Runtime.InteropServices;
 4using System.Security.Cryptography.X509Certificates;
 5
 6namespace X509Cert
 7{
 8    /**//// <summary>
 9    /// Cert 的摘要說明。
10    /// </summary>
11    public class Cert
12    {
13        public Cert()
14        {
15            //
16            // TODO: 在此處添加建構函式邏輯
17            //
18        }
19        public static System.Security.Cryptography.X509Certificates.X509Certificate[] Read(string filename,string password) {
20
21            //開啟認證檔案,並讀到一個位元組數組中。
22            FileStream stream = new FileStream(filename,FileMode.Open);
23            byte[] buffer = new byte[stream.Length];
24            stream.Read(buffer,0,buffer.Length);
25            stream.Close();         
26
27            //聲明並執行個體化WIN32.CRYPT_DATA_BLOB 將讀取到的位元組數組拷貝到它的pbData屬性中。將位元組數組長度賦給cbData屬性
28            WIN32.CRYPT_DATA_BLOB cryptdata = new WIN32.CRYPT_DATA_BLOB();
29            cryptdata.cbData = buffer.Length;
30            cryptdata.pbData = Marshal.AllocHGlobal(cryptdata.cbData);
31            Marshal.Copy(buffer,0,cryptdata.pbData,buffer.Length);
32            IntPtr hMemStore = WIN32.PFXImportCertStore(ref cryptdata,"1234",WIN32.CRYPT_USER_KEYSET);
33            Marshal.FreeHGlobal(cryptdata.pbData);
34
35            uint provinfosize = 0;
36            WIN32.CRYPT_KEY_PROV_INFO certinfo = new WIN32.CRYPT_KEY_PROV_INFO();
37
38            System.Collections.ArrayList certs = new System.Collections.ArrayList();
39
40            IntPtr certHandle = IntPtr.Zero;
41            while((certHandle = WIN32.CertEnumCertificatesInStore(hMemStore,certHandle)) != IntPtr.Zero) {
42
43                if(WIN32.CertGetCertificateContextProperty(certHandle,WIN32.CERT_KEY_PROV_INFO_PROP_ID,IntPtr.Zero,ref provinfosize)){
44
45                    IntPtr info = Marshal.AllocHGlobal((int)provinfosize);
46
47                    if(WIN32.CertGetCertificateContextProperty(certHandle,WIN32.CERT_KEY_PROV_INFO_PROP_ID,info,ref provinfosize)) {
48                        certinfo = (WIN32.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(info,typeof(WIN32.CRYPT_KEY_PROV_INFO));   
49
50                        certs.Add(new X509Certificate(certHandle));
51                    }
52                    Marshal.FreeHGlobal(info);
53
54                }
55            }
56
57            Marshal.FreeHGlobal(hMemStore);
58
59            IntPtr hCryptProv = IntPtr.Zero;
60            if(!WIN32.CryptAcquireContext(ref hCryptProv,certinfo.ContainerName,certinfo.ProvName,certinfo.ProvType,WIN32.CRYPT_DeleteKEYSET))
61                throw new Exception("釋放記憶體錯誤");
62            return (X509Certificate[])certs.ToArray(typeof(X509Certificate));
63    
64        }
65    }
66}
67

該文章轉載自德仔工作室:http://www.dezai.cn/Article_Show.asp?ArticleID=20748&ArticlePage=1 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.