Cryptography.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6. namespace Common.Wechat
  7. {
  8. /// <summary>
  9. ///
  10. /// </summary>
  11. public class Cryptography
  12. {
  13. public static UInt32 HostToNetworkOrder(UInt32 inval)
  14. {
  15. UInt32 outval = 0;
  16. for (int i = 0; i < 4; i++)
  17. outval = (outval << 8) + ((inval >> (i * 8)) & 255);
  18. return outval;
  19. }
  20. public static Int32 HostToNetworkOrder(Int32 inval)
  21. {
  22. Int32 outval = 0;
  23. for (int i = 0; i < 4; i++)
  24. outval = (outval << 8) + ((inval >> (i * 8)) & 255);
  25. return outval;
  26. }
  27. /// <summary>
  28. /// 解密方法
  29. /// </summary>
  30. /// <param name="Input">密文</param>
  31. /// <param name="EncodingAESKey"></param>
  32. /// <returns></returns>
  33. ///
  34. public static string AES_decrypt(String Input, string EncodingAESKey, ref string appid)
  35. {
  36. byte[] Key;
  37. Key = Convert.FromBase64String(EncodingAESKey + "=");
  38. byte[] Iv = new byte[16];
  39. Array.Copy(Key, Iv, 16);
  40. byte[] btmpMsg = AES_decrypt(Input, Iv, Key);
  41. int len = BitConverter.ToInt32(btmpMsg, 16);
  42. len = IPAddress.NetworkToHostOrder(len);
  43. byte[] bMsg = new byte[len];
  44. byte[] bAppid = new byte[btmpMsg.Length - 20 - len];
  45. Array.Copy(btmpMsg, 20, bMsg, 0, len);
  46. Array.Copy(btmpMsg, 20 + len, bAppid, 0, btmpMsg.Length - 20 - len);
  47. string oriMsg = Encoding.UTF8.GetString(bMsg);
  48. appid = Encoding.UTF8.GetString(bAppid);
  49. return oriMsg;
  50. }
  51. public static String AES_encrypt(String Input, string EncodingAESKey, string appid)
  52. {
  53. byte[] Key;
  54. Key = Convert.FromBase64String(EncodingAESKey + "=");
  55. byte[] Iv = new byte[16];
  56. Array.Copy(Key, Iv, 16);
  57. string Randcode = CreateRandCode(16);
  58. byte[] bRand = Encoding.UTF8.GetBytes(Randcode);
  59. byte[] bAppid = Encoding.UTF8.GetBytes(appid);
  60. byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);
  61. byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));
  62. byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppid.Length + btmpMsg.Length];
  63. Array.Copy(bRand, bMsg, bRand.Length);
  64. Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
  65. Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
  66. Array.Copy(bAppid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bAppid.Length);
  67. return AES_encrypt(bMsg, Iv, Key);
  68. }
  69. private static string CreateRandCode(int codeLen)
  70. {
  71. 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";
  72. if (codeLen == 0)
  73. {
  74. codeLen = 16;
  75. }
  76. string[] arr = codeSerial.Split(',');
  77. string code = "";
  78. int randValue = -1;
  79. Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
  80. for (int i = 0; i < codeLen; i++)
  81. {
  82. randValue = rand.Next(0, arr.Length - 1);
  83. code += arr[randValue];
  84. }
  85. return code;
  86. }
  87. private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
  88. {
  89. var aes = new RijndaelManaged();
  90. //秘钥的大小,以位为单位
  91. aes.KeySize = 256;
  92. //支持的块大小
  93. aes.BlockSize = 128;
  94. //填充模式
  95. aes.Padding = PaddingMode.PKCS7;
  96. aes.Mode = CipherMode.CBC;
  97. aes.Key = Key;
  98. aes.IV = Iv;
  99. var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
  100. byte[] xBuff = null;
  101. using (var ms = new MemoryStream())
  102. {
  103. using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
  104. {
  105. byte[] xXml = Encoding.UTF8.GetBytes(Input);
  106. cs.Write(xXml, 0, xXml.Length);
  107. }
  108. xBuff = ms.ToArray();
  109. }
  110. String Output = Convert.ToBase64String(xBuff);
  111. return Output;
  112. }
  113. private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
  114. {
  115. var aes = new RijndaelManaged();
  116. //秘钥的大小,以位为单位
  117. aes.KeySize = 256;
  118. //支持的块大小
  119. aes.BlockSize = 128;
  120. //填充模式
  121. //aes.Padding = PaddingMode.PKCS7;
  122. aes.Padding = PaddingMode.None;
  123. aes.Mode = CipherMode.CBC;
  124. aes.Key = Key;
  125. aes.IV = Iv;
  126. var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
  127. byte[] xBuff = null;
  128. #region 自己进行PKCS7补位,用系统自己带的不行
  129. byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
  130. Array.Copy(Input, msg, Input.Length);
  131. byte[] pad = KCS7Encoder(Input.Length);
  132. Array.Copy(pad, 0, msg, Input.Length, pad.Length);
  133. #endregion
  134. #region 注释的也是一种方法,效果一样
  135. //ICryptoTransform transform = aes.CreateEncryptor();
  136. //byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
  137. #endregion
  138. using (var ms = new MemoryStream())
  139. {
  140. using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
  141. {
  142. cs.Write(msg, 0, msg.Length);
  143. }
  144. xBuff = ms.ToArray();
  145. }
  146. String Output = Convert.ToBase64String(xBuff);
  147. return Output;
  148. }
  149. private static byte[] KCS7Encoder(int text_length)
  150. {
  151. int block_size = 32;
  152. // 计算需要填充的位数
  153. int amount_to_pad = block_size - (text_length % block_size);
  154. if (amount_to_pad == 0)
  155. {
  156. amount_to_pad = block_size;
  157. }
  158. // 获得补位所用的字符
  159. char pad_chr = chr(amount_to_pad);
  160. string tmp = "";
  161. for (int index = 0; index < amount_to_pad; index++)
  162. {
  163. tmp += pad_chr;
  164. }
  165. return Encoding.UTF8.GetBytes(tmp);
  166. }
  167. /**
  168. * 将数字转化成ASCII码对应的字符,用于对明文进行补码
  169. *
  170. * @param a 需要转化的数字
  171. * @return 转化得到的字符
  172. */
  173. static char chr(int a)
  174. {
  175. byte target = (byte)(a & 0xFF);
  176. return (char)target;
  177. }
  178. private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
  179. {
  180. RijndaelManaged aes = new RijndaelManaged();
  181. aes.KeySize = 256;
  182. aes.BlockSize = 128;
  183. aes.Mode = CipherMode.CBC;
  184. aes.Padding = PaddingMode.None;
  185. aes.Key = Key;
  186. aes.IV = Iv;
  187. var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
  188. byte[] xBuff = null;
  189. using (var ms = new MemoryStream())
  190. {
  191. using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
  192. {
  193. byte[] xXml = Convert.FromBase64String(Input);
  194. byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
  195. Array.Copy(xXml, msg, xXml.Length);
  196. cs.Write(xXml, 0, xXml.Length);
  197. }
  198. xBuff = decode2(ms.ToArray());
  199. }
  200. return xBuff;
  201. }
  202. private static byte[] decode2(byte[] decrypted)
  203. {
  204. int pad = (int)decrypted[decrypted.Length - 1];
  205. if (pad < 1 || pad > 32)
  206. {
  207. pad = 0;
  208. }
  209. byte[] res = new byte[decrypted.Length - pad];
  210. Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
  211. return res;
  212. }
  213. }
  214. }