C#实现字符串RSA加密与解密算法

来源:互联网 发布:淘宝怎么开通电子面单 编辑:程序博客网 时间:2024/05/22 11:49

        利用C#的加密库,实现RSA加密算法还是很容易的,因为我只是初步了解这个加密算法,据说是目前非对称加密中比较优秀的加密算法了,如银行什么的都在在RSA1024 RSA2048 RSA4096之类,后面的数字,我想,越大,越复杂,破解也越困难吧。。

        RSA加密也很复杂,把几位数加密后,变成了很大的字符串(一般为十六进制字符串),当然也可以使用BASE64处理一下,因为加密后的数值,有可能不是可以显示的字符。


主要的加密算法如下:

(1)加密类:网上找来的,能用。。

using System;using System.Collections.Generic;using System.Text;using System.Security.Cryptography;using System.IO;using System.Xml;namespace RSA_V1{    class RSAUtil    {        public void CreateRSAKey()        {            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();            RSAParameters keys = rsa.ExportParameters(true);            String pkxml = "<root>\n<Modulus>" + ToHexString(keys.Modulus) + "</Modulus>";            pkxml += "\n<Exponent>" + ToHexString(keys.Exponent) + "</Exponent>\n</root>";            String psxml = "<root>\n<Modulus>" + ToHexString(keys.Modulus) + "</Modulus>";            psxml += "\n<Exponent>" + ToHexString(keys.Exponent) + "</Exponent>";            psxml += "\n<D>" + ToHexString(keys.D) + "</D>";            psxml += "\n<DP>" + ToHexString(keys.DP) + "</DP>";            psxml += "\n<P>" + ToHexString(keys.P) + "</P>";            psxml += "\n<Q>" + ToHexString(keys.Q) + "</Q>";            psxml += "\n<DQ>" + ToHexString(keys.DQ) + "</DQ>";            psxml += "\n<InverseQ>" + ToHexString(keys.InverseQ) + "</InverseQ>\n</root>";            SaveToFile("publickey.xml", pkxml);            SaveToFile("privatekey.xml", psxml);        }        public RSACryptoServiceProvider CreateRSADEEncryptProvider(String privateKeyFile)        {            RSAParameters parameters1;            parameters1 = new RSAParameters();            StreamReader reader1 = new StreamReader(privateKeyFile);            XmlDocument document1 = new XmlDocument();            document1.LoadXml(reader1.ReadToEnd());            XmlElement element1 = (XmlElement)document1.SelectSingleNode("root");            parameters1.Modulus = ReadChild(element1, "Modulus");            parameters1.Exponent = ReadChild(element1, "Exponent");            parameters1.D = ReadChild(element1, "D");            parameters1.DP = ReadChild(element1, "DP");            parameters1.DQ = ReadChild(element1, "DQ");            parameters1.P = ReadChild(element1, "P");            parameters1.Q = ReadChild(element1, "Q");            parameters1.InverseQ = ReadChild(element1, "InverseQ");            CspParameters parameters2 = new CspParameters();            parameters2.Flags = CspProviderFlags.UseMachineKeyStore;            RSACryptoServiceProvider provider1 = new RSACryptoServiceProvider(parameters2);            provider1.ImportParameters(parameters1);            reader1.Close();            return provider1;        }        public RSACryptoServiceProvider CreateRSAEncryptProvider(String publicKeyFile)        {            RSAParameters parameters1;            parameters1 = new RSAParameters();            StreamReader reader1 = new StreamReader(publicKeyFile);            XmlDocument document1 = new XmlDocument();            document1.LoadXml(reader1.ReadToEnd());            XmlElement element1 = (XmlElement)document1.SelectSingleNode("root");            parameters1.Modulus = ReadChild(element1, "Modulus");            parameters1.Exponent = ReadChild(element1, "Exponent");            CspParameters parameters2 = new CspParameters();            parameters2.Flags = CspProviderFlags.UseMachineKeyStore;            RSACryptoServiceProvider provider1 = new RSACryptoServiceProvider(parameters2);            provider1.ImportParameters(parameters1);            reader1.Close();            return provider1;        }        public byte[] ReadChild(XmlElement parent, string name)        {            XmlElement element1 = (XmlElement)parent.SelectSingleNode(name);            return hexToBytes(element1.InnerText);        }        public string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "        {            string hexString = string.Empty;            if (bytes != null)            {                StringBuilder strB = new StringBuilder();                for (int i = 0; i < bytes.Length; i++)                {                    strB.Append(bytes[i].ToString("X2"));                }                hexString = strB.ToString();            }            return hexString;        }        public byte[] hexToBytes(String src)        {            int l = src.Length / 2;            String str;            byte[] ret = new byte[l];            for (int i = 0; i < l; i++)            {                str = src.Substring(i * 2, 2);                ret[i] = Convert.ToByte(str, 16);            }            return ret;        }        public void SaveToFile(String filename, String data)        {            System.IO.StreamWriter sw = System.IO.File.CreateText(filename);            sw.WriteLine(data);            sw.Close();        }        public string EnCrypt(string str)        {            RSACryptoServiceProvider rsaencrype = CreateRSAEncryptProvider("publickey.xml");            String text = str;            byte[] data = new UnicodeEncoding().GetBytes(text);            byte[] endata = rsaencrype.Encrypt(data, true);            return ToHexString(endata);        }        public string DoEncrypt(string hexstr)        {            RSACryptoServiceProvider rsadeencrypt = CreateRSADEEncryptProvider("privatekey.xml");            byte[] miwen = hexToBytes(hexstr);            byte[] dedata = rsadeencrypt.Decrypt(miwen, true);            return System.Text.UnicodeEncoding.Unicode.GetString(dedata);        }    }}


(2)WinForm实现,我不太喜欢控制台的程序,其实有界面的软件才更美观。

实现起来很容易。代码如下:


using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Security.Cryptography;using System.Xml;using System.IO;namespace RSA_V1{    public partial class RSA_Frm : Form    {        RSAUtil rsa = new RSAUtil();        public RSA_Frm()        {            InitializeComponent();        }        private void btn_Encrypt_Click(object sender, EventArgs e)        {            txt_DST.Text = rsa.EnCrypt(txt_SRC.Text);        }        private void btn_Decrypt_Click(object sender, EventArgs e)        {            txt_SRC.Text = rsa.DoEncrypt(txt_DST.Text);        }        private void RSA_Frm_Load(object sender, EventArgs e)        {            New_Key();                  }        private void btn_NewKey_Click(object sender, EventArgs e)        {            New_Key();        }        private void New_Key()        {           rsa.CreateRSAKey();            StreamReader reader1 = new StreamReader("privatekey.xml");            XmlDocument document1 = new XmlDocument();            document1.LoadXml(reader1.ReadToEnd());            XmlElement element1 = (XmlElement)document1.SelectSingleNode("root");            //parameters1.Modulus = ReadChild(element1, "Modulus");            txt_RSA_E.Text = rsa.ToHexString(rsa.ReadChild(element1, "Exponent"));            txt_RSA_D.Text = rsa.ToHexString(rsa.ReadChild(element1, "D"));            txt_RSA_Q.Text = rsa.ToHexString(rsa.ReadChild(element1, "Q"));            txt_RSA_P.Text = rsa.ToHexString(rsa.ReadChild(element1, "P"));            //parameters1.DP = ReadChild(element1, "DP");            //parameters1.DQ = ReadChild(element1, "DQ");            //parameters1.P = ReadChild(element1, "P");            //parameters1.Q = ReadChild(element1, "Q");            //parameters1.InverseQ = ReadChild(element1, "InverseQ");            reader1.Close();        }    }}


运行的效果如下:



            目前只是使用C#自带的功能,如生成密钥对等,还不支持自己定义的密钥对,打算有时间继续完善一下。RSA是大数模运算架起来的,这个倒底安不安全不敢说。

总之,同一个字符串,加密后有N多种的密文,每一个密文,都可以通过私钥得到正确的解密。一把锁,有几把钥匙,这本身不太安全吧。


         我觉得如果研究一下同一字符串 公钥相同的情况下,得到不同的密文,这些密文有什么关系呢?有时间可以先用小的素数进行测试一下。大整数,大素数的模幂运算,是RSA加密与解密的基础,以后有时间,多了解!


工程测试源码下载:点击打开链接




0 0
原创粉丝点击