本文源程序下载:http://download.csdn.net/source/2444494

我的项目当中,考虑到安全性,需要为每个客户端分发一个数字证书,同时使用数字证书中的公私钥来进行数据的加解密。为了完成这个安全模块,特写了如下一个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. }

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

  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. }

  

C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密的更多相关文章

  1. 使用makecert.exe创建数字证书

    RT makecert.exe不用去找,安装VS2008后,在开始菜单相应的路径找到该命令提示符:Microsoft Visual Studio 2008/Visual Studio Tools/Vi ...

  2. 免费CA数字证书的申请、安装、导入、导出

    http://wenku.baidu.com/link?url=oDUw50eCE5zX8tmg4N3-ddYGLt1U5aJYGEN7rk_z7t6LuMHL3M4oBstYBI_dQ1UnCtcK ...

  3. 数字证书KeyTool使用(第二篇)

    http://my.oschina.net/frankies/blog/344914 J2SDK提供了keytool命令行工具,可以根据指定的参数来创建数字证书.生成的证书或证书库默认保存在命令行当前 ...

  4. Java加密解密与数字证书的操作

    1 keytool命令总结 一.创建数字证书 交互模式 使用默认的密钥库.keystore(文件夹是c: Documents and Settingusername)和算法(DSA) keytool  ...

  5. 【转】Android数字证书

    Android数字证书的作用是非常重要的.Android操作系统每一个应用程序的安装都需要经过这一数字证书的签名. Android手机操作系统作为一款比较流行的开源系统在手机领域占据着举足轻重的地位. ...

  6. JDK 生成数字证书

    JDK(keytool.exe)生成数字证书 2010-11-21 15:52 QUOTE: keytool JAVA是个密钥和证书管理工具.它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数 ...

  7. 【上】安全HTTPS-全面具体解释对称加密,非对称加密,数字签名,数字证书和HTTPS

    一,对称加密 所谓对称加密.就是它们在编码时使用的密钥e和解码时一样d(e=d),我们就将其统称为密钥k. 对称加解密的步骤例如以下: 发送端和接收端首先要共享同样的密钥k(即通信前两方都须要知道相应 ...

  8. android利用数字证书对程序签名

     签名的必要性 1.  防止你已安装的应用被恶意的第三方覆盖或替换掉. 2.  开发者的身份标识,签名可以防止抵赖等事件的发生. 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同 ...

  9. android 利用数字证书对程序签名

    签名的必要性 1.  防止你已安装的应用被恶意的第三方覆盖或替换掉. 2.  开发者的身份标识,签名可以防止抵赖等事件的发生. 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同样 ...

随机推荐

  1. UVa210 Concurrency Simulator (ACM/ICPC World Finals 1991) 双端队列

    Programs executed concurrently on a uniprocessor system appear to be executed at the same time, but ...

  2. WMRouter:美团外卖Android开源路由框架

    WMRouter是一款Android路由框架,基于组件化的设计思路,功能灵活,使用也比较简单. WMRouter最初用于解决美团外卖C端App在业务演进过程中的实际问题,之后逐步推广到了美团其他App ...

  3. 你见过这些JavaScript的陷阱吗?

    一.成员操作符 Number.prototype.testFn=function () { console.log(this<0, this.valueOf()); } var num = -1 ...

  4. 深入理解Python生成器(Generator)

    我们可以通过列表生成式简单直接地创建一个列表,但是受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,而且如果我们仅仅需要访问前面几个元素,那后面绝大多 ...

  5. 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1908  Solved: 678 Description In ...

  6. PHP7新特性 What will be in PHP 7/PHPNG

    本文结合php官网和鸟哥相关文章总结: 官网:http://www.php7.ca/   https://wiki.php.net/phpng PHP7将在2015年10月正式发布,PHP7 ,将会是 ...

  7. java多线程技术之条件变量

    上一篇讲述了并发包下的Lock,Lock可以更好的解决线程同步问题,使之更面向对象,并且ReadWriteLock在处理同步时更强大,那么同样,线程间仅仅互斥是不够的,还需要通信,本篇的内容是基于上篇 ...

  8. 持续集成之Jenkins插件使用(一)- 多个job之间的串并联

    转载自:http://qa.blog.163.com/blog/static/190147002201391661510655/ Jenkins除了开源和免费,还有一个最吸引人的功能之一就是支持插件. ...

  9. SLF4J versions 1.4.0 and later requires log4j 1.2.12 or later 终极解决

    http://blog.sina.com.cn/s/blog_54eb26870100uynj.html 到SLF4J官方网站:http://www.slf4j.org/codes.html#log4 ...

  10. Codeforces Round #254 (Div. 1) A. DZY Loves Physics 智力题

    A. DZY Loves Physics 题目连接: http://codeforces.com/contest/444/problem/A Description DZY loves Physics ...