using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Exceptions;
namespace Hotline.Application.Tools
{
///
/// 加密、解密
///
public class RSA
{
///
/// RSA加密
///
/// 原文
/// 公钥
/// 密钥类型XML/PEM
///
public static string RSAEncrypt(string Data, string PublicKeyString, string KeyType)
{
byte[] data = Encoding.GetEncoding("UTF-8").GetBytes(Data);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
switch (KeyType)
{
case "XML":
rsa.FromXmlString(PublicKeyString);
break;
case "PEM":
rsa = RSA_PEM.FromPEM(PublicKeyString);
break;
default:
throw UserFriendlyException.SameMessage("不支持的密钥类型");
}
//加密块最大长度限制,如果加密数据的长度超过 秘钥长度/8-11,会引发长度不正确的异常,所以进行数据的分块加密
int MaxBlockSize = rsa.KeySize / 8 - 11;
//正常长度
if (data.Length <= MaxBlockSize)
{
byte[] hashvalueEcy = rsa.Encrypt(data, false); //加密
return System.Convert.ToBase64String(hashvalueEcy);
}
//长度超过正常值
else
{
using (MemoryStream PlaiStream = new MemoryStream(data))
using (MemoryStream CrypStream = new MemoryStream())
{
Byte[] Buffer = new Byte[MaxBlockSize];
int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize > 0)
{
Byte[] ToEncrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph = rsa.Encrypt(ToEncrypt, false);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
}
return System.Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
}
}
}
///
/// RSA解密
///
/// 密文
/// 私钥
/// 密钥类型XML/PEM
///
public static string RSADecrypt(string Data, string PrivateKeyString, string KeyType)
{
// 把+号,替换回来
Data = Data.Replace("%2B", "+");
// 补全密文
Data = CorrectionCiphertext(Data);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
switch (KeyType)
{
case "XML":
rsa.FromXmlString(PrivateKeyString);
break;
case "PEM":
rsa = RSA_PEM.FromPEM(PrivateKeyString);
break;
default:
throw UserFriendlyException.SameMessage("不支持的密钥类型");
}
int MaxBlockSize = rsa.KeySize / 8; //解密块最大长度限制
//正常解密
if (Data.Length <= MaxBlockSize)
{
byte[] hashvalueDcy = rsa.Decrypt(System.Convert.FromBase64String(Data), false);//解密
return Encoding.GetEncoding("UTF-8").GetString(hashvalueDcy);
}
//分段解密
else
{
using (MemoryStream CrypStream = new MemoryStream(System.Convert.FromBase64String(Data)))
using (MemoryStream PlaiStream = new MemoryStream())
{
Byte[] Buffer = new Byte[MaxBlockSize];
int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize > 0)
{
Byte[] ToDecrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);
Byte[] Plaintext = rsa.Decrypt(ToDecrypt, false);
PlaiStream.Write(Plaintext, 0, Plaintext.Length);
BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
}
string output = Encoding.GetEncoding("UTF-8").GetString(PlaiStream.ToArray());
return output;
}
}
}
///
/// 补全密文
///
/// 密文
/// 秘钥长度
/// 补全后的密文
private static string CorrectionCiphertext(string strCiphertext, int keySize = 1024)
{
int ciphertextLength = keySize / 8;
byte[] data = Convert.FromBase64String(strCiphertext);
var newData = new List(data);
while (newData.Count < ciphertextLength)
{
newData.Insert(0, 0x00);
}
return Convert.ToBase64String(newData.ToArray());
}
}
}