123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741 |
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using System.Text;
- using PaySharp.Core.Exceptions;
- namespace PaySharp.Core.Utils
- {
- /// <summary>
- /// 加密工具类
- /// </summary>
- public static class EncryptUtil
- {
- #region 私有字段
- /// <summary>
- /// 默认编码
- /// </summary>
- private static readonly string _defaultCharset = "UTF-8";
- #endregion
- #region MD5加密
- /// <summary>
- /// MD5加密
- /// </summary>
- /// <param name="data">数据</param>
- public static string MD5(string data)
- {
- return MD5(data, Encoding.UTF8);
- }
- /// <summary>
- /// MD5加密
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="encoding">编码</param>
- /// <returns></returns>
- public static string MD5(string data, Encoding encoding)
- {
- var md5 = System.Security.Cryptography.MD5.Create();
- var dataByte = md5.ComputeHash(encoding.GetBytes(data));
- return BitConverter.ToString(dataByte).Replace("-", "");
- }
- #endregion
- #region RSA加密
- /// <summary>
- /// RSA加密
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="privateKey">私钥</param>
- /// <param name="signType">签名类型</param>
- /// <returns></returns>
- public static string RSA(string data, string privateKey, string signType)
- {
- return RSA(data, privateKey, _defaultCharset, signType, false);
- }
- private static string RSA(string data, string privateKeyPem, string charset, string signType, bool keyFromFile)
- {
- byte[] signatureBytes = null;
- try
- {
- RSA rsaCsp = null;
- if (keyFromFile)
- {
- //文件读取
- rsaCsp = LoadCertificateFile(privateKeyPem, signType);
- }
- else
- {
- //字符串获取
- rsaCsp = LoadCertificateString(privateKeyPem, signType);
- }
- byte[] dataBytes = null;
- if (string.IsNullOrEmpty(charset))
- {
- dataBytes = Encoding.UTF8.GetBytes(data);
- }
- else
- {
- dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
- }
- if (null == rsaCsp)
- {
- throw new GatewayException("您使用的私钥格式错误,请检查RSA私钥配置" + ",charset = " + charset);
- }
- if ("RSA2".Equals(signType))
- {
- #if NETCOREAPP3_1
- signatureBytes = rsaCsp.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
- #else
- signatureBytes = ((RSACryptoServiceProvider)rsaCsp).SignData(dataBytes, "SHA256");
- #endif
- }
- else
- {
- #if NETCOREAPP3_1
- signatureBytes = rsaCsp.SignData(dataBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
- #else
- signatureBytes = ((RSACryptoServiceProvider)rsaCsp).SignData(dataBytes, "SHA1");
- #endif
- }
- }
- catch
- {
- throw new GatewayException("您使用的私钥格式错误,请检查RSA私钥配置" + ",charset = " + charset);
- }
- return Convert.ToBase64String(signatureBytes);
- }
- /// <summary>
- /// RSA2验签
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="sign">签名</param>
- /// <param name="publicKey">公钥</param>
- /// <param name="signType">签名类型</param>
- /// <returns></returns>
- public static bool RSAVerifyData(string data, string sign, string publicKey, string signType)
- {
- return RSAVerifyData(data, sign, publicKey, _defaultCharset, signType, false);
- }
- private static bool RSAVerifyData(string signContent, string sign, string publicKeyPem, string charset, string signType, bool keyFromFile)
- {
- try
- {
- var sPublicKeyPEM = publicKeyPem;
- if (keyFromFile)
- {
- sPublicKeyPEM = File.ReadAllText(publicKeyPem);
- }
- var rsa = CreateRsaProviderFromPublicKey(sPublicKeyPEM, signType);
- var bVerifyResultOriginal = false;
- if ("RSA2".Equals(signType))
- {
- #if NETCOREAPP3_1
- bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
- Convert.FromBase64String(sign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
- #else
- bVerifyResultOriginal = ((RSACryptoServiceProvider)rsa).VerifyData(
- Encoding.GetEncoding(charset).GetBytes(signContent), "SHA256", Convert.FromBase64String(sign));
- #endif
- }
- else
- {
- #if NETCOREAPP3_1
- bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
- Convert.FromBase64String(sign), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
- #else
- bVerifyResultOriginal = ((RSACryptoServiceProvider)rsa).VerifyData(
- Encoding.GetEncoding(charset).GetBytes(signContent), "SHA1", Convert.FromBase64String(sign));
- #endif
- }
- return bVerifyResultOriginal;
- }
- catch
- {
- return false;
- }
- }
- private static RSA CreateRsaProviderFromPublicKey(string publicKeyString, string signType)
- {
- byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
- var seq = new byte[15];
- var x509Key = Convert.FromBase64String(publicKeyString);
- using var mem = new MemoryStream(x509Key);
- using var binr = new BinaryReader(mem);
- byte bt = 0;
- ushort twobytes = 0;
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130)
- {
- binr.ReadByte();
- }
- else if (twobytes == 0x8230)
- {
- binr.ReadInt16();
- }
- else
- {
- return null;
- }
- seq = binr.ReadBytes(15);
- if (!CompareBytearrays(seq, seqOid))
- {
- return null;
- }
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8103)
- {
- binr.ReadByte();
- }
- else if (twobytes == 0x8203)
- {
- binr.ReadInt16();
- }
- else
- {
- return null;
- }
- bt = binr.ReadByte();
- if (bt != 0x00)
- {
- return null;
- }
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130)
- {
- binr.ReadByte();
- }
- else if (twobytes == 0x8230)
- {
- binr.ReadInt16();
- }
- else
- {
- return null;
- }
- twobytes = binr.ReadUInt16();
- byte lowbyte = 0x00;
- byte highbyte = 0x00;
- if (twobytes == 0x8102)
- {
- lowbyte = binr.ReadByte();
- }
- else if (twobytes == 0x8202)
- {
- highbyte = binr.ReadByte();
- lowbyte = binr.ReadByte();
- }
- else
- {
- return null;
- }
- byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
- var modsize = BitConverter.ToInt32(modint, 0);
- var firstbyte = binr.PeekChar();
- if (firstbyte == 0x00)
- {
- binr.ReadByte();
- modsize -= 1;
- }
- var modulus = binr.ReadBytes(modsize);
- if (binr.ReadByte() != 0x02)
- {
- return null;
- }
- int expbytes = binr.ReadByte();
- var exponent = binr.ReadBytes(expbytes);
- var rsa = System.Security.Cryptography.RSA.Create();
- rsa.KeySize = signType == "RSA" ? 1024 : 2048;
- var rsaKeyInfo = new RSAParameters
- {
- Modulus = modulus,
- Exponent = exponent
- };
- rsa.ImportParameters(rsaKeyInfo);
- return rsa;
- }
- private static bool CompareBytearrays(byte[] a, byte[] b)
- {
- if (a.Length != b.Length)
- {
- return false;
- }
- var i = 0;
- foreach (var c in a)
- {
- if (c != b[i])
- {
- return false;
- }
- i++;
- }
- return true;
- }
- private static RSA LoadCertificateFile(string filename, string signType)
- {
- using var fs = File.OpenRead(filename);
- var data = new byte[fs.Length];
- byte[] res = null;
- fs.Read(data, 0, data.Length);
- if (data[0] != 0x30)
- {
- res = GetPem("RSA PRIVATE KEY", data);
- }
- try
- {
- return DecodeRSAPrivateKey(res, signType);
- }
- catch
- {
- return null;
- }
- }
- private static RSA LoadCertificateString(string strKey, string signType)
- {
- var data = Convert.FromBase64String(strKey);
- try
- {
- return DecodeRSAPrivateKey(data, signType);
- }
- catch
- {
- return null;
- }
- }
- private static RSA DecodeRSAPrivateKey(byte[] privkey, string signType)
- {
- byte[] modulus, e, d, p, q, dP, dQ, iQ;
- var mem = new MemoryStream(privkey);
- var binr = new BinaryReader(mem);
- try
- {
- var twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130)
- {
- binr.ReadByte();
- }
- else if (twobytes == 0x8230)
- {
- binr.ReadInt16();
- }
- else
- {
- return null;
- }
- twobytes = binr.ReadUInt16();
- if (twobytes != 0x0102)
- {
- return null;
- }
- var bt = binr.ReadByte();
- if (bt != 0x00)
- {
- return null;
- }
- var 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);
- var bitLen = 1024;
- if ("RSA2".Equals(signType))
- {
- bitLen = 2048;
- }
- var rsa = System.Security.Cryptography.RSA.Create();
- rsa.KeySize = bitLen;
- var rsaParams = new RSAParameters
- {
- Modulus = modulus,
- Exponent = e,
- D = d,
- P = p,
- Q = q,
- DP = dP,
- DQ = dQ,
- InverseQ = iQ
- };
- rsa.ImportParameters(rsaParams);
- return rsa;
- }
- catch
- {
- return null;
- }
- finally
- {
- binr.Close();
- }
- }
- private static byte[] GetPem(string type, byte[] data)
- {
- var pem = Encoding.UTF8.GetString(data);
- var header = string.Format("-----BEGIN {0}-----\\n", type);
- var footer = string.Format("-----END {0}-----", type);
- var start = pem.IndexOf(header) + header.Length;
- var end = pem.IndexOf(footer, start);
- var base64 = pem.Substring(start, end - start);
- return Convert.FromBase64String(base64);
- }
- #endregion
- #region SHA256加密
- /// <summary>
- /// SHA256加密
- /// </summary>
- /// <param name="data">数据</param>
- /// <returns></returns>
- public static string SHA256(string data)
- {
- var byteData = Encoding.UTF8.GetBytes(data);
- var sha256 = new SHA256Managed();
- var result = sha256.ComputeHash(byteData);
- return BitConverter.ToString(result).Replace("-", "").ToLower();
- }
- #endregion
- #region HMACSHA1加密
- /// <summary>
- /// HMACSHA1加密
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="key">密钥</param>
- /// <returns></returns>
- public static string HMACSHA1(string data, string key)
- {
- var byteData = Encoding.UTF8.GetBytes(data);
- var byteKey = Encoding.UTF8.GetBytes(key);
- var hmacsha1 = new HMACSHA1(byteKey);
- var result = hmacsha1.ComputeHash(byteData);
- return Convert.ToBase64String(result);
- }
- #endregion
- #region HMACSHA256加密
- /// <summary>
- /// HMACSHA256加密
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="key">密钥</param>
- /// <returns></returns>
- public static string HMACSHA256(string data, string key)
- {
- var byteData = Encoding.UTF8.GetBytes(data);
- var byteKey = Encoding.UTF8.GetBytes(key);
- var hmacsha256 = new HMACSHA256(byteKey);
- var result = hmacsha256.ComputeHash(byteData);
- return BitConverter.ToString(result).Replace("-", "").ToLower();
- }
- #endregion
- #region AES解密
- /// <summary>
- /// AES解密
- /// </summary>
- /// <param name="data">待解密数据</param>
- /// <param name="key">密钥</param>
- /// <returns></returns>
- public static string AESDecrypt(string data, string key)
- {
- var keyArray = Encoding.UTF8.GetBytes(key);
- var toEncryptArray = Convert.FromBase64String(data);
- var rDel = new RijndaelManaged
- {
- Key = keyArray,
- Mode = CipherMode.ECB,
- Padding = PaddingMode.PKCS7
- };
- var cTransform = rDel.CreateDecryptor();
- var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
- return Encoding.UTF8.GetString(resultArray);
- }
- #endregion
- #region from alipay signer
- /// <summary>
- /// 验证签名
- /// </summary>
- /// <param name="content">待验签的内容</param>
- /// <param name="sign">签名值的Base64串</param>
- /// <param name="publicKeyPem">支付宝公钥</param>
- /// <returns>true:验证成功;false:验证失败</returns>
- public static bool Verify(string content, string sign, string publicKeyPem)
- {
- try
- {
- using (RSACryptoServiceProvider rsaService = new RSACryptoServiceProvider())
- {
- rsaService.PersistKeyInCsp = false;
- rsaService.ImportParameters(ConvertFromPemPublicKey(publicKeyPem));
- return rsaService.VerifyData(Encoding.UTF8.GetBytes(content),
- "SHA256", Convert.FromBase64String(sign));
- }
- }
- catch (Exception e)
- {
- string errorMessage = "验签遭遇异常,content=" + content + " sign=" + sign +
- " publicKey=" + publicKeyPem + " reason=" + e.Message;
- throw new Exception(errorMessage, e);
- }
- }
- /// <summary>
- /// SHA256WithRSA 计算签名
- /// </summary>
- /// <param name="content">数据</param>
- /// <param name="privateKeyPem">私钥</param>
- /// <returns></returns>
- public static string Sign(string content, string privateKeyPem)
- {
- try
- {
- using (RSACryptoServiceProvider rsaService = BuildRSAServiceProvider(Convert.FromBase64String(privateKeyPem)))
- {
- byte[] data = Encoding.UTF8.GetBytes(content);
- byte[] sign = rsaService.SignData(data, "SHA256");
- return Convert.ToBase64String(sign);
- }
- }
- catch (Exception e)
- {
- string errorMessage = "签名遭遇异常,content=" + content + " privateKeySize=" + privateKeyPem.Length + " reason=" + e.Message;
- throw new Exception(errorMessage, e);
- }
- }
- private static RSAParameters ConvertFromPemPublicKey(string pemPublickKey)
- {
- if (string.IsNullOrEmpty(pemPublickKey))
- {
- throw new Exception("PEM格式公钥不可为空。");
- }
- //移除干扰文本
- pemPublickKey = pemPublickKey.Replace("-----BEGIN PUBLIC KEY-----", "")
- .Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
- byte[] keyData = Convert.FromBase64String(pemPublickKey);
- bool keySize1024 = (keyData.Length == 162);
- bool keySize2048 = (keyData.Length == 294);
- if (!(keySize1024 || keySize2048))
- {
- throw new Exception("公钥长度只支持1024和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
- {
- Modulus = pemModulus,
- Exponent = pemPublicExponent
- };
- return para;
- }
- private static RSACryptoServiceProvider BuildRSAServiceProvider(byte[] privateKey)
- {
- byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
- byte bt = 0;
- ushort twobytes = 0;
- int elems = 0;
- //set up stream to decode the asn.1 encoded RSA private key
- //wrap Memory Stream with BinaryReader for easy reading
- using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(privateKey)))
- {
- twobytes = binaryReader.ReadUInt16();
- //data read as little endian order (actual data order for Sequence is 30 81)
- if (twobytes == 0x8130)
- {
- //advance 1 byte
- binaryReader.ReadByte();
- }
- else if (twobytes == 0x8230)
- {
- //advance 2 bytes
- binaryReader.ReadInt16();
- }
- else
- {
- return null;
- }
- twobytes = binaryReader.ReadUInt16();
- //version number
- if (twobytes != 0x0102)
- {
- return null;
- }
- bt = binaryReader.ReadByte();
- if (bt != 0x00)
- {
- return null;
- }
- //all private key components are Integer sequences
- elems = GetIntegerSize(binaryReader);
- MODULUS = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- E = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- D = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- P = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- Q = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- DP = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- DQ = binaryReader.ReadBytes(elems);
- elems = GetIntegerSize(binaryReader);
- IQ = binaryReader.ReadBytes(elems);
- //create RSACryptoServiceProvider instance and initialize with public key
- RSACryptoServiceProvider rsaService = new RSACryptoServiceProvider();
- RSAParameters rsaParams = new RSAParameters
- {
- Modulus = MODULUS,
- Exponent = E,
- D = D,
- P = P,
- Q = Q,
- DP = DP,
- DQ = DQ,
- InverseQ = IQ
- };
- rsaService.ImportParameters(rsaParams);
- return rsaService;
- }
- }
- private static int GetIntegerSize(BinaryReader binaryReader)
- {
- byte bt = 0;
- byte lowbyte = 0x00;
- byte highbyte = 0x00;
- int count = 0;
- bt = binaryReader.ReadByte();
- //expect integer
- if (bt != 0x02)
- {
- return 0;
- }
- bt = binaryReader.ReadByte();
- if (bt == 0x81)
- {
- //data size in next byte
- count = binaryReader.ReadByte();
- }
- else if (bt == 0x82)
- {
- //data size in next 2 bytes
- highbyte = binaryReader.ReadByte();
- lowbyte = binaryReader.ReadByte();
- byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
- count = BitConverter.ToInt32(modint, 0);
- }
- else
- {
- //we already have the data size
- count = bt;
- }
- while (binaryReader.ReadByte() == 0x00)
- { //remove high order zeros in data
- count -= 1;
- }
- //last ReadByte wasn't a removed zero, so back up a byte
- binaryReader.BaseStream.Seek(-1, SeekOrigin.Current);
- return count;
- }
- #endregion
- }
- }
|