您的位置:首页 > 编程语言 > C#

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

2010-10-28 09:55 651 查看
本文源程序下载:http://download.csdn.net/source/2444494

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

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

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

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

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

系统界面:





代码如下:

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.    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: