RSA加密也很复杂,把几位数加密后,变成了很大的字符串(一般为十六进制字符串),当然也可以使用BASE64处理一下,因为加密后的数值,有可能不是可以显示的字符。
主要的加密算法如下:
(1)加密类:网上找来的,能用。。
"
+ ToHexString(keys.P) + "";"+ ToHexString(keys.Q) + "";
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);
}
}
}
实现起来很容易。代码如下:
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加密与解密的基础,以后有时间,多了解!
工程测试源码下载:点击打开链接