RSA不对称加密,公钥加密私钥解密,私钥加密公钥解密

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。

 

.NET提供常用的加密算法类,支持RSA的类是RSACryptoServiceProvider(命名空间:System.Security.Cryptography),但只支持公钥加密,私钥解密。RSACryptoServiceProvider类包括:Modulus、Exponent、P、Q、DP、DQ、InverseQ、D等8个属性,其中Modulus和Exponent就是公钥,Modulus和D就是私钥,RSACryptoServiceProvider类提供导出公钥的方法,也提供导出私钥的方法,但导出的私钥包含上面8个属性,显然要用RSACryptoServiceProvider实现私钥加密公钥是不可行的。

    从RSA的原理来看,公钥加密私钥解密和私钥加密公钥解密应该是等价的,在某些情况下,比如共享软件加密,我们需要用私钥加密注册码或注册文件,发给用户,用户用公钥解密注册码或注册文件进行合法性验证。

不对称密钥

.NET Framework 为不对称加密提供了 RSACryptoServiceProvider 和 DSACryptoServiceProvider 类。这些类在您使用默认构造函数创建新实例时创建一个公钥/私钥对。既可以存储不对称密钥以用在多个会话中,也可以只为一个会话生成不对称密钥。公钥可以被广泛地使用,私钥应被严密地保护起来。

每当创建不对称算法类的新实例时,都生成一个公钥/私钥对。创建该类的新实例后,可以用以下两种方法之一提取密钥信息:

两个方法都接受布尔值,该值指示是只返回公钥信息还是同时返回公钥和私钥信息。通过使用 ImportParameters 方法,可以将 RSACryptoServiceProvider 类初始化为 RSAParameters 结构的值。

下面的代码示例创建 RSACryptoServiceProvider 类的一个新实例,创建一个公钥/私钥对,并将公钥信息保存在RSAParameters 结构中

 

[csharp] view plaincopy
 
  1. //Generate a public/private key pair.  
  2. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();  
  3. //Save the public key information to an RSAParameters structure.  
  4. RSAParameters RSAKeyInfo = RSA.ExportParameters(false);  

 

 

一、公钥加密私钥解密

[csharp] view plaincopy
 
  1. /// <summary>  
  2.    /// 公钥加密,私钥解密  
  3.    /// </summary>  
  4.    public class RSAEncryptHelper  
  5.    {  
  6.   
  7.        /// <summary>  
  8.        /// 将字符串使用base64算法加密  
  9.        /// </summary>  
  10.        /// <param name="code_type">编码类型</param>  
  11.        /// <param name="code">待加密的字符串</param>  
  12.        /// <returns>加密后的字符串</returns>        
  13.        public string EncodeBase64(string code_type, string code)  
  14.        {  
  15.            string encode = "";  
  16.            byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code); //将一组字符编码为一个字节序列.  
  17.            try  
  18.            {  
  19.                encode = Convert.ToBase64String(bytes); //将8位无符号整数数组的子集转换为其等效的,以64为基的数字编码的字符串形式.  
  20.            }  
  21.            catch  
  22.            {  
  23.                encode = code;  
  24.            }  
  25.            return encode;  
  26.        }  
  27.   
  28.        /// <summary>  
  29.        /// 将字符串使用base64算法解密  
  30.        /// </summary>  
  31.        /// <param name="code_type">编码类型</param>  
  32.        /// <param name="code">已用base64算法加密的字符串</param>  
  33.        /// <returns>解密后的字符串</returns>  
  34.        public string DecodeBase64(string code_type, string code)  
  35.        {  
  36.   
  37.            string decode = "";  
  38.            byte[] bytes = Convert.FromBase64String(code); //将2进制编码转换为8位无符号整数数组.  
  39.            try  
  40.            {  
  41.                decode = Encoding.GetEncoding(code_type).GetString(bytes); //将指定字节数组中的一个字节序列解码为一个字符串。  
  42.            }  
  43.            catch  
  44.            {  
  45.                decode = code;  
  46.            }  
  47.            return decode;  
  48.        }  
  49.        /// <summary>  
  50.        /// 获取本机的MAC地址  
  51.        /// </summary>  
  52.        /// <returns></returns>  
  53.        public static string GetLocalMac()  
  54.        {  
  55.            string mac = null;  
  56.            ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");  
  57.            ManagementObjectCollection queryCollection = query.Get();  
  58.            foreach (ManagementObject mo in queryCollection)  
  59.            {  
  60.                if (mo["IPEnabled"].ToString() == "True")  
  61.                    mac = mo["MacAddress"].ToString();  
  62.            }  
  63.            return (mac);  
  64.        }  
  65.   
  66.        /// <summary>  
  67.        /// 得到CPU序列号  
  68.        /// </summary>  
  69.        /// <returns></returns>  
  70.        public static string GetCpuID()  
  71.        {  
  72.            try  
  73.            {  
  74.                //获取CPU序列号代码   
  75.                string cpuInfo = "";//cpu序列号   
  76.                ManagementClass mc = new ManagementClass("Win32_Processor");  
  77.                ManagementObjectCollection moc = mc.GetInstances();  
  78.                foreach (ManagementObject mo in moc)  
  79.                {  
  80.                    cpuInfo = mo.Properties["ProcessorId"].Value.ToString();  
  81.                }  
  82.                moc = null;  
  83.                mc = null;  
  84.                return cpuInfo;  
  85.            }  
  86.            catch  
  87.            {  
  88.                return "unknow";  
  89.            }  
  90.            finally  
  91.            {  
  92.            }  
  93.   
  94.        }  
  95.        /// <summary>  
  96.   
  97.        /// 生成公私钥  
  98.   
  99.        /// </summary>  
  100.   
  101.        /// <param name="PrivateKeyPath"></param>  
  102.   
  103.        /// <param name="PublicKeyPath"></param>  
  104.   
  105.        public void RSAKey(string PrivateKeyPath, string PublicKeyPath)  
  106.        {  
  107.   
  108.            try  
  109.            {  
  110.   
  111.                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();  
  112.   
  113.                this.CreatePrivateKeyXML(PrivateKeyPath, provider.ToXmlString(true));  
  114.   
  115.                this.CreatePublicKeyXML(PublicKeyPath, provider.ToXmlString(false));  
  116.   
  117.            }  
  118.   
  119.            catch (Exception exception)  
  120.            {  
  121.   
  122.                throw exception;  
  123.   
  124.            }  
  125.   
  126.        }  
  127.   
  128.        /// <summary>  
  129.   
  130.        /// 对原始数据进行MD5加密  
  131.   
  132.        /// </summary>  
  133.   
  134.        /// <param name="m_strSource">待加密数据</param>  
  135.   
  136.        /// <returns>返回机密后的数据</returns>  
  137.   
  138.        public string GetHash(string m_strSource)  
  139.        {  
  140.   
  141.            HashAlgorithm algorithm = HashAlgorithm.Create("MD5");  
  142.   
  143.            byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(m_strSource);  
  144.   
  145.            byte[] inArray = algorithm.ComputeHash(bytes);  
  146.   
  147.            return Convert.ToBase64String(inArray);  
  148.   
  149.        }  
  150.   
  151.        /// <summary>  
  152.   
  153.        /// RSA加密  
  154.   
  155.        /// </summary>  
  156.   
  157.        /// <param name="xmlPublicKey">公钥</param>  
  158.   
  159.        /// <param name="m_strEncryptString">MD5加密后的数据</param>  
  160.   
  161.        /// <returns>RSA公钥加密后的数据</returns>  
  162.   
  163.        public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString)  
  164.        {  
  165.   
  166.            string str2;  
  167.   
  168.            try  
  169.            {  
  170.   
  171.                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();  
  172.   
  173.                provider.FromXmlString(xmlPublicKey);  
  174.                 
  175.                byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString);  
  176.   
  177.                str2 = Convert.ToBase64String(provider.Encrypt(bytes, false));  
  178.   
  179.            }  
  180.   
  181.            catch (Exception exception)  
  182.            {  
  183.   
  184.                throw exception;  
  185.   
  186.            }  
  187.   
  188.            return str2;  
  189.   
  190.        }  
  191.   
  192.        /// <summary>  
  193.   
  194.        /// RSA解密  
  195.   
  196.        /// </summary>  
  197.   
  198.        /// <param name="xmlPrivateKey">私钥</param>  
  199.   
  200.        /// <param name="m_strDecryptString">待解密的数据</param>  
  201.   
  202.        /// <returns>解密后的结果</returns>  
  203.   
  204.        public string RSADecrypt(string xmlPrivateKey, string m_strDecryptString)  
  205.        {  
  206.   
  207.            string str2;  
  208.   
  209.            try  
  210.            {  
  211.   
  212.                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();  
  213.   
  214.                provider.FromXmlString(xmlPrivateKey);  
  215.   
  216.                byte[] rgb = Convert.FromBase64String(m_strDecryptString);  
  217.   
  218.                byte[] buffer2 = provider.Decrypt(rgb, false);  
  219.   
  220.                str2 = new UnicodeEncoding().GetString(buffer2);  
  221.   
  222.            }  
  223.            catch (Exception exception)  
  224.            {  
  225.   
  226.                throw exception;  
  227.   
  228.            }  
  229.   
  230.            return str2;  
  231.   
  232.        }  
  233.   
  234.        /// <summary>  
  235.   
  236.        /// 对MD5加密后的密文进行签名  
  237.   
  238.        /// </summary>  
  239.   
  240.        /// <param name="p_strKeyPrivate">私钥</param>  
  241.   
  242.        /// <param name="m_strHashbyteSignature">MD5加密后的密文</param>  
  243.   
  244.        /// <returns></returns>  
  245.   
  246.        public string SignatureFormatter(string p_strKeyPrivate, string m_strHashbyteSignature)  
  247.        {  
  248.   
  249.            byte[] rgbHash = Convert.FromBase64String(m_strHashbyteSignature);  
  250.   
  251.            RSACryptoServiceProvider key = new RSACryptoServiceProvider();  
  252.   
  253.            key.FromXmlString(p_strKeyPrivate);  
  254.   
  255.            RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);  
  256.   
  257.            formatter.SetHashAlgorithm("MD5");  
  258.   
  259.            byte[] inArray = formatter.CreateSignature(rgbHash);  
  260.   
  261.            return Convert.ToBase64String(inArray);  
  262.   
  263.        }  
  264.   
  265.        /// <summary>  
  266.   
  267.        /// 签名验证  
  268.   
  269.        /// </summary>  
  270.   
  271.        /// <param name="p_strKeyPublic">公钥</param>  
  272.   
  273.        /// <param name="p_strHashbyteDeformatter">待验证的用户名</param>  
  274.   
  275.        /// <param name="p_strDeformatterData">注册码</param>  
  276.   
  277.        /// <returns></returns>  
  278.   
  279.        public bool SignatureDeformatter(string p_strKeyPublic, string p_strHashbyteDeformatter, string p_strDeformatterData)  
  280.        {  
  281.   
  282.            try  
  283.            {  
  284.   
  285.                byte[] rgbHash = Convert.FromBase64String(p_strHashbyteDeformatter);  
  286.   
  287.                RSACryptoServiceProvider key = new RSACryptoServiceProvider();  
  288.   
  289.                key.FromXmlString(p_strKeyPublic);  
  290.   
  291.                RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);  
  292.   
  293.                deformatter.SetHashAlgorithm("MD5");  
  294.   
  295.                byte[] rgbSignature = Convert.FromBase64String(p_strDeformatterData);  
  296.   
  297.                if (deformatter.VerifySignature(rgbHash, rgbSignature))  
  298.                {  
  299.   
  300.                    return true;  
  301.   
  302.                }  
  303.   
  304.                return false;  
  305.   
  306.            }  
  307.   
  308.            catch  
  309.            {  
  310.   
  311.                return false;  
  312.   
  313.            }  
  314.   
  315.        }  
  316.   
  317.        /// <summary>  
  318.   
  319.        /// 获取硬盘ID  
  320.   
  321.        /// </summary>  
  322.   
  323.        /// <returns>硬盘ID</returns>  
  324.   
  325.        public string GetHardID()  
  326.        {  
  327.   
  328.            string HDInfo = "";  
  329.   
  330.            ManagementClass cimobject1 = new ManagementClass("Win32_DiskDrive");  
  331.   
  332.            ManagementObjectCollection moc1 = cimobject1.GetInstances();  
  333.   
  334.            foreach (ManagementObject mo in moc1)  
  335.            {  
  336.   
  337.                HDInfo = (string)mo.Properties["Model"].Value;  
  338.   
  339.            }  
  340.   
  341.            return HDInfo;  
  342.   
  343.        }  
  344.   
  345.        /// <summary>  
  346.   
  347.        /// 读注册表中指定键的值  
  348.   
  349.        /// </summary>  
  350.   
  351.        /// <param name="key">键名</param>  
  352.   
  353.        /// <returns>返回键值</returns>  
  354.   
  355.        private string ReadReg(string key)  
  356.        {  
  357.   
  358.            string temp = "";  
  359.   
  360.            try  
  361.            {  
  362.   
  363.                RegistryKey myKey = Registry.LocalMachine;  
  364.   
  365.                RegistryKey subKey = myKey.OpenSubKey(@"SOFTWARE/JX/Register");  
  366.   
  367.   
  368.   
  369.                temp = subKey.GetValue(key).ToString();  
  370.   
  371.                subKey.Close();  
  372.   
  373.                myKey.Close();  
  374.   
  375.                return temp;  
  376.   
  377.            }  
  378.   
  379.            catch (Exception)  
  380.            {  
  381.   
  382.                throw;//可能没有此注册项;  
  383.   
  384.            }  
  385.   
  386.   
  387.   
  388.        }  
  389.   
  390.        /// <summary>  
  391.   
  392.        /// 创建注册表中指定的键和值  
  393.   
  394.        /// </summary>  
  395.   
  396.        /// <param name="key">键名</param>  
  397.   
  398.        /// <param name="value">键值</param>  
  399.   
  400.        private void WriteReg(string key, string value)  
  401.        {  
  402.   
  403.            try  
  404.            {  
  405.   
  406.                RegistryKey rootKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE/JX/Register");  
  407.   
  408.                rootKey.SetValue(key, value);  
  409.   
  410.                rootKey.Close();  
  411.   
  412.            }  
  413.   
  414.            catch (Exception)  
  415.            {  
  416.   
  417.                throw;  
  418.   
  419.            }  
  420.   
  421.        }  
  422.   
  423.        /// <summary>  
  424.   
  425.        /// 创建公钥文件  
  426.   
  427.        /// </summary>  
  428.   
  429.        /// <param name="path"></param>  
  430.   
  431.        /// <param name="publickey"></param>  
  432.   
  433.        public void CreatePublicKeyXML(string path, string publickey)  
  434.        {  
  435.   
  436.            try  
  437.            {  
  438.   
  439.                FileStream publickeyxml = new FileStream(path, FileMode.Create);  
  440.   
  441.                StreamWriter sw = new StreamWriter(publickeyxml);  
  442.   
  443.                sw.WriteLine(publickey);  
  444.   
  445.                sw.Close();  
  446.   
  447.                publickeyxml.Close();  
  448.   
  449.            }  
  450.   
  451.            catch  
  452.            {  
  453.   
  454.                throw;  
  455.   
  456.            }  
  457.   
  458.        }  
  459.   
  460.        /// <summary>  
  461.   
  462.        /// 创建私钥文件  
  463.   
  464.        /// </summary>  
  465.   
  466.        /// <param name="path"></param>  
  467.   
  468.        /// <param name="privatekey"></param>  
  469.   
  470.        public void CreatePrivateKeyXML(string path, string privatekey)  
  471.        {  
  472.   
  473.            try  
  474.            {  
  475.   
  476.                FileStream privatekeyxml = new FileStream(path, FileMode.Create);  
  477.   
  478.                StreamWriter sw = new StreamWriter(privatekeyxml);  
  479.   
  480.                sw.WriteLine(privatekey);  
  481.   
  482.                sw.Close();  
  483.   
  484.                privatekeyxml.Close();  
  485.   
  486.            }  
  487.   
  488.            catch  
  489.            {  
  490.   
  491.                throw;  
  492.   
  493.            }  
  494.   
  495.        }  
  496.   
  497.        /// <summary>  
  498.   
  499.        /// 读取公钥  
  500.   
  501.        /// </summary>  
  502.   
  503.        /// <param name="path"></param>  
  504.   
  505.        /// <returns></returns>  
  506.   
  507.        public string ReadPublicKey(string path)  
  508.        {  
  509.   
  510.            StreamReader reader = new StreamReader(path);  
  511.   
  512.            string publickey = reader.ReadToEnd();  
  513.   
  514.            reader.Close();  
  515.   
  516.            return publickey;  
  517.   
  518.        }  
  519.   
  520.        /// <summary>  
  521.   
  522.        /// 读取私钥  
  523.   
  524.        /// </summary>  
  525.   
  526.        /// <param name="path"></param>  
  527.   
  528.        /// <returns></returns>  
  529.   
  530.        public string ReadPrivateKey(string path)  
  531.        {  
  532.   
  533.            StreamReader reader = new StreamReader(path);  
  534.   
  535.            string privatekey = reader.ReadToEnd();  
  536.   
  537.            reader.Close();  
  538.   
  539.            return privatekey;  
  540.   
  541.        }  
  542.   
  543.        /// <summary>  
  544.   
  545.        /// 初始化注册表,程序运行时调用,在调用之前更新公钥xml  
  546.   
  547.        /// </summary>  
  548.   
  549.        /// <param name="path">公钥路径</param>  
  550.   
  551.        public void InitialReg(string path)  
  552.        {  
  553.   
  554.            Registry.LocalMachine.CreateSubKey(@"SOFTWARE/JX/Register");  
  555.   
  556.            Random ra = new Random();  
  557.   
  558.            string publickey = this.ReadPublicKey(path);  
  559.   
  560.            if (Registry.LocalMachine.OpenSubKey(@"SOFTWARE/JX/Register").ValueCount <= 0)  
  561.            {  
  562.   
  563.                this.WriteReg("RegisterRandom", ra.Next(1, 100000).ToString());  
  564.   
  565.                this.WriteReg("RegisterPublicKey", publickey);  
  566.   
  567.            }  
  568.   
  569.            else  
  570.            {  
  571.   
  572.                this.WriteReg("RegisterPublicKey", publickey);  
  573.   
  574.            }  
  575.   
  576.        }   
  577.    }  



 

二、私钥加密公钥解密

 

[csharp] view plaincopy
 
  1. /// <summary>  
  2.    /// 非对称RSA加密类 可以参考  
  3.    /// http://www.cnblogs.com/hhh/archive/2011/06/03/2070692.html  
  4.    /// http://blog.csdn.net/zhilunchen/article/details/2943158  
  5.    /// http://www.cnblogs.com/yyl8781697/archive/2013/04/28/RSA.html  
  6.    /// 若是私匙加密 则需公钥解密  
  7.    /// 反正公钥加密 私匙来解密  
  8.    /// 需要BigInteger类来辅助  
  9.    /// </summary>  
  10.    public static class RSAHelper  
  11.    {  
  12.        /// <summary>  
  13.        /// RSA的容器 可以解密的源字符串长度为 DWKEYSIZE/8-11   
  14.        /// </summary>  
  15.        public const int DWKEYSIZE = 1024;  
  16.   
  17.        /// <summary>  
  18.        /// RSA加密的密匙结构  公钥和私匙  
  19.        /// </summary>  
  20.        //public struct RSAKey  
  21.        //{  
  22.        //    public string PublicKey { get; set; }  
  23.        //    public string PrivateKey { get; set; }  
  24.        //}  
  25.  
  26.        #region 得到RSA的解谜的密匙对  
  27.        /// <summary>  
  28.        /// 得到RSA的解谜的密匙对  
  29.        /// </summary>  
  30.        /// <returns></returns>  
  31.        //public static RSAKey GetRASKey()  
  32.        //{  
  33.        //    RSACryptoServiceProvider.UseMachineKeyStore = true;  
  34.        //    //声明一个指定大小的RSA容器  
  35.        //    RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(DWKEYSIZE);  
  36.        //    //取得RSA容易里的各种参数  
  37.        //    RSAParameters p = rsaProvider.ExportParameters(true);  
  38.   
  39.        //    return new RSAKey()  
  40.        //    {  
  41.        //        PublicKey = ComponentKey(p.Exponent, p.Modulus),  
  42.        //        PrivateKey = ComponentKey(p.D, p.Modulus)  
  43.        //    };  
  44.        //}  
  45.        #endregion  
  46.  
  47.        #region 检查明文的有效性 DWKEYSIZE/8-11 长度之内为有效 中英文都算一个字符  
  48.        /// <summary>  
  49.        /// 检查明文的有效性 DWKEYSIZE/8-11 长度之内为有效 中英文都算一个字符  
  50.        /// </summary>  
  51.        /// <param name="source"></param>  
  52.        /// <returns></returns>  
  53.        public static bool CheckSourceValidate(string source)  
  54.        {  
  55.            return (DWKEYSIZE / 8 - 11) >= source.Length;  
  56.        }  
  57.        #endregion  
  58.  
  59.        #region 组合解析密匙  
  60.        /// <summary>  
  61.        /// 组合成密匙字符串  
  62.        /// </summary>  
  63.        /// <param name="b1"></param>  
  64.        /// <param name="b2"></param>  
  65.        /// <returns></returns>  
  66.        public static string ComponentKey(byte[] b1, byte[] b2)  
  67.        {  
  68.            List<byte> list = new List<byte>();  
  69.            //在前端加上第一个数组的长度值 这样今后可以根据这个值分别取出来两个数组  
  70.            list.Add((byte)b1.Length);  
  71.            list.AddRange(b1);  
  72.            list.AddRange(b2);  
  73.            byte[] b = list.ToArray<byte>();  
  74.            return Convert.ToBase64String(b);  
  75.        }  
  76.   
  77.        /// <summary>  
  78.        /// 解析密匙  
  79.        /// </summary>  
  80.        /// <param name="key">密匙</param>  
  81.        /// <param name="b1">RSA的相应参数1</param>  
  82.        /// <param name="b2">RSA的相应参数2</param>  
  83.        private static void ResolveKey(string key, out byte[] b1, out byte[] b2)  
  84.        {  
  85.            //从base64字符串 解析成原来的字节数组  
  86.            byte[] b = Convert.FromBase64String(key);  
  87.            //初始化参数的数组长度  
  88.            b1 = new byte[b[0]];  
  89.            b2 = new byte[b.Length - b[0] - 1];  
  90.            //将相应位置是值放进相应的数组  
  91.            for (int n = 1, i = 0, j = 0; n < b.Length; n++)  
  92.            {  
  93.                if (n <= b[0])  
  94.                {  
  95.                    b1[i++] = b[n];  
  96.                }  
  97.                else  
  98.                {  
  99.                    b2[j++] = b[n];  
  100.                }  
  101.            }  
  102.        }  
  103.        #endregion  
  104.  
  105.        #region 字符串加密解密 公开方法  
  106.        /// <summary>  
  107.        /// 字符串加密  
  108.        /// </summary>  
  109.        /// <param name="source">源字符串 明文</param>  
  110.        /// <param name="key">密匙</param>  
  111.        /// <returns>加密遇到错误将会返回原字符串</returns>  
  112.        public static string EncryptString(string source, string key)  
  113.        {  
  114.            string encryptString = string.Empty;  
  115.            byte[] d;  
  116.            byte[] n;  
  117.            try  
  118.            {  
  119.                if (!CheckSourceValidate(source))  
  120.                {  
  121.                    throw new Exception("source string too long");  
  122.                }  
  123.                //解析这个密钥  
  124.                ResolveKey(key, out d, out n);  
  125.                BigInteger biN = new BigInteger(n);  
  126.                BigInteger biD = new BigInteger(d);  
  127.                encryptString = EncryptString(source, biD, biN);  
  128.            }  
  129.            catch  
  130.            {  
  131.                encryptString = source;  
  132.            }  
  133.            return encryptString;  
  134.        }  
  135.   
  136.        /// <summary>  
  137.        /// 字符串解密  
  138.        /// </summary>  
  139.        /// <param name="encryptString">密文</param>  
  140.        /// <param name="key">密钥</param>  
  141.        /// <returns>遇到解密失败将会返回空字符串</returns>  
  142.        public static string DecryptString(string encryptString, string key)  
  143.        {  
  144.            string source = string.Empty;  
  145.            byte[] e;  
  146.            byte[] n;  
  147.            try  
  148.            {  
  149.                //解析这个密钥  
  150.                ResolveKey(key, out e, out n);  
  151.                BigInteger biE = new BigInteger(e);  
  152.                BigInteger biN = new BigInteger(n);  
  153.                source = DecryptString(encryptString, biE, biN);  
  154.            }  
  155.            catch  
  156.            {  
  157.            }  
  158.            return source;  
  159.        }  
  160.        #endregion  
  161.  
  162.        #region 字符串加密解密 私有  实现加解密的实现方法  
  163.        /// <summary>  
  164.        /// 用指定的密匙加密   
  165.        /// </summary>  
  166.        /// <param name="source">明文</param>  
  167.        /// <param name="d">可以是RSACryptoServiceProvider生成的D</param>  
  168.        /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>  
  169.        /// <returns>返回密文</returns>  
  170.        private static string EncryptString(string source, BigInteger d, BigInteger n)  
  171.        {  
  172.            int len = source.Length;  
  173.            int len1 = 0;  
  174.            int blockLen = 0;  
  175.            if ((len % 128) == 0)  
  176.                len1 = len / 128;  
  177.            else  
  178.                len1 = len / 128 + 1;  
  179.            string block = "";  
  180.            StringBuilder result = new StringBuilder();  
  181.            for (int i = 0; i < len1; i++)  
  182.            {  
  183.                if (len >= 128)  
  184.                    blockLen = 128;  
  185.                else  
  186.                    blockLen = len;  
  187.                block = source.Substring(i * 128, blockLen);  
  188.                byte[] oText = System.Text.Encoding.Default.GetBytes(block);  
  189.                BigInteger biText = new BigInteger(oText);  
  190.                BigInteger biEnText = biText.modPow(d, n);  
  191.                string temp = biEnText.ToHexString();  
  192.                result.Append(temp).Append("@");  
  193.                len -= blockLen;  
  194.            }  
  195.            return result.ToString().TrimEnd('@');  
  196.        }  
  197.   
  198.        /// <summary>  
  199.        /// 用指定的密匙加密   
  200.        /// </summary>  
  201.        /// <param name="source">密文</param>  
  202.        /// <param name="e">可以是RSACryptoServiceProvider生成的Exponent</param>  
  203.        /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>  
  204.        /// <returns>返回明文</returns>  
  205.        private static string DecryptString(string encryptString, BigInteger e, BigInteger n)  
  206.        {  
  207.            StringBuilder result = new StringBuilder();  
  208.            string[] strarr1 = encryptString.Split(new char[] { '@' }, StringSplitOptions.RemoveEmptyEntries);  
  209.            for (int i = 0; i < strarr1.Length; i++)  
  210.            {  
  211.                string block = strarr1[i];  
  212.                BigInteger biText = new BigInteger(block, 16);  
  213.                BigInteger biEnText = biText.modPow(e, n);  
  214.                string temp = System.Text.Encoding.Default.GetString(biEnText.getBytes());  
  215.                result.Append(temp);  
  216.            }  
  217.            return result.ToString();  
  218.        }  
  219.        #endregion  
  220.   
  221.   
  222.        /// <summary>  
  223.        /// 将字符串使用base64算法加密  
  224.        /// </summary>  
  225.        /// <param name="code_type">编码类型</param>  
  226.        /// <param name="code">待加密的字符串</param>  
  227.        /// <returns>加密后的字符串</returns>        
  228.        public static string EncodeBase64(string code_type, string code)  
  229.        {  
  230.            string encode = "";  
  231.            byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code); //将一组字符编码为一个字节序列.  
  232.            try  
  233.            {  
  234.                encode = Convert.ToBase64String(bytes); //将8位无符号整数数组的子集转换为其等效的,以64为基的数字编码的字符串形式.  
  235.            }  
  236.            catch  
  237.            {  
  238.                encode = code;  
  239.            }  
  240.            return encode;  
  241.        }  
  242.   
  243.        /// <summary>  
  244.        /// 将字符串使用base64算法解密  
  245.        /// </summary>  
  246.        /// <param name="code_type">编码类型</param>  
  247.        /// <param name="code">已用base64算法加密的字符串</param>  
  248.        /// <returns>解密后的字符串</returns>  
  249.        public static string DecodeBase64(string code_type, string code)  
  250.        {  
  251.   
  252.            string decode = "";  
  253.            byte[] bytes = Convert.FromBase64String(code); //将2进制编码转换为8位无符号整数数组.  
  254.            try  
  255.            {  
  256.                decode = Encoding.GetEncoding(code_type).GetString(bytes); //将指定字节数组中的一个字节序列解码为一个字符串。  
  257.            }  
  258.            catch  
  259.            {  
  260.                decode = code;  
  261.            }  
  262.            return decode;  
  263.        }  
  264.          
  265.        /// <summary>  
  266.        /// 读取公钥或私钥  
  267.        /// </summary>  
  268.        /// <param name="includePrivateparameters">为True则包含私钥</param>  
  269.        /// <param name="path">Xml格式保存的完整公/私钥路径</param>  
  270.        /// <returns>公钥或私钥参数形式 </returns>  
  271.        public static RSAParameters ReadKey(bool includePrivateparameters,string path)  
  272.        {  
  273.            using (StreamReader reader = new StreamReader(path))  
  274.            {  
  275.                string publickey = reader.ReadToEnd();  
  276.                RSACryptoServiceProvider rcp = new RSACryptoServiceProvider();  
  277.                rcp.FromXmlString(publickey);  
  278.                return rcp.ExportParameters(includePrivateparameters);  
  279.            }  
  280.        }  
  281.   
  282.        /// <summary>  
  283.        /// 获取本机的MAC地址  
  284.        /// </summary>  
  285.        /// <returns></returns>  
  286.        public static string GetLocalMac()  
  287.        {  
  288.            string mac = null;  
  289.            ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");  
  290.            ManagementObjectCollection queryCollection = query.Get();  
  291.            foreach (ManagementObject mo in queryCollection)  
  292.            {  
  293.                if (mo["IPEnabled"].ToString() == "True")  
  294.                    mac = mo["MacAddress"].ToString();  
  295.            }  
  296.            return (mac);  
  297.        }  
  298.   
  299.        /// <summary>  
  300.        /// 得到CPU序列号  
  301.        /// </summary>  
  302.        /// <returns></returns>  
  303.        public static string GetCpuID()  
  304.        {  
  305.            try  
  306.            {  
  307.                //获取CPU序列号代码   
  308.                string cpuInfo = "";//cpu序列号   
  309.                ManagementClass mc = new ManagementClass("Win32_Processor");  
  310.                ManagementObjectCollection moc = mc.GetInstances();  
  311.                foreach (ManagementObject mo in moc)  
  312.                {  
  313.                    cpuInfo = mo.Properties["ProcessorId"].Value.ToString();  
  314.                }  
  315.                moc = null;  
  316.                mc = null;  
  317.                return cpuInfo;  
  318.            }  
  319.            catch  
  320.            {  
  321.                return "unknow";  
  322.            }  
  323.            finally  
  324.            {  
  325.            }  
  326.   
  327.        }  
  328.   
  329.        /// <summary>  
  330.   
  331.        /// 获取硬盘ID  
  332.   
  333.        /// </summary>  
  334.   
  335.        /// <returns>硬盘ID</returns>  
  336.   
  337.        public static string GetHardID()  
  338.        {  
  339.   
  340.            string HDInfo = "";  
  341.   
  342.            ManagementClass cimobject1 = new ManagementClass("Win32_DiskDrive");  
  343.   
  344.            ManagementObjectCollection moc1 = cimobject1.GetInstances();  
  345.   
  346.            foreach (ManagementObject mo in moc1)  
  347.            {  
  348.   
  349.                HDInfo = (string)mo.Properties["Model"].Value;  
  350.   
  351.            }  
  352.   
  353.            return HDInfo;  
  354.   
  355.        }  
  356.   
  357.        /// <summary>  
  358.   
  359.        /// 读注册表中指定键的值  
  360.   
  361.        /// </summary>  
  362.   
  363.        /// <param name="key">键名</param>  
  364.   
  365.        /// <returns>返回键值</returns>  
  366.   
  367.        private static string ReadReg(string key)  
  368.        {  
  369.   
  370.            string temp = "";  
  371.   
  372.            try  
  373.            {  
  374.   
  375.                RegistryKey myKey = Registry.LocalMachine;  
  376.   
  377.                RegistryKey subKey = myKey.OpenSubKey(@"SOFTWARE/JX/Register");  
  378.   
  379.   
  380.   
  381.                temp = subKey.GetValue(key).ToString();  
  382.   
  383.                subKey.Close();  
  384.   
  385.                myKey.Close();  
  386.   
  387.                return temp;  
  388.   
  389.            }  
  390.   
  391.            catch (Exception)  
  392.            {  
  393.   
  394.                throw;//可能没有此注册项;  
  395.   
  396.            }  
  397.        }  
  398.   
  399.        /// <summary>  
  400.   
  401.        /// 创建注册表中指定的键和值  
  402.   
  403.        /// </summary>  
  404.   
  405.        /// <param name="key">键名</param>  
  406.   
  407.        /// <param name="value">键值</param>  
  408.   
  409.        private static void WriteReg(string key, string value)  
  410.        {  
  411.            try  
  412.            {  
  413.   
  414.                RegistryKey rootKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE/JX/Register");  
  415.   
  416.                rootKey.SetValue(key, value);  
  417.   
  418.                rootKey.Close();  
  419.   
  420.            }  
  421.   
  422.            catch (Exception)  
  423.            {  
  424.   
  425.                throw;  
  426.   
  427.            }  
  428.   
  429.        }  
  430.   
  431.         
  432.    }  



 

 

使用场景:如共享软件加密,我们需要用私钥加密注册码或注册文件,发给用户,用户用公钥解密注册码或注册文件进行合法性验证。

RSA算法实现激活码注册方式的原理如下:

1. 生成一对公钥E和私钥D(供软件注册模板和注册机使用);

2. 用户安装软件后,软件注册模板提取用户机器指纹信息(如:MAC地址、CPU序列号、硬盘序列号等),并通过其它的编码算法(如BASE64)生成一个申请码C;

3. 用户将申请码C发给软件开发商。软件开发商通过注册机采用私钥D加密申请码C后生成激活码F。软件供应商将激活码F发给用户。

4. 用户输入激活码F,软件注册模板采用公钥E对激活码F解码后生成G(即:用户机器特征信息),然后软件注册模板提取用户机器的特定信息后进行编码。将编码的结果与G进行比较,如果相等则用户合法,完成授权,否则授权失败。

 

[csharp] view plaincopy
 
  1. //应用程序注册模块  
  2.    public partial class Form1 : Form  
  3.    {  
  4.         
  5.        public Form1()  
  6.        {  
  7.            InitializeComponent();  
  8.        }  
  9.   
  10.        private void Form1_Load(object sender, EventArgs e)  
  11.        {  
  12.            string cpu = RSAHelper.GetCpuID();  
  13.            string _申请码C = RSAHelper.EncodeBase64("utf-8", cpu);  
  14.            textEdit申请码.Text = _申请码C;  
  15.        }  
  16.   
  17.        private void simpleButton注册_Click(object sender, EventArgs e)  
  18.        {  
  19.            string publicKeyPath = @"C://PublicKey.xml";  
  20.            RSAParameters pm = RSAHelper.ReadKey(false, publicKeyPath);  
  21.   
  22.            string _PublicKey = RSAHelper.ComponentKey(pm.Exponent, pm.Modulus);  
  23.   
  24.            string cpu = RSAHelper.DecryptString(textEdit激活码.Text, _PublicKey);  
  25.            if (cpu == textEdit申请码.Text)  
  26.            {  
  27.                MessageBox.Show("注册成功");  
  28.            }  
  29.            else  
  30.            {  
  31.                MessageBox.Show("注册失败");  
  32.            }  
  33.        }  
  34.    }  

 

[csharp] view plaincopy
 
  1. /// <summary>  
  2.    /// 注册机  
  3.    /// </summary>  
  4.    public partial class Form1 : Form  
  5.    {  
  6.        public Form1()  
  7.        {  
  8.            InitializeComponent();  
  9.        }  
  10.        
  11.        private void simpleButton生成激活码_Click(object sender, EventArgs e)  
  12.        {  
  13.            string privateKeyPath = @"C://PrivateKey.xml";  
  14.            RSAParameters pm = RSAHelper.ReadKey(true, privateKeyPath);  
  15.            string _PrivateKey = RSAHelper.ComponentKey(pm.D, pm.Modulus);  
  16.            textEdit激活码.Text = RSAHelper.EncryptString(textEdit申请码.Text, _PrivateKey);  
  17.        }  
  18.    }  



 

 

 

 

 

 
posted @ 2015-09-07 20:37  星火卓越  阅读(1743)  评论(0编辑  收藏  举报