220 lines
7.6 KiB
C#
220 lines
7.6 KiB
C#
using System;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
namespace BF
|
|
{
|
|
/// <summary>
|
|
/// PKCS#1
|
|
/// </summary>
|
|
internal class NetRsaEncrypt
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
/// RSA公钥加密
|
|
/// </summary>
|
|
/// <param name="publickey">公钥</param>
|
|
/// <param name="content">待加密字符串</param>
|
|
/// <returns></returns>
|
|
public static byte[] RsaEncrypt(string content, string publickey)
|
|
{
|
|
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
|
byte[] cipherbytes;
|
|
rsa.ImportParameters(ConvertFromPublicKey(publickey));
|
|
cipherbytes = rsa.Encrypt(Encoding.ASCII.GetBytes(content), true);
|
|
return cipherbytes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// RSA私钥解密
|
|
/// </summary>
|
|
/// <param name="DataToDecrypt">RSA加密后字符串</param>
|
|
/// <param name="privateKey">私钥</param>
|
|
/// <returns>明文</returns>
|
|
public static string RsaDecrypt(byte[] DataToDecrypt, string privateKey)
|
|
{
|
|
string result = "";
|
|
for (int j = 0; j < DataToDecrypt.Length / 128; j++)
|
|
{
|
|
byte[] buf = new byte[128];
|
|
for (int i = 0; i < 128; i++)
|
|
{
|
|
|
|
buf[i] = DataToDecrypt[i + 128 * j];
|
|
}
|
|
result += decrypt(buf, privateKey);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#region 内部方法
|
|
|
|
private static string decrypt(byte[] data, string privateKey)
|
|
{
|
|
string result = "";
|
|
RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey);
|
|
using (var sh = SHA1.Create())
|
|
{
|
|
byte[] source = rsa.Decrypt(data, false);
|
|
char[] asciiChars = new char[Encoding.ASCII.GetCharCount(source, 0, source.Length)];
|
|
Encoding.ASCII.GetChars(source, 0, source.Length, asciiChars, 0);
|
|
result = new string(asciiChars);
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr)
|
|
{
|
|
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(Convert.FromBase64String(pemstr));
|
|
return rsa;
|
|
}
|
|
|
|
private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
|
|
{
|
|
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
|
|
|
|
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
|
|
MemoryStream mem = new MemoryStream(privkey);
|
|
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
|
|
byte bt = 0;
|
|
ushort twobytes = 0;
|
|
int elems = 0;
|
|
try
|
|
{
|
|
twobytes = binr.ReadUInt16();
|
|
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
|
|
binr.ReadByte(); //advance 1 byte
|
|
else if (twobytes == 0x8230)
|
|
binr.ReadInt16(); //advance 2 bytes
|
|
else
|
|
return null;
|
|
|
|
twobytes = binr.ReadUInt16();
|
|
if (twobytes != 0x0102) //version number
|
|
return null;
|
|
bt = binr.ReadByte();
|
|
if (bt != 0x00)
|
|
return null;
|
|
|
|
|
|
//------ all private key components are Integer sequences ----
|
|
elems = GetIntegerSize(binr);
|
|
MODULUS = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
E = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
D = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
P = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
Q = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
DP = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
DQ = binr.ReadBytes(elems);
|
|
|
|
elems = GetIntegerSize(binr);
|
|
IQ = binr.ReadBytes(elems);
|
|
|
|
|
|
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
|
CspParameters CspParameters = new CspParameters();
|
|
CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
|
|
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
|
|
RSAParameters RSAparams = new RSAParameters();
|
|
RSAparams.Modulus = MODULUS;
|
|
RSAparams.Exponent = E;
|
|
RSAparams.D = D;
|
|
RSAparams.P = P;
|
|
RSAparams.Q = Q;
|
|
RSAparams.DP = DP;
|
|
RSAparams.DQ = DQ;
|
|
RSAparams.InverseQ = IQ;
|
|
RSA.ImportParameters(RSAparams);
|
|
return RSA;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
binr.Dispose();
|
|
}
|
|
}
|
|
|
|
private static int GetIntegerSize(BinaryReader binr)
|
|
{
|
|
byte bt = 0;
|
|
byte lowbyte = 0x00;
|
|
byte highbyte = 0x00;
|
|
int count = 0;
|
|
bt = binr.ReadByte();
|
|
if (bt != 0x02) //expect integer
|
|
return 0;
|
|
bt = binr.ReadByte();
|
|
|
|
if (bt == 0x81)
|
|
count = binr.ReadByte(); // data size in next byte
|
|
else
|
|
if (bt == 0x82)
|
|
{
|
|
highbyte = binr.ReadByte(); // data size in next 2 bytes
|
|
lowbyte = binr.ReadByte();
|
|
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
|
|
count = BitConverter.ToInt32(modint, 0);
|
|
}
|
|
else
|
|
{
|
|
count = bt; // we already have the data size
|
|
}
|
|
|
|
while (binr.ReadByte() == 0x00)
|
|
{ //remove high order zeros in data
|
|
count -= 1;
|
|
}
|
|
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
|
|
return count;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 生成的Pem
|
|
private static RSAParameters ConvertFromPublicKey(string pemFileConent)
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(pemFileConent))
|
|
{
|
|
throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
|
|
}
|
|
pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
|
|
byte[] keyData = Convert.FromBase64String(pemFileConent);
|
|
bool keySize1024 = (keyData.Length == 162);
|
|
bool keySize2048 = (keyData.Length == 294);
|
|
if (!(keySize1024 || keySize2048))
|
|
{
|
|
throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
|
|
}
|
|
byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
|
|
byte[] pemPublicExponent = new byte[3];
|
|
Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
|
|
Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
|
|
RSAParameters para = new RSAParameters();
|
|
para.Modulus = pemModulus;
|
|
para.Exponent = pemPublicExponent;
|
|
return para;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |