123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- using Masuit.Tools.Systems;
- using System;
- using System.Security.Cryptography;
- using System.Text;
- namespace Masuit.Tools.Security;
- /// <summary>
- /// RSA操作类
- /// </summary>
- internal class RSA
- {
- /// <summary>
- /// 导出XML格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
- /// </summary>
- public string ToXML(bool convertToPublic = false)
- {
- return RSAObject.ToXmlString(!RSAObject.PublicOnly && !convertToPublic);
- }
- /// <summary>
- /// 导出PEM PKCS#1格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
- /// </summary>
- public string ToPEM_PKCS1(bool convertToPublic = false)
- {
- return new RsaPem(RSAObject).ToPEM(convertToPublic, false);
- }
- /// <summary>
- /// 导出PEM PKCS#8格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
- /// </summary>
- public string ToPEM_PKCS8(bool convertToPublic = false)
- {
- return new RsaPem(RSAObject).ToPEM(convertToPublic, true);
- }
- /// <summary>
- /// 将密钥对导出成PEM对象,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
- /// </summary>
- public RsaPem ToPEM(bool convertToPublic = false)
- {
- return new RsaPem(RSAObject, convertToPublic);
- }
- /// <summary>
- /// 加密字符串(utf-8),出错抛异常
- /// </summary>
- public string Encrypt(string str)
- {
- return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(str)));
- }
- /// <summary>
- /// 加密数据,出错抛异常
- /// </summary>
- public byte[] Encrypt(byte[] data)
- {
- int blockLen = RSAObject.KeySize / 8 - 11;
- if (data.Length <= blockLen)
- {
- return RSAObject.Encrypt(data, false);
- }
- using var dataStream = new PooledMemoryStream(data);
- using var enStream = new PooledMemoryStream();
- var buffer = new byte[blockLen];
- int len = dataStream.Read(buffer, 0, blockLen);
- while (len > 0)
- {
- var block = new byte[len];
- Array.Copy(buffer, 0, block, 0, len);
- var enBlock = RSAObject.Encrypt(block, false);
- enStream.Write(enBlock, 0, enBlock.Length);
- len = dataStream.Read(buffer, 0, blockLen);
- }
- return enStream.ToArray();
- }
- /// <summary>
- /// 解密字符串(utf-8),解密异常返回null
- /// </summary>
- public string DecryptOrNull(string str)
- {
- if (string.IsNullOrEmpty(str))
- {
- return null;
- }
- try
- {
- var bytes = Convert.FromBase64String(str);
- var val = DecryptOrNull(bytes);
- return val == null ? null : Encoding.UTF8.GetString(val);
- }
- catch
- {
- return null;
- }
- }
- /// <summary>
- /// 解密数据,解密异常返回null
- /// </summary>
- public byte[] DecryptOrNull(byte[] data)
- {
- try
- {
- int blockLen = RSAObject.KeySize / 8;
- if (data.Length <= blockLen)
- {
- return RSAObject.Decrypt(data, false);
- }
- using var dataStream = new PooledMemoryStream(data);
- using var deStream = new PooledMemoryStream();
- byte[] buffer = new byte[blockLen];
- int len = dataStream.Read(buffer, 0, blockLen);
- while (len > 0)
- {
- var block = new byte[len];
- Array.Copy(buffer, 0, block, 0, len);
- var deBlock = RSAObject.Decrypt(block, false);
- deStream.Write(deBlock, 0, deBlock.Length);
- len = dataStream.Read(buffer, 0, blockLen);
- }
- return deStream.ToArray();
- }
- catch
- {
- return null;
- }
- }
- /// <summary>
- /// 对str进行签名,并指定hash算法(如:SHA256)
- /// </summary>
- public string Sign(string hash, string str)
- {
- return Convert.ToBase64String(Sign(hash, Encoding.UTF8.GetBytes(str)));
- }
- /// <summary>
- /// 对data进行签名,并指定hash算法(如:SHA256)
- /// </summary>
- public byte[] Sign(string hash, byte[] data)
- {
- return RSAObject.SignData(data, hash);
- }
- /// <summary>
- /// 验证字符串str的签名是否是sgin,并指定hash算法(如:SHA256)
- /// </summary>
- public bool Verify(string hash, string sgin, string str)
- {
- byte[] bytes = null;
- try
- {
- bytes = Convert.FromBase64String(sgin);
- }
- catch
- {
- }
- return bytes != null && Verify(hash, bytes, Encoding.UTF8.GetBytes(str));
- }
- /// <summary>
- /// 验证data的签名是否是sgin,并指定hash算法(如:SHA256)
- /// </summary>
- public bool Verify(string hash, byte[] sgin, byte[] data)
- {
- try
- {
- return RSAObject.VerifyData(data, hash, sgin);
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 最底层的RSACryptoServiceProvider对象
- /// </summary>
- public RSACryptoServiceProvider RSAObject { get; }
- /// <summary>
- /// 密钥位数
- /// </summary>
- public int KeySize => RSAObject.KeySize;
- /// <summary>
- /// 是否包含私钥
- /// </summary>
- public bool HasPrivate => !RSAObject.PublicOnly;
- /// <summary>
- /// 用指定密钥大小创建一个新的RSA,出错抛异常
- /// </summary>
- public RSA(int keySize)
- {
- RSAObject = new RSACryptoServiceProvider(keySize);
- }
- /// <summary>
- /// 通过公钥或私钥创建RSA,出错抛异常
- /// </summary>
- public RSA(string key)
- {
- if (!key.StartsWith("<"))
- {
- RSAObject = RsaPem.FromPEM(key).GetRSA();
- }
- else
- {
- RSAObject = new RSACryptoServiceProvider();
- RSAObject.FromXmlString(key);
- }
- }
- /// <summary>
- /// 通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常
- /// </summary>
- public RSA(RsaPem pem)
- {
- RSAObject = pem.GetRSA();
- }
- }
|