C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密

Posted 空余恨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密相关的知识,希望对你有一定的参考价值。

我的项目当中,考虑到安全性,需要为每个客户端分发一个数字证书,同时使用数字证书中的公私钥来进行数据的加解密。为了完成这个安全模块,特写了如下一个DEMO程序,该DEMO程序包含的功能有:

1:调用.NET2.0的MAKECERT创建含有私钥的数字证书,并存储到个人证书区;

2:将该证书导出为pfx文件,并为其指定一个用来打开pfx文件的password;

3:读取pfx文件,导出pfx中公钥和私钥;

4:用pfx证书中的公钥进行数据的加密,用私钥进行数据的解密;

 

系统界面:

image

代码如下:

01./// <summary>   
02.        /// 将证书从证书存储区导出,并存储为pfx文件,同时为pfx文件指定打开的密码   
03.        /// 本函数同时也演示如何用公钥进行加密,私钥进行解密   
04.        /// </summary>   
05.        /// <param name="sender"></param>   
06.        /// <param name="e"></param>   
07.        private void btn_toPfxFile_Click(object sender, EventArgs e)   
08.        {   
09.            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);   
10.            store.Open(OpenFlags.ReadWrite);   
11.            X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;   
12.            foreach (X509Certificate2 x509 in storecollection)   
13.            {   
14.                if (x509.Subject == "CN=luminji")   
15.                {   
16.                    Debug.Print(string.Format("certificate name: {0}", x509.Subject));   
17.                    byte[] pfxByte = x509.Export(X509ContentType.Pfx, "123");   
18.                    using (FileStream  fileStream = new FileStream("luminji.pfx", FileMode.Create))   
19.                    {   
20.                        // Write the data to the file, byte by byte.   
21.                        for (int i = 0; i < pfxByte.Length; i++)   
22.                            fileStream.WriteByte(pfxByte[i]);   
23.                        // Set the stream position to the beginning of the file.   
24.                        fileStream.Seek(0, SeekOrigin.Begin);   
25.                        // Read and verify the data.   
26.                        for (int i = 0; i < fileStream.Length; i++)   
27.                        {   
28.                            if (pfxByte[i] != fileStream.ReadByte())   
29.                            {   
30.                                Debug.Print("Error writing data.");   
31.                                return;   
32.                            }   
33.                        }   
34.                        fileStream.Close();   
35.                        Debug.Print("The data was written to {0} " +   
36.                            "and verified.", fileStream.Name);   
37.                    }   
38.                    string myname = "my name is luminji! and i love huzhonghua!";   
39.                    string enStr = this.RSAEncrypt(x509.PublicKey.Key.ToXmlString(false), myname);   
40.                    MessageBox.Show("密文是:" + enStr);   
41.                    string deStr = this.RSADecrypt(x509.PrivateKey.ToXmlString(true), enStr);   
42.                    MessageBox.Show("明文是:" + deStr);   
43.                }   
44.            }   
45.            store.Close();   
46.            store = null;   
47.            storecollection = null;   
48.        }   
49.        /// <summary>   
50.        /// 创建还有私钥的证书   
51.        /// </summary>   
52.        /// <param name="sender"></param>   
53.        /// <param name="e"></param>   
54.        private void btn_createPfx_Click(object sender, EventArgs e)   
55.        {   
56.            string MakeCert = "C:\\\\Program Files\\\\Microsoft Visual Studio 8\\\\SDK\\\\v2.0\\\\Bin\\\\makecert.exe";   
57.            string x509Name = "CN=luminji";   
58.            string param = " -pe -ss my -n \\"" + x509Name + "\\" " ;   
59.            Process p = Process.Start(MakeCert, param);   
60.            p.WaitForExit();   
61.            p.Close();   
62.            MessageBox.Show("over");   
63.        }   
64.        /// <summary>   
65.        /// 从pfx文件读取证书信息   
66.        /// </summary>   
67.        /// <param name="sender"></param>   
68.        /// <param name="e"></param>   
69.        private void btn_readFromPfxFile(object sender, EventArgs e)   
70.        {   
71.            X509Certificate2 pc = new X509Certificate2("luminji.pfx", "123");   
72.            MessageBox.Show("name:" + pc.SubjectName.Name);   
73.            MessageBox.Show("public:" + pc.PublicKey.ToString());   
74.            MessageBox.Show("private:" + pc.PrivateKey.ToString());   
75.            pc = null;   
76.        }   
77.        /// <summary>   
78.        /// RSA解密   
79.        /// </summary>   
80.        /// <param name="xmlPrivateKey"></param>   
81.        /// <param name="m_strDecryptString"></param>   
82.        /// <returns></returns>   
83.        public string RSADecrypt(string xmlPrivateKey, string m_strDecryptString)   
84.        {   
85.            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();   
86.            provider.FromXmlString(xmlPrivateKey);   
87.            byte[] rgb = Convert.FromBase64String(m_strDecryptString);   
88.            byte[] bytes = provider.Decrypt(rgb, false);   
89.            return new UnicodeEncoding().GetString(bytes);   
90.        }   
91.        /// <summary>   
92.        /// RSA加密   
93.        /// </summary>   
94.        /// <param name="xmlPublicKey"></param>   
95.        /// <param name="m_strEncryptString"></param>   
96.        /// <returns></returns>   
97.        public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString)   
98.        {   
99.            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();   
100.            provider.FromXmlString(xmlPublicKey);   
101.            byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString);   
102.            return Convert.ToBase64String(provider.Encrypt(bytes, false));   
103.        }  

 

上文是一个示例程序,一个完整的证书工具类如下:

01.public sealed class DataCertificate   
02.    {  
03.        #region 生成证书   
04.        /// <summary>   
05.        /// 根据指定的证书名和makecert全路径生成证书(包含公钥和私钥,并保存在MY存储区)   
06.        /// </summary>   
07.        /// <param name="subjectName"></param>   
08.        /// <param name="makecertPath"></param>   
09.        /// <returns></returns>   
10.        public static bool CreateCertWithPrivateKey(string subjectName, string makecertPath)   
11.        {   
12.            subjectName = "CN=" + subjectName;   
13.            string param = " -pe -ss my -n \\"" + subjectName + "\\" ";   
14.            try  
15.            {   
16.                Process p = Process.Start(makecertPath, param);   
17.                p.WaitForExit();   
18.                p.Close();   
19.            }   
20.            catch (Exception e)   
21.            {   
22.                LogRecord.putErrorLog(e.ToString(), "DataCerficate.CreateCertWithPrivateKey");   
23.                return false;   
24.            }   
25.            return true;   
26.        }  
27.        #endregion  
28. 
29.        #region 文件导入导出   
30.        /// <summary>   
31.        /// 从WINDOWS证书存储区的个人MY区找到主题为subjectName的证书,   
32.        /// 并导出为pfx文件,同时为其指定一个密码   
33.        /// 并将证书从个人区删除(如果isDelFromstor为true)   
34.        /// </summary>   
35.        /// <param name="subjectName">证书主题,不包含CN=</param>   
36.        /// <param name="pfxFileName">pfx文件名</param>   
37.        /// <param name="password">pfx文件密码</param>   
38.        /// <param name="isDelFromStore">是否从存储区删除</param>   
39.        /// <returns></returns>   
40.        public static bool ExportToPfxFile(string subjectName, string pfxFileName,   
41.            string password, bool isDelFromStore)   
42.        {   
43.            subjectName = "CN=" + subjectName;   
44.            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);   
45.            store.Open(OpenFlags.ReadWrite);   
46.            X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;   
47.            foreach (X509Certificate2 x509 in storecollection)   
48.            {   
49.                if (x509.Subject == subjectName)   
50.                {   
51.                    Debug.Print(string.Format("certificate name: {0}", x509.Subject));   
52.  
53.                    byte[] pfxByte = x509.Export(X509ContentType.Pfx, password);   
54.                    using (FileStream fileStream = new FileStream(pfxFileName, FileMode.Create))   
55.                    {   
56.                        // Write the data to the file, byte by byte.   
57.                        for (int i = 0; i < pfxByte.Length; i++)   
58.                            fileStream.WriteByte(pfxByte[i]);   
59.                        // Set the stream position to the beginning of the file.   
60.                        fileStream.Seek(0, SeekOrigin.Begin);   
61.                        // Read and verify the data.   
62.                        for (int i = 0; i < fileStream.Length; i++)   
63.                        {   
64.                            if (pfxByte[i] != fileStream.ReadByte())   
65.                            {   
66.                                LogRecord.putErrorLog("Export pfx error while verify the pfx file!", "ExportToPfxFile");   
67.                                fileStream.Close();   
68.                                return false;   
69.                            }   
70.                        }   
71.                        fileStream.Close();   
72.                    }   
73.                    if( isDelFromStore == true)   
74.                        store.Remove(x509);   
75.                }   
76.            }   
77.            store.Close();   
78.            store = null;   
79.            storecollection = null;   
80.            return true;   
81.        }   
82.        /// <summary>   
83.        /// 从WINDOWS证书存储区的个人MY区找到主题为subjectName的证书,   
84.        /// 并导出为CER文件(即,只含公钥的)   
85.        /// </summary>   
86.        /// <param name="subjectName"></param>   
87.        /// <param name="cerFileName"></param>   
88.        /// <returns></returns>   
89.        public static bool ExportToCerFile(string subjectName, string cerFileName)   
90.        {   
91.            subjectName = "CN=" + subjectName;   
92.            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);   
93.            store.Open(OpenFlags.ReadWrite);   
94.            X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;   
95.            foreach (X509Certificate2 x509 in storecollection)   
96.            {   
97.                if (x509.Subject == subjectName)   
98.                {   
99.                    Debug.Print(string.Format("certificate name: {0}", x509.Subject));   
100.                    //byte[] pfxByte = x509.Export(X509ContentType.Pfx, password);   
101.                    byte[] cerByte = x509.Export(X509ContentType.Cert);   
102.                    using (FileStream fileStream = new FileStream(cerFileName, FileMode.Create))   
103.                    {   
104.                        // Write the data to the file, byte by byte.   
105.                        for (int i = 0; i < cerByte.Length; i++)   
106.                            fileStream.WriteByte(cerByte[i]);   
107.                        // Set the stream position to the beginning of the file.   
108.                        fileStream.Seek(0, SeekOrigin.Begin);   
109.                        // Read and verify the data.   
110.                        for (int i = 0; i < fileStream.Length; i++)   
111.                        {   
112.                            if (cerByte[i] != fileStream.ReadByte())   
113.                            {   
114.                                LogRecord.putErrorLog("Export CER error while verify the CERT file!", "ExportToCERFile");   
115.                                fileStream.Close();   
116.                                return false;   
117.                            }   
118.                        }   
119.                        fileStream.Close();   
120.                    }   
121.                }   
122.            }   
123.            store.Close();   
124.            store = null;   
125.            storecollection = null;   
126.            return true;   
127.        }  
128.        #endregion  
129. 
130.        #region 从证书中获取信息   
131.        /// <summary>   
132.        /// 根据私钥证书得到证书实体,得到实体后可以根据其公钥和私钥进行加解密   
133.        /// 加解密函数使用DEncrypt的RSACryption类   
134.        /// </summary>   
135.        /// <param name="pfxFileName"></param>   
136.        /// <param name="password"></param>   
137.        /// <returns></returns>   
138.        public static X509Certificate2 GetCertificateFromPfxFile(string pfxFileName,   
139.            string password)   
140.        {   
141.            try  
142.            {   
143.                return new X509Certificate2(pfxFileName, password, X509KeyStorageFlags.Exportable);   
144.            }   
145.            catch (Exception e)   
146.            {   
147.                LogRecord.putErrorLog("get certificate from pfx" + pfxFileName + " error:" + e.ToString(),   
148.                    "GetCertificateFromPfxFile");   
149.                return null;   
150.            }   
151.        }   
152.        /// <summary>   
153.        /// 到存储区获取证书   
154.        /// </summary>   
155.        /// <param name="subjectName"></param>   
156.        /// <returns></returns>   
157.        public static X509Certificate2 GetCertificateFromStore(string subjectName)   
158.        {   
159.            subjectName = "CN=" + subjectName;   
160.            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);   
161.            store.Open(OpenFlags.ReadWrite);   
162.            X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;   
163.            foreach (X509Certificate2 x509 in storecollection)   
164.            {   
165.                if (x509.Subject == subjectName)   
166.                {   
167.                    return x509;   
168.                }   
169.            }   
170.            store.Close();   
171.            store = null;   
172.            storecollection = null;   
173.            return null;   
174.        }   
175.        /// <summary>   
176.        /// 根据公钥证书,返回证书实体   
177.        /// </summary>   
178.        /// <param name="cerPath"></param>   
179.        public static X509Certificate2 GetCertFromCerFile(string cerPath)   
180.        {   
181.            try  
182.            {   
183.                return new X509Certificate2(cerPath);   
184.            }   
185.            catch (Exception e)   
186.            {   
187.                LogRecord.putErrorLog(e.ToString(), "DataCertificate.LoadStudentPublicKey");   
188.                return null;   
189.            }               
190.        }  
191.        #endregion          
192.    }  

以上是关于C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密的主要内容,如果未能解决你的问题,请参考以下文章

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

如何使用 c# 从 pfx 文件中检索证书?

如何从网络解决方案中间和域证书文件为 Azure 网站创建 PFX 证书导出?

将证书导出为 pfx

在 C# 中以编程方式将证书和私钥转换为 .PFX