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

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

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

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