123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Security.Cryptography;
- using System.IO;
- namespace Aop.Api.Util
- {
- public class AlipaySignature
- {
- /** 默认编码字符集 */
- private static string DEFAULT_CHARSET = "GBK";
- public static string GetSignContent(IDictionary<string, string> parameters)
- {
- // 第一步:把字典按Key的字母顺序排序
- IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
- IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
- // 第二步:把所有参数名和参数值串在一起
- StringBuilder query = new StringBuilder("");
- while (dem.MoveNext())
- {
- string key = dem.Current.Key;
- string value = dem.Current.Value;
- if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
- {
- query.Append(key).Append("=").Append(value).Append("&");
- }
- }
- string content = query.ToString().Substring(0, query.Length - 1);
- return content;
- }
- public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset)
- {
- string signContent = GetSignContent(parameters);
- return RSASignCharSet(signContent, privateKeyPem, charset);
- }
- public static string RSASign(string data, string privateKeyPem, string charset)
- {
- return RSASignCharSet(data, privateKeyPem, charset);
- }
- public static string RSASignCharSet(string data, string privateKeyPem, string charset)
- {
- RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, charset);
- byte[] dataBytes = null;
- if (string.IsNullOrEmpty(charset))
- {
- dataBytes = Encoding.UTF8.GetBytes(data);
- }
- else
- {
- dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
- }
-
- byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
- return Convert.ToBase64String(signatureBytes);
- }
- public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
- {
- string sign = parameters["sign"];
- parameters.Remove("sign");
- parameters.Remove("sign_type");
- string signContent = GetSignContent(parameters);
- return RSACheckContent(signContent, sign, publicKeyPem, charset);
- }
- public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem)
- {
- string sign = parameters["sign"];
- parameters.Remove("sign");
- parameters.Remove("sign_type");
- string signContent = GetSignContent(parameters);
- return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET);
- }
- public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem)
- {
- string sign = parameters["sign"];
- parameters.Remove("sign");
- string signContent = GetSignContent(parameters);
- return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET);
- }
- public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset)
- {
- string sign = parameters["sign"];
- parameters.Remove("sign");
- string signContent = GetSignContent(parameters);
- return RSACheckContent(signContent, sign, publicKeyPem, charset);
- }
- public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset)
- {
- try
- {
- //Abby
- //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- rsa.PersistKeyInCsp = false;
- RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, publicKeyPem);
- SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
- if (string.IsNullOrEmpty(charset))
- {
- charset = DEFAULT_CHARSET;
- }
- bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
- return bVerifyResultOriginal;
- }
- catch
- {
- return false;
- }
- }
- public static string CheckSignAndDecrypt(IDictionary<string, string> parameters, string alipayPublicKey,
- string cusPrivateKey, bool isCheckSign,
- bool isDecrypt)
- {
- string charset = parameters["charset"];
- string bizContent = parameters["biz_content"];
- if (isCheckSign)
- {
- if (!RSACheckV2(parameters, alipayPublicKey, charset))
- {
- throw new AopException("rsaCheck failure:rsaParams=" + parameters);
- }
- }
- if (isDecrypt)
- {
- return RSADecrypt(bizContent, cusPrivateKey, charset);
- }
- return bizContent;
- }
- public static string encryptAndSign(string bizContent, string alipayPublicKey,
- string cusPrivateKey, string charset, bool isEncrypt,
- bool isSign)
- {
- StringBuilder sb=new StringBuilder();
- if (string.IsNullOrEmpty(charset))
- {
- charset = DEFAULT_CHARSET;
- }
- sb.Append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
- if (isEncrypt)
- {// 加密
- sb.Append("<alipay>");
- String encrypted = RSAEncrypt(bizContent, alipayPublicKey, charset);
- sb.Append("<response>" + encrypted + "</response>");
- sb.Append("<encryption_type>RSA</encryption_type>");
- if (isSign)
- {
- String sign = RSASign(encrypted, cusPrivateKey, charset);
- sb.Append("<sign>" + sign + "</sign>");
- sb.Append("<sign_type>RSA</sign_type>");
- }
- sb.Append("</alipay>");
- }
- else if (isSign)
- {// 不加密,但需要签名
- sb.Append("<alipay>");
- sb.Append("<response>" + bizContent + "</response>");
- String sign = RSASign(bizContent, cusPrivateKey, charset);
- sb.Append("<sign>" + sign + "</sign>");
- sb.Append("<sign_type>RSA</sign_type>");
- sb.Append("</alipay>");
- }
- else
- {// 不加密,不加签
- sb.Append(bizContent);
- }
- return sb.ToString();
- }
- public static string RSAEncrypt(string content, string publicKeyPem, string charset)
- {
- try
- {
- if (string.IsNullOrEmpty(charset))
- {
- charset = DEFAULT_CHARSET;
- }
- //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- rsa.PersistKeyInCsp = false;
- RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, publicKeyPem);
- byte[] data = Encoding.GetEncoding(charset).GetBytes(content);
- int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
- if (data.Length <= maxBlockSize)
- {
- byte[] cipherbytes = rsa.Encrypt(data, false);
- return Convert.ToBase64String(cipherbytes);
- }
- MemoryStream plaiStream = new MemoryStream(data);
- 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 Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
- }
- catch (Exception ex)
- {
- throw new AopException("EncryptContent = " + content + ",charset = " + charset, ex);
- }
- }
- public static string RSADecrypt(string content, string privateKeyPem, string charset)
- {
- try
- {
- RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, charset);
- if (string.IsNullOrEmpty(charset))
- {
- charset = DEFAULT_CHARSET;
- }
- byte[] data = Convert.FromBase64String(content);
- int maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
- if (data.Length <= maxBlockSize)
- {
- byte[] cipherbytes = rsaCsp.Decrypt(data, false);
- return Encoding.GetEncoding(charset).GetString(cipherbytes);
- }
- MemoryStream crypStream = new MemoryStream(data);
- 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[] cryptograph = rsaCsp.Decrypt(toDecrypt, false);
- plaiStream.Write(cryptograph, 0, cryptograph.Length);
- blockSize = crypStream.Read(buffer, 0, maxBlockSize);
- }
- return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
- }
- catch (Exception ex)
- {
- throw new AopException("DecryptContent = " + content + ",charset = " + charset, ex);
- }
- }
- private static byte[] GetPem(string type, byte[] data)
- {
- string pem = Encoding.UTF8.GetString(data);
- string header = String.Format("-----BEGIN {0}-----\\n", type);
- string footer = String.Format("-----END {0}-----", type);
- int start = pem.IndexOf(header) + header.Length;
- int end = pem.IndexOf(footer, start);
- string base64 = pem.Substring(start, (end - start));
- return Convert.FromBase64String(base64);
- }
- private static RSACryptoServiceProvider LoadCertificateFile(string privateKeyPem, string charset)
- {
- if (string.IsNullOrEmpty(charset))
- {
- charset = DEFAULT_CHARSET;
- }
- byte[] data = Encoding.GetEncoding(charset).GetBytes(privateKeyPem);
- byte[] res = null;
- if (data[0] != 0x30)
- {
- res = GetPem("RSA PRIVATE KEY", data);
- }
- try
- {
- RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
- return rsa;
- }
- catch (Exception ex)
- {
- }
- return null;
- }
- private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
- {
- byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
- // --------- Set up stream to decode the asn.1 encoded RSA private key ------
- MemoryStream mem = new MemoryStream(privkey);
- BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
- byte bt = 0;
- ushort twobytes = 0;
- int elems = 0;
- try
- {
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
- binr.ReadByte(); //advance 1 byte
- else if (twobytes == 0x8230)
- binr.ReadInt16(); //advance 2 bytes
- else
- return null;
- twobytes = binr.ReadUInt16();
- if (twobytes != 0x0102) //version number
- return null;
- bt = binr.ReadByte();
- if (bt != 0x00)
- return null;
- //------ all private key components are Integer sequences ----
- 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);
- // ------- create RSACryptoServiceProvider instance and initialize with public key -----
- CspParameters CspParameters = new CspParameters();
- CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
- RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
- RSAParameters RSAparams = new RSAParameters();
- RSAparams.Modulus = MODULUS;
- RSAparams.Exponent = E;
- RSAparams.D = D;
- RSAparams.P = P;
- RSAparams.Q = Q;
- RSAparams.DP = DP;
- RSAparams.DQ = DQ;
- RSAparams.InverseQ = IQ;
- RSA.ImportParameters(RSAparams);
- return RSA;
- }
- catch (Exception ex)
- {
- return null;
- }
- finally
- {
- binr.Close();
- }
- }
- private static int GetIntegerSize(BinaryReader binr)
- {
- byte bt = 0;
- byte lowbyte = 0x00;
- byte highbyte = 0x00;
- int count = 0;
- bt = binr.ReadByte();
- if (bt != 0x02) //expect integer
- return 0;
- bt = binr.ReadByte();
- if (bt == 0x81)
- count = binr.ReadByte(); // data size in next byte
- else
- if (bt == 0x82)
- {
- highbyte = binr.ReadByte(); // data size in next 2 bytes
- lowbyte = binr.ReadByte();
- byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
- count = BitConverter.ToInt32(modint, 0);
- }
- else
- {
- count = bt; // we already have the data size
- }
- while (binr.ReadByte() == 0x00)
- { //remove high order zeros in data
- count -= 1;
- }
- binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
- return count;
- }
- }
- }
|