/* Goal:
* .NET内置的RSA算法太难用, 这里要实现一个自动分段加解密的封装.
*
* Design describe:
* 本着实用的原则, 只提供产生密钥对的方法, 和加解密方法.
*
* Write by:
* WangYiBo, 2008/5/20
*
* Changing record:
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace PublicClassLibrary.Definition
{
public class RSAKeyPair
{
public readonly string PrivateKey;
public readonly string PublicKey;
private RSAKeyPair()
{ }
internal RSAKeyPair(string privateKey, string publicKey)
{
PrivateKey = privateKey;
PublicKey = publicKey;
}
}
static public class RSAEncryption
{
//微软的RSA算法需要填充随机数, 此数值受Encrypt方法中参数fOAEP的影响
const int MinRandomCount_fOAEPIsTure = 11;
const int MinRandomCount_fOAEPIsFalse = 41;
static public RSAKeyPair CreatRSAKey(int dwKeySize)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(dwKeySize);
return new RSAKeyPair(rsa.ToXmlString(true), rsa.ToXmlString(false));
}
static public byte[] RSAEncrypt(this byte[] data, string publicKey, bool fOAEP)
{
#region 因为不同的RSA加密位数会导致不同的buffer大小, 此步推算.
int bfSize = 1, length = publicKey.Length - 67;
int count = 0;
while (length > 1)
{
length >>= 1;
count++;
}
bfSize <<= count;
#endregion
#region 推算每次运算实际可以允许的最大有效数量
int eCount;
if (fOAEP)
{
eCount = bfSize - MinRandomCount_fOAEPIsFalse;
}
else
{
eCount = bfSize - MinRandomCount_fOAEPIsTure;
}
#endregion
#region 分段加密.
int resultBlockCount = (data.Length - 1) / eCount + 1;
byte[] bfBytes;
byte[] oBytes1 = new byte[eCount];
byte[] oBytes2 = new byte[data.Length % eCount];
byte[] result = new byte[resultBlockCount * bfSize];
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(publicKey);
for (int bc = 0; bc < resultBlockCount - 1; bc++)
{
for (int i = 0; i < oBytes1.Length; i++)
{
oBytes1[i] = data[bc * oBytes1.Length + i];
}
bfBytes = rsa.Encrypt(oBytes1, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[bc * bfBytes.Length + j] = bfBytes[j];
}
}
for (int i = 0; i < oBytes2.Length; i++)
{
oBytes2[i] = data[(resultBlockCount - 1) * oBytes1.Length + i];
}
bfBytes = rsa.Encrypt(oBytes2, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[(resultBlockCount - 1) *bfBytes.Length + j] = bfBytes[j];
}
#endregion
return result;
}
static public byte[] RSADecrypt(this byte[] data, string privateKey, bool fOAEP)
{
#region 推算bufferSize
int bfSize = 1, length = (privateKey.Length - 127) / 4;
int count = 0;
while (length > 1)
{
length >>= 1;
count++;
}
bfSize <<= count;
#endregion
#region 分段解密
int resultBlockCount = (data.Length - 1) / bfSize + 1;
byte[] bfBytes;
byte[] oBytes = new byte[bfSize];
byte[] result = new byte[data.Length];
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(privateKey);
int pbfBytesLength = 0;
for (int bc = 0; bc < resultBlockCount; bc++)
{
for (int i = 0; i < oBytes.Length; i++)
{
oBytes[i] = data[bc * oBytes.Length + i];
}
bfBytes = rsa.Decrypt(oBytes, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[pbfBytesLength + j] = bfBytes[j];
}
pbfBytesLength += bfBytes.Length;
}
Array.Resize<byte>(ref result, pbfBytesLength);
#endregion
return result;
}
}
}
* .NET内置的RSA算法太难用, 这里要实现一个自动分段加解密的封装.
*
* Design describe:
* 本着实用的原则, 只提供产生密钥对的方法, 和加解密方法.
*
* Write by:
* WangYiBo, 2008/5/20
*
* Changing record:
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace PublicClassLibrary.Definition
{
public class RSAKeyPair
{
public readonly string PrivateKey;
public readonly string PublicKey;
private RSAKeyPair()
{ }
internal RSAKeyPair(string privateKey, string publicKey)
{
PrivateKey = privateKey;
PublicKey = publicKey;
}
}
static public class RSAEncryption
{
//微软的RSA算法需要填充随机数, 此数值受Encrypt方法中参数fOAEP的影响
const int MinRandomCount_fOAEPIsTure = 11;
const int MinRandomCount_fOAEPIsFalse = 41;
static public RSAKeyPair CreatRSAKey(int dwKeySize)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(dwKeySize);
return new RSAKeyPair(rsa.ToXmlString(true), rsa.ToXmlString(false));
}
static public byte[] RSAEncrypt(this byte[] data, string publicKey, bool fOAEP)
{
#region 因为不同的RSA加密位数会导致不同的buffer大小, 此步推算.
int bfSize = 1, length = publicKey.Length - 67;
int count = 0;
while (length > 1)
{
length >>= 1;
count++;
}
bfSize <<= count;
#endregion
#region 推算每次运算实际可以允许的最大有效数量
int eCount;
if (fOAEP)
{
eCount = bfSize - MinRandomCount_fOAEPIsFalse;
}
else
{
eCount = bfSize - MinRandomCount_fOAEPIsTure;
}
#endregion
#region 分段加密.
int resultBlockCount = (data.Length - 1) / eCount + 1;
byte[] bfBytes;
byte[] oBytes1 = new byte[eCount];
byte[] oBytes2 = new byte[data.Length % eCount];
byte[] result = new byte[resultBlockCount * bfSize];
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(publicKey);
for (int bc = 0; bc < resultBlockCount - 1; bc++)
{
for (int i = 0; i < oBytes1.Length; i++)
{
oBytes1[i] = data[bc * oBytes1.Length + i];
}
bfBytes = rsa.Encrypt(oBytes1, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[bc * bfBytes.Length + j] = bfBytes[j];
}
}
for (int i = 0; i < oBytes2.Length; i++)
{
oBytes2[i] = data[(resultBlockCount - 1) * oBytes1.Length + i];
}
bfBytes = rsa.Encrypt(oBytes2, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[(resultBlockCount - 1) *bfBytes.Length + j] = bfBytes[j];
}
#endregion
return result;
}
static public byte[] RSADecrypt(this byte[] data, string privateKey, bool fOAEP)
{
#region 推算bufferSize
int bfSize = 1, length = (privateKey.Length - 127) / 4;
int count = 0;
while (length > 1)
{
length >>= 1;
count++;
}
bfSize <<= count;
#endregion
#region 分段解密
int resultBlockCount = (data.Length - 1) / bfSize + 1;
byte[] bfBytes;
byte[] oBytes = new byte[bfSize];
byte[] result = new byte[data.Length];
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(privateKey);
int pbfBytesLength = 0;
for (int bc = 0; bc < resultBlockCount; bc++)
{
for (int i = 0; i < oBytes.Length; i++)
{
oBytes[i] = data[bc * oBytes.Length + i];
}
bfBytes = rsa.Decrypt(oBytes, fOAEP);
for (int j = 0; j < bfBytes.Length; j++)
{
result[pbfBytesLength + j] = bfBytes[j];
}
pbfBytesLength += bfBytes.Length;
}
Array.Resize<byte>(ref result, pbfBytesLength);
#endregion
return result;
}
}
}