AlipaySignature.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Security.Cryptography;
  5. using System.IO;
  6. namespace Aop.Api.Util
  7. {
  8. public class AlipaySignature
  9. {
  10. /** 默认编码字符集 */
  11. private static string DEFAULT_CHARSET = "GBK";
  12. public static string GetSignContent(IDictionary<string, string> parameters)
  13. {
  14. // 第一步:把字典按Key的字母顺序排序
  15. IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
  16. IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
  17. // 第二步:把所有参数名和参数值串在一起
  18. StringBuilder query = new StringBuilder("");
  19. while (dem.MoveNext())
  20. {
  21. string key = dem.Current.Key;
  22. string value = dem.Current.Value;
  23. if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
  24. {
  25. query.Append(key).Append("=").Append(value).Append("&");
  26. }
  27. }
  28. string content = query.ToString().Substring(0, query.Length - 1);
  29. return content;
  30. }
  31. public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset)
  32. {
  33. string signContent = GetSignContent(parameters);
  34. return RSASignCharSet(signContent, privateKeyPem, charset);
  35. }
  36. public static string RSASign(string data, string privateKeyPem, string charset)
  37. {
  38. return RSASignCharSet(data, privateKeyPem, charset);
  39. }
  40. public static string RSASignCharSet(string data, string privateKeyPem, string charset)
  41. {
  42. RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, charset);
  43. byte[] dataBytes = null;
  44. if (string.IsNullOrEmpty(charset))
  45. {
  46. dataBytes = Encoding.UTF8.GetBytes(data);
  47. }
  48. else
  49. {
  50. dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
  51. }
  52. byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
  53. return Convert.ToBase64String(signatureBytes);
  54. }
  55. public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
  56. {
  57. string sign = parameters["sign"];
  58. parameters.Remove("sign");
  59. parameters.Remove("sign_type");
  60. string signContent = GetSignContent(parameters);
  61. return RSACheckContent(signContent, sign, publicKeyPem, charset);
  62. }
  63. public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem)
  64. {
  65. string sign = parameters["sign"];
  66. parameters.Remove("sign");
  67. parameters.Remove("sign_type");
  68. string signContent = GetSignContent(parameters);
  69. return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET);
  70. }
  71. public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem)
  72. {
  73. string sign = parameters["sign"];
  74. parameters.Remove("sign");
  75. string signContent = GetSignContent(parameters);
  76. return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET);
  77. }
  78. public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset)
  79. {
  80. string sign = parameters["sign"];
  81. parameters.Remove("sign");
  82. string signContent = GetSignContent(parameters);
  83. return RSACheckContent(signContent, sign, publicKeyPem, charset);
  84. }
  85. public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset)
  86. {
  87. try
  88. {
  89. //Abby
  90. //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  91. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  92. rsa.PersistKeyInCsp = false;
  93. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, publicKeyPem);
  94. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  95. if (string.IsNullOrEmpty(charset))
  96. {
  97. charset = DEFAULT_CHARSET;
  98. }
  99. bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
  100. return bVerifyResultOriginal;
  101. }
  102. catch
  103. {
  104. return false;
  105. }
  106. }
  107. public static string CheckSignAndDecrypt(IDictionary<string, string> parameters, string alipayPublicKey,
  108. string cusPrivateKey, bool isCheckSign,
  109. bool isDecrypt)
  110. {
  111. string charset = parameters["charset"];
  112. string bizContent = parameters["biz_content"];
  113. if (isCheckSign)
  114. {
  115. if (!RSACheckV2(parameters, alipayPublicKey, charset))
  116. {
  117. throw new AopException("rsaCheck failure:rsaParams=" + parameters);
  118. }
  119. }
  120. if (isDecrypt)
  121. {
  122. return RSADecrypt(bizContent, cusPrivateKey, charset);
  123. }
  124. return bizContent;
  125. }
  126. public static string encryptAndSign(string bizContent, string alipayPublicKey,
  127. string cusPrivateKey, string charset, bool isEncrypt,
  128. bool isSign)
  129. {
  130. StringBuilder sb=new StringBuilder();
  131. if (string.IsNullOrEmpty(charset))
  132. {
  133. charset = DEFAULT_CHARSET;
  134. }
  135. sb.Append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
  136. if (isEncrypt)
  137. {// 加密
  138. sb.Append("<alipay>");
  139. String encrypted = RSAEncrypt(bizContent, alipayPublicKey, charset);
  140. sb.Append("<response>" + encrypted + "</response>");
  141. sb.Append("<encryption_type>RSA</encryption_type>");
  142. if (isSign)
  143. {
  144. String sign = RSASign(encrypted, cusPrivateKey, charset);
  145. sb.Append("<sign>" + sign + "</sign>");
  146. sb.Append("<sign_type>RSA</sign_type>");
  147. }
  148. sb.Append("</alipay>");
  149. }
  150. else if (isSign)
  151. {// 不加密,但需要签名
  152. sb.Append("<alipay>");
  153. sb.Append("<response>" + bizContent + "</response>");
  154. String sign = RSASign(bizContent, cusPrivateKey, charset);
  155. sb.Append("<sign>" + sign + "</sign>");
  156. sb.Append("<sign_type>RSA</sign_type>");
  157. sb.Append("</alipay>");
  158. }
  159. else
  160. {// 不加密,不加签
  161. sb.Append(bizContent);
  162. }
  163. return sb.ToString();
  164. }
  165. public static string RSAEncrypt(string content, string publicKeyPem, string charset)
  166. {
  167. try
  168. {
  169. if (string.IsNullOrEmpty(charset))
  170. {
  171. charset = DEFAULT_CHARSET;
  172. }
  173. //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
  174. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  175. rsa.PersistKeyInCsp = false;
  176. RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, publicKeyPem);
  177. byte[] data = Encoding.GetEncoding(charset).GetBytes(content);
  178. int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
  179. if (data.Length <= maxBlockSize)
  180. {
  181. byte[] cipherbytes = rsa.Encrypt(data, false);
  182. return Convert.ToBase64String(cipherbytes);
  183. }
  184. MemoryStream plaiStream = new MemoryStream(data);
  185. MemoryStream crypStream = new MemoryStream();
  186. Byte[] buffer = new Byte[maxBlockSize];
  187. int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
  188. while (blockSize > 0)
  189. {
  190. Byte[] toEncrypt = new Byte[blockSize];
  191. Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
  192. Byte[] cryptograph = rsa.Encrypt(toEncrypt, false);
  193. crypStream.Write(cryptograph, 0, cryptograph.Length);
  194. blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
  195. }
  196. return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
  197. }
  198. catch (Exception ex)
  199. {
  200. throw new AopException("EncryptContent = " + content + ",charset = " + charset, ex);
  201. }
  202. }
  203. public static string RSADecrypt(string content, string privateKeyPem, string charset)
  204. {
  205. try
  206. {
  207. RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem, charset);
  208. if (string.IsNullOrEmpty(charset))
  209. {
  210. charset = DEFAULT_CHARSET;
  211. }
  212. byte[] data = Convert.FromBase64String(content);
  213. int maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
  214. if (data.Length <= maxBlockSize)
  215. {
  216. byte[] cipherbytes = rsaCsp.Decrypt(data, false);
  217. return Encoding.GetEncoding(charset).GetString(cipherbytes);
  218. }
  219. MemoryStream crypStream = new MemoryStream(data);
  220. MemoryStream plaiStream = new MemoryStream();
  221. Byte[] buffer = new Byte[maxBlockSize];
  222. int blockSize = crypStream.Read(buffer, 0, maxBlockSize);
  223. while (blockSize > 0)
  224. {
  225. Byte[] toDecrypt = new Byte[blockSize];
  226. Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
  227. Byte[] cryptograph = rsaCsp.Decrypt(toDecrypt, false);
  228. plaiStream.Write(cryptograph, 0, cryptograph.Length);
  229. blockSize = crypStream.Read(buffer, 0, maxBlockSize);
  230. }
  231. return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
  232. }
  233. catch (Exception ex)
  234. {
  235. throw new AopException("DecryptContent = " + content + ",charset = " + charset, ex);
  236. }
  237. }
  238. private static byte[] GetPem(string type, byte[] data)
  239. {
  240. string pem = Encoding.UTF8.GetString(data);
  241. string header = String.Format("-----BEGIN {0}-----\\n", type);
  242. string footer = String.Format("-----END {0}-----", type);
  243. int start = pem.IndexOf(header) + header.Length;
  244. int end = pem.IndexOf(footer, start);
  245. string base64 = pem.Substring(start, (end - start));
  246. return Convert.FromBase64String(base64);
  247. }
  248. private static RSACryptoServiceProvider LoadCertificateFile(string privateKeyPem, string charset)
  249. {
  250. if (string.IsNullOrEmpty(charset))
  251. {
  252. charset = DEFAULT_CHARSET;
  253. }
  254. byte[] data = Encoding.GetEncoding(charset).GetBytes(privateKeyPem);
  255. byte[] res = null;
  256. if (data[0] != 0x30)
  257. {
  258. res = GetPem("RSA PRIVATE KEY", data);
  259. }
  260. try
  261. {
  262. RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
  263. return rsa;
  264. }
  265. catch (Exception ex)
  266. {
  267. }
  268. return null;
  269. }
  270. private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
  271. {
  272. byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
  273. // --------- Set up stream to decode the asn.1 encoded RSA private key ------
  274. MemoryStream mem = new MemoryStream(privkey);
  275. BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
  276. byte bt = 0;
  277. ushort twobytes = 0;
  278. int elems = 0;
  279. try
  280. {
  281. twobytes = binr.ReadUInt16();
  282. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  283. binr.ReadByte(); //advance 1 byte
  284. else if (twobytes == 0x8230)
  285. binr.ReadInt16(); //advance 2 bytes
  286. else
  287. return null;
  288. twobytes = binr.ReadUInt16();
  289. if (twobytes != 0x0102) //version number
  290. return null;
  291. bt = binr.ReadByte();
  292. if (bt != 0x00)
  293. return null;
  294. //------ all private key components are Integer sequences ----
  295. elems = GetIntegerSize(binr);
  296. MODULUS = binr.ReadBytes(elems);
  297. elems = GetIntegerSize(binr);
  298. E = binr.ReadBytes(elems);
  299. elems = GetIntegerSize(binr);
  300. D = binr.ReadBytes(elems);
  301. elems = GetIntegerSize(binr);
  302. P = binr.ReadBytes(elems);
  303. elems = GetIntegerSize(binr);
  304. Q = binr.ReadBytes(elems);
  305. elems = GetIntegerSize(binr);
  306. DP = binr.ReadBytes(elems);
  307. elems = GetIntegerSize(binr);
  308. DQ = binr.ReadBytes(elems);
  309. elems = GetIntegerSize(binr);
  310. IQ = binr.ReadBytes(elems);
  311. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  312. CspParameters CspParameters = new CspParameters();
  313. CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
  314. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
  315. RSAParameters RSAparams = new RSAParameters();
  316. RSAparams.Modulus = MODULUS;
  317. RSAparams.Exponent = E;
  318. RSAparams.D = D;
  319. RSAparams.P = P;
  320. RSAparams.Q = Q;
  321. RSAparams.DP = DP;
  322. RSAparams.DQ = DQ;
  323. RSAparams.InverseQ = IQ;
  324. RSA.ImportParameters(RSAparams);
  325. return RSA;
  326. }
  327. catch (Exception ex)
  328. {
  329. return null;
  330. }
  331. finally
  332. {
  333. binr.Close();
  334. }
  335. }
  336. private static int GetIntegerSize(BinaryReader binr)
  337. {
  338. byte bt = 0;
  339. byte lowbyte = 0x00;
  340. byte highbyte = 0x00;
  341. int count = 0;
  342. bt = binr.ReadByte();
  343. if (bt != 0x02) //expect integer
  344. return 0;
  345. bt = binr.ReadByte();
  346. if (bt == 0x81)
  347. count = binr.ReadByte(); // data size in next byte
  348. else
  349. if (bt == 0x82)
  350. {
  351. highbyte = binr.ReadByte(); // data size in next 2 bytes
  352. lowbyte = binr.ReadByte();
  353. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  354. count = BitConverter.ToInt32(modint, 0);
  355. }
  356. else
  357. {
  358. count = bt; // we already have the data size
  359. }
  360. while (binr.ReadByte() == 0x00)
  361. { //remove high order zeros in data
  362. count -= 1;
  363. }
  364. binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
  365. return count;
  366. }
  367. }
  368. }