Cryptography.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #region Apache License Version 2.0
  2. /*----------------------------------------------------------------
  3. Copyright 2019 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
  4. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5. except in compliance with the License. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software distributed under the
  8. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  9. either express or implied. See the License for the specific language governing permissions
  10. and limitations under the License.
  11. Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
  12. ----------------------------------------------------------------*/
  13. #endregion Apache License Version 2.0
  14. /*----------------------------------------------------------------
  15. 文件名:Cryptography.cs
  16. 文件功能描述:加解密算法
  17. 创建标识:Senparc - 20150211
  18. 修改标识:Senparc - 20150303
  19. 修改描述:整理接口
  20. 修改标识:Senparc - 20170522
  21. 修改描述:v6.3.2 修改TenPayUtil.GetNoncestr()方法,将编码由GBK改为UTF8
  22. ----------------------------------------------------------------*/
  23. using System;
  24. using System.IO;
  25. using System.Net;
  26. using System.Security.Cryptography;
  27. using System.Text;
  28. namespace Senparc.Weixin.Tencent
  29. {
  30. public class Cryptography
  31. {
  32. public static UInt32 HostToNetworkOrder(UInt32 inval)
  33. {
  34. UInt32 outval = 0;
  35. for (int i = 0; i < 4; i++)
  36. outval = (outval << 8) + ((inval >> (i * 8)) & 255);
  37. return outval;
  38. }
  39. public static Int32 HostToNetworkOrder(Int32 inval)
  40. {
  41. Int32 outval = 0;
  42. for (int i = 0; i < 4; i++)
  43. outval = (outval << 8) + ((inval >> (i * 8)) & 255);
  44. return outval;
  45. }
  46. /// <summary>
  47. /// 解密方法
  48. /// </summary>
  49. /// <param name="Input">密文</param>
  50. /// <param name="EncodingAESKey"></param>
  51. /// <returns></returns>
  52. ///
  53. public static string AES_decrypt(String Input, string EncodingAESKey, ref string appid)
  54. {
  55. byte[] Key;
  56. Key = Convert.FromBase64String(EncodingAESKey + "=");
  57. byte[] Iv = new byte[16];
  58. Array.Copy(Key, Iv, 16);
  59. byte[] btmpMsg = AES_decrypt(Input, Iv, Key);
  60. int len = BitConverter.ToInt32(btmpMsg, 16);
  61. len = IPAddress.NetworkToHostOrder(len);
  62. byte[] bMsg = new byte[len];
  63. byte[] bAppid = new byte[btmpMsg.Length - 20 - len];
  64. Array.Copy(btmpMsg, 20, bMsg, 0, len);
  65. Array.Copy(btmpMsg, 20 + len, bAppid, 0, btmpMsg.Length - 20 - len);
  66. string oriMsg = Encoding.UTF8.GetString(bMsg);
  67. appid = Encoding.UTF8.GetString(bAppid);
  68. return oriMsg;
  69. }
  70. public static String AES_encrypt(String Input, string EncodingAESKey, string appid)
  71. {
  72. byte[] Key;
  73. Key = Convert.FromBase64String(EncodingAESKey + "=");
  74. byte[] Iv = new byte[16];
  75. Array.Copy(Key, Iv, 16);
  76. string Randcode = CreateRandCode(16);
  77. byte[] bRand = Encoding.UTF8.GetBytes(Randcode);
  78. byte[] bAppid = Encoding.UTF8.GetBytes(appid);
  79. byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);
  80. byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));
  81. byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppid.Length + btmpMsg.Length];
  82. Array.Copy(bRand, bMsg, bRand.Length);
  83. Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
  84. Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
  85. Array.Copy(bAppid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bAppid.Length);
  86. return AES_encrypt(bMsg, Iv, Key);
  87. }
  88. private static string CreateRandCode(int codeLen)
  89. {
  90. string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";
  91. if (codeLen == 0)
  92. {
  93. codeLen = 16;
  94. }
  95. string[] arr = codeSerial.Split(',');
  96. string code = "";
  97. int randValue = -1;
  98. Random rand = new Random(unchecked((int)SystemTime.Now.Ticks));
  99. for (int i = 0; i < codeLen; i++)
  100. {
  101. randValue = rand.Next(0, arr.Length - 1);
  102. code += arr[randValue];
  103. }
  104. return code;
  105. }
  106. private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
  107. {
  108. #if NET35 || NET40 || NET45
  109. var aes = new RijndaelManaged();
  110. #else
  111. var aes = Aes.Create();
  112. #endif
  113. //秘钥的大小,以位为单位
  114. aes.KeySize = 256;
  115. //支持的块大小
  116. aes.BlockSize = 128;
  117. //填充模式
  118. aes.Padding = PaddingMode.PKCS7;
  119. aes.Mode = CipherMode.CBC;
  120. aes.Key = Key;
  121. aes.IV = Iv;
  122. var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
  123. byte[] xBuff = null;
  124. using (var ms = new MemoryStream())
  125. {
  126. using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
  127. {
  128. byte[] xXml = Encoding.UTF8.GetBytes(Input);
  129. cs.Write(xXml, 0, xXml.Length);
  130. }
  131. xBuff = ms.ToArray();
  132. }
  133. String Output = Convert.ToBase64String(xBuff);
  134. return Output;
  135. }
  136. private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
  137. {
  138. #if NET35 || NET40 || NET45
  139. var aes = new RijndaelManaged();
  140. #else
  141. var aes = Aes.Create();
  142. #endif
  143. //秘钥的大小,以位为单位
  144. aes.KeySize = 256;
  145. //支持的块大小
  146. aes.BlockSize = 128;
  147. //填充模式
  148. //aes.Padding = PaddingMode.PKCS7;
  149. aes.Padding = PaddingMode.None;
  150. aes.Mode = CipherMode.CBC;
  151. aes.Key = Key;
  152. aes.IV = Iv;
  153. var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
  154. byte[] xBuff = null;
  155. #region 自己进行PKCS7补位,用系统自己带的不行
  156. byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
  157. Array.Copy(Input, msg, Input.Length);
  158. byte[] pad = KCS7Encoder(Input.Length);
  159. Array.Copy(pad, 0, msg, Input.Length, pad.Length);
  160. #endregion
  161. #region 注释的也是一种方法,效果一样
  162. //ICryptoTransform transform = aes.CreateEncryptor();
  163. //byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
  164. #endregion
  165. using (var ms = new MemoryStream())
  166. {
  167. using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
  168. {
  169. cs.Write(msg, 0, msg.Length);
  170. }
  171. xBuff = ms.ToArray();
  172. }
  173. String Output = Convert.ToBase64String(xBuff);
  174. return Output;
  175. }
  176. private static byte[] KCS7Encoder(int text_length)
  177. {
  178. int block_size = 32;
  179. // 计算需要填充的位数
  180. int amount_to_pad = block_size - (text_length % block_size);
  181. if (amount_to_pad == 0)
  182. {
  183. amount_to_pad = block_size;
  184. }
  185. // 获得补位所用的字符
  186. char pad_chr = chr(amount_to_pad);
  187. string tmp = "";
  188. for (int index = 0; index < amount_to_pad; index++)
  189. {
  190. tmp += pad_chr;
  191. }
  192. return Encoding.UTF8.GetBytes(tmp);
  193. }
  194. /**
  195. * 将数字转化成ASCII码对应的字符,用于对明文进行补码
  196. *
  197. * @param a 需要转化的数字
  198. * @return 转化得到的字符
  199. */
  200. static char chr(int a)
  201. {
  202. byte target = (byte)(a & 0xFF);
  203. return (char)target;
  204. }
  205. private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
  206. {
  207. #if NET35 || NET40 || NET45
  208. var aes = new RijndaelManaged();
  209. #else
  210. var aes = Aes.Create();
  211. #endif
  212. aes.KeySize = 128;//原始:256
  213. aes.BlockSize = 128;
  214. aes.Mode = CipherMode.CBC;
  215. aes.Padding = PaddingMode.None;
  216. aes.Key = Key;
  217. aes.IV = Iv;
  218. var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
  219. byte[] xBuff = null;
  220. using (var ms = new MemoryStream())
  221. {
  222. using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
  223. {
  224. byte[] xXml = Convert.FromBase64String(Input);
  225. byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
  226. Array.Copy(xXml, msg, xXml.Length);
  227. cs.Write(xXml, 0, xXml.Length);
  228. }
  229. xBuff = decode2(ms.ToArray());
  230. }
  231. return xBuff;
  232. }
  233. private static byte[] decode2(byte[] decrypted)
  234. {
  235. int pad = (int)decrypted[decrypted.Length - 1];
  236. if (pad < 1 || pad > 32)
  237. {
  238. pad = 0;
  239. }
  240. byte[] res = new byte[decrypted.Length - pad];
  241. Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
  242. return res;
  243. }
  244. }
  245. }