123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- 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
- {
- /// <summary>
- /// 加密、解密
- /// </summary>
- public class RSA
- {
- /// <summary>
- /// RSA加密
- /// </summary>
- /// <param name="Data">原文</param>
- /// <param name="PublicKeyString">公钥</param>
- /// <param name="KeyType">密钥类型XML/PEM</param>
- /// <returns></returns>
- 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);
- }
- }
- }
- /// <summary>
- /// RSA解密
- /// </summary>
- /// <param name="Data">密文</param>
- /// <param name="PrivateKeyString">私钥</param>
- /// <param name="KeyType">密钥类型XML/PEM</param>
- /// <returns></returns>
- 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;
- }
- }
- }
- /// <summary>
- /// 补全密文
- /// </summary>
- /// <param name="strCiphertext">密文</param>
- /// <param name="keySize">秘钥长度</param>
- /// <returns>补全后的密文</returns>
- private static string CorrectionCiphertext(string strCiphertext, int keySize = 1024)
- {
- int ciphertextLength = keySize / 8;
- byte[] data = Convert.FromBase64String(strCiphertext);
- var newData = new List<byte>(data);
- while (newData.Count < ciphertextLength)
- {
- newData.Insert(0, 0x00);
- }
- return Convert.ToBase64String(newData.ToArray());
- }
- }
- }
|