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()); } } }