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

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

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

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

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

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

代码如下:

  1. /// <summary>  
  2.         /// 将证书从证书存储区导出,并存储为pfx文件,同时为pfx文件指定打开的密码  
  3.         /// 本函数同时也演示如何用公钥进行加密,私钥进行解密  
  4.         /// </summary>  
  5.         /// <param name="sender"></param>  
  6.         /// <param name="e"></param>  
  7.         private void btn_toPfxFile_Click(object sender, EventArgs e)  
  8.         {  
  9.             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.         }  
/// <summary> /// 将证书从证书存储区导出,并存储为pfx文件,同时为pfx文件指定打开的密码 /// 本函数同时也演示如何用公钥进行加密,私钥进行解密 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_toPfxFile_Click(object sender, EventArgs e) { X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates; foreach (X509Certificate2 x509 in storecollection) { if (x509.Subject == "CN=luminji") { Debug.Print(string.Format("certificate name: {0}", x509.Subject)); byte[] pfxByte = x509.Export(X509ContentType.Pfx, "123"); using (FileStream fileStream = new FileStream("luminji.pfx", FileMode.Create)) { // Write the data to the file, byte by byte. for (int i = 0; i < pfxByte.Length; i++) fileStream.WriteByte(pfxByte[i]); // Set the stream position to the beginning of the file. fileStream.Seek(0, SeekOrigin.Begin); // Read and verify the data. for (int i = 0; i < fileStream.Length; i++) { if (pfxByte[i] != fileStream.ReadByte()) { Debug.Print("Error writing data."); return; } } fileStream.Close(); Debug.Print("The data was written to {0} " + "and verified.", fileStream.Name); } string myname = "my name is luminji! and i love huzhonghua!"; string enStr = this.RSAEncrypt(x509.PublicKey.Key.ToXmlString(false), myname); MessageBox.Show("密文是:" + enStr); string deStr = this.RSADecrypt(x509.PrivateKey.ToXmlString(true), enStr); MessageBox.Show("明文是:" + deStr); } } store.Close(); store = null; storecollection = null; } /// <summary> /// 创建还有私钥的证书 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_createPfx_Click(object sender, EventArgs e) { string MakeCert = "C:\\Program Files\\Microsoft Visual Studio 8\\SDK\\v2.0\\Bin\\makecert.exe"; string x509Name = "CN=luminji"; string param = " -pe -ss my -n \"" + x509Name + "\" " ; Process p = Process.Start(MakeCert, param); p.WaitForExit(); p.Close(); MessageBox.Show("over"); } /// <summary> /// 从pfx文件读取证书信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_readFromPfxFile(object sender, EventArgs e) { X509Certificate2 pc = new X509Certificate2("luminji.pfx", "123"); MessageBox.Show("name:" + pc.SubjectName.Name); MessageBox.Show("public:" + pc.PublicKey.ToString()); MessageBox.Show("private:" + pc.PrivateKey.ToString()); pc = null; } /// <summary> /// RSA解密 /// </summary> /// <param name="xmlPrivateKey"></param> /// <param name="m_strDecryptString"></param> /// <returns></returns> public string RSADecrypt(string xmlPrivateKey, string m_strDecryptString) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPrivateKey); byte[] rgb = Convert.FromBase64String(m_strDecryptString); byte[] bytes = provider.Decrypt(rgb, false); return new UnicodeEncoding().GetString(bytes); } /// <summary> /// RSA加密 /// </summary> /// <param name="xmlPublicKey"></param> /// <param name="m_strEncryptString"></param> /// <returns></returns> public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPublicKey); byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString); return Convert.ToBase64String(provider.Encrypt(bytes, false)); }

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

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. public sealed class DataCertificate  
  2.     {  
  3.         #region 生成证书  
  4.         /// <summary>  
  5.         /// 根据指定的证书名和makecert全路径生成证书(包含公钥和私钥,并保存在MY存储区)  
  6.         /// </summary>  
  7.         /// <param name="subjectName"></param>  
  8.         /// <param name="makecertPath"></param>  
  9.         /// <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.     } 
转自:http://blog.csdn.net/luminji/archive/2009/03/05/3960308.aspx

转载于:https://www.cnblogs.com/Deckard/archive/2009/12/03/1616080.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值