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

        利用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 = "\n" + ToHexString(keys.Modulus) + "";
            pkxml += "\n" + ToHexString(keys.Exponent) + "\n";
            String psxml = "\n" + ToHexString(keys.Modulus) + "";
            psxml += "\n" + ToHexString(keys.Exponent) + "";
            psxml += "\n" + ToHexString(keys.D) + "";
            psxml += "\n" + ToHexString(keys.DP) + "";
            psxml += "\n

" + ToHexString(keys.P) + "

"; psxml += "\n" + ToHexString(keys.Q) + ""; psxml += "\n" + ToHexString(keys.DQ) + ""; psxml += "\n" + ToHexString(keys.InverseQ) + "\n
"; 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加密与解密的基础,以后有时间,多了解!


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




你可能感兴趣的:(C#)