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


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

         我的项目当中,考虑到安全性,需要为每个客户端分发一个数字证书,同时使用数字证书中的公私钥来进行数据的加解密。为了完成这个安全模块,特写了如下一个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.    }  
    
    
    Creative Commons License本文基于Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
  • 相关阅读:
    【转载】常见的Web攻击手段之XSS攻击讲解及实战
    【转载】常见的Web攻击手段之CSRF攻击
    【转载】Ognl表达式基本原理和使用方法(最全最详细附带源码解读)
    linux(centos7)安装jdk8--附带oracle账号
    Vagrant+Secure CRT的使用
    Idea 如何解决项目依赖冲突
    全局唯一iD的生成 雪花算法详解及其他用法
    【转载】什么是java OOM?如何分析及解决oom问题?
    FastJSON的0day漏洞报告
    MySQL/Oracle 添加/查看表注释和字段注释
  • 原文地址:https://www.cnblogs.com/luminji/p/1863179.html
Copyright © 2020-2023  润新知