非对称加密(RSA)加密解密实现通信.NET(C#)端工具类(教程)

前一篇文章是JAVA端对文本进行加密、解密,在.Net(CSharp)端和Java加密解密交互的代码如下:
private void button1_Click(object sender, EventArgs e)
{
//加密发送数据
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024);
rsaProvider.FromXmlString(this.textBox3.Text);
//待加密数据
byte[] mainData = UTF8Encoding.UTF8.GetBytes(this.textBox5.Text);
//加密后数据
string encryptData = Convert.ToBase64String(rsaProvider.Encrypt(mainData, false));
WebReference2.MainDataBO service = new WebReference2.MainDataBO(this.textBox1.Text,this.textBox2.Text);
string result = service.sync(encryptData);
//解密接收数据
rsaProvider.FromXmlString(this.textBox4.Text);
//解密后数据
string decryptData = UTF8Encoding.UTF8.GetString(rsaProvider.Decrypt(resultData, false));
MessageBox.Show("返回数据:" + decryptData);
}
加密过程中可能会报出:不正确的长度 的错误。错误的原因是:由于待加密的数据超长所致。.NET Framework中提供的RSA算法规定,待加密的字节数不能超过密钥的长度值除以8再减去11(即:RSACryptoServiceProvider.KeySize/8-11),而加密后
得到密文的字节数,正好是密钥的长度值除以8(即:RSACryptoServiceProvider.KeySize/8)。
解决方法使用分段加密,参考代码如下:
private void button1_Click(object sender, EventArgs e)
{
//加密发送数据
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024);
rsaProvider.FromXmlString(this.textBox3.Text);
//待加密数据
byte[] mainData = UTF8Encoding.UTF8.GetBytes(this.textBox5.Text);
//加密后数据
string encryptData = null;
//分段加密
int encryptBlockSize = rsaProvider.KeySize / 8 - 11;//加密块最大长度限制
if (mainData.Length <= encryptBlockSize)
{
encryptData = Convert.ToBase64String(rsaProvider.Encrypt(mainData, false));
}
else
{
using (MemoryStream mainDataStream = new MemoryStream(mainData))
using (MemoryStream encryptDataStream = new MemoryStream())
{
Byte[] buffer = new Byte[encryptBlockSize];
int blockSize = mainDataStream.Read(buffer, 0, encryptBlockSize);
while (blockSize > 0)
{
Byte[] tempMainData = new Byte[blockSize];
Array.Copy(buffer, 0, tempMainData, 0, blockSize);
Byte[] encryptStr = rsaProvider.Encrypt(tempMainData, false);
encryptDataStream.Write(encryptStr, 0, encryptStr.Length);
blockSize = mainDataStream.Read(buffer, 0, encryptBlockSize);
}
encryptData = Convert.ToBase64String(encryptDataStream.ToArray(), Base64FormattingOptions.None);
}
}
WebReference2.MainDataBO service = new WebReference2.MainDataBO(this.textBox1.Text,this.textBox2.Text);
string result = service.sync(encryptData);
//解密接收数据
rsaProvider.FromXmlString(this.textBox4.Text);
//解密后数据
string decryptData = null;
//分段解密
int dncrypteBlockSize = rsaProvider.KeySize / 8;
byte[] resultData = Convert.FromBase64String(result);
if (resultData.Length <= dncrypteBlockSize)
{
decryptData = UTF8Encoding.UTF8.GetString(rsaProvider.Decrypt(resultData, false));
}
else
{
using (MemoryStream resultDataStream = new MemoryStream(resultData))
using (MemoryStream decryptDataStream = new MemoryStream())
{
Byte[] buffer = new Byte[dncrypteBlockSize];
int blockSize = resultDataStream.Read(buffer, 0, dncrypteBlockSize);
while (blockSize > 0)
{
Byte[] tempResultData = new Byte[blockSize];
Array.Copy(buffer, 0, tempResultData, 0, blockSize);
Byte[] decrypt = rsaProvider.Decrypt(tempResultData, false);
decryptDataStream.Write(decrypt, 0, decrypt.Length);
blockSize = resultDataStream.Read(buffer, 0, dncrypteBlockSize);
}
decryptData = UTF8Encoding.UTF8.GetString(decryptDataStream.ToArray());
}
}
MessageBox.Show("返回数据:" + decryptData);
}
其实当写完这个很复杂的RSA分段加密解密是,你是否会觉得,这种RSA的这种用法是否有问题,不然这么流行的加密解密技术,用起来怎么这么麻烦。看过我之前的一片文章(Java加密解密相关名词(概念)解释),就大概能猜到原因。RSA主要适用于数字签名,加密的内容少,加密级别高。不适合大数据量的加密。做了一个测试,加密数据较大时,速度慢,内存消耗大。因此想要使用RSA加密时请先确认使用场景是否正确。