Base64Util.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace ProjectBase.Data.Encrypt
  7. {
  8. /// <summary>
  9. /// 基于Base64的加密编码辅助类,
  10. /// 可以设置不同的密码表来获取不同的编码与解码
  11. /// </summary>
  12. public class Base64Util
  13. {
  14. /// <summary>
  15. /// 构造函数,初始化编码表
  16. /// </summary>
  17. public Base64Util()
  18. {
  19. this.InitDict();
  20. }
  21. protected static Base64Util s_b64 = new Base64Util();
  22. /// <summary>
  23. /// 使用默认的密码表加密字符串
  24. /// </summary>
  25. /// <param name="input">待加密字符串</param>
  26. /// <returns></returns>
  27. public static string Encrypt(string input)
  28. {
  29. return s_b64.Encode(input);
  30. }
  31. /// <summary>
  32. /// 使用默认的密码表解密字符串
  33. /// </summary>
  34. /// <param name="input">待解密字符串</param>
  35. /// <returns></returns>
  36. public static string Decrypt(string input)
  37. {
  38. return s_b64.Decode(input);
  39. }
  40. /// <summary>
  41. /// 获取具有标准的Base64密码表的加密类
  42. /// </summary>
  43. /// <returns></returns>
  44. public static Base64Util GetStandardBase64()
  45. {
  46. Base64Util b64 = new Base64Util();
  47. b64.Pad = "=";
  48. b64.CodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  49. return b64;
  50. }
  51. protected string m_codeTable = @"ABCDEFGHIJKLMNOPQRSTUVWXYZbacdefghijklmnopqrstu_wxyz0123456789*-";
  52. protected string m_pad = "v";
  53. protected Dictionary<int, char> m_t1 = new Dictionary<int, char>();
  54. protected Dictionary<char, int> m_t2 = new Dictionary<char, int>();
  55. /// <summary>
  56. /// 密码表
  57. /// </summary>
  58. public string CodeTable
  59. {
  60. get { return m_codeTable; }
  61. set
  62. {
  63. if (value == null)
  64. {
  65. throw new Exception("密码表不能为null");
  66. }
  67. else if (value.Length < 64)
  68. {
  69. throw new Exception("密码表长度必须至少为64");
  70. }
  71. else
  72. {
  73. this.ValidateRepeat(value);
  74. this.ValidateEqualPad(value, m_pad);
  75. m_codeTable = value;
  76. this.InitDict();
  77. }
  78. }
  79. }
  80. /// <summary>
  81. /// 补码
  82. /// </summary>
  83. public string Pad
  84. {
  85. get { return m_pad; }
  86. set
  87. {
  88. if (value == null)
  89. {
  90. throw new Exception("密码表的补码不能为null");
  91. }
  92. else if (value.Length != 1)
  93. {
  94. throw new Exception("密码表的补码长度必须为1");
  95. }
  96. else
  97. {
  98. this.ValidateEqualPad(m_codeTable, value);
  99. m_pad = value;
  100. this.InitDict();
  101. }
  102. }
  103. }
  104. /// <summary>
  105. /// 返回编码后的字符串
  106. /// </summary>
  107. /// <param name="source">原字符串</param>
  108. /// <returns></returns>
  109. public string Encode(string source)
  110. {
  111. if (source == null || source == "")
  112. {
  113. return "";
  114. }
  115. else
  116. {
  117. StringBuilder sb = new StringBuilder();
  118. byte[] tmp = System.Text.UTF8Encoding.UTF8.GetBytes(source);
  119. int remain = tmp.Length % 3;
  120. int patch = 3 - remain;
  121. if (remain != 0)
  122. {
  123. Array.Resize(ref tmp, tmp.Length + patch);
  124. }
  125. int cnt = (int)Math.Ceiling(tmp.Length * 1.0 / 3);
  126. for (int i = 0; i < cnt; i++)
  127. {
  128. sb.Append(this.EncodeUnit(tmp[i * 3], tmp[i * 3 + 1], tmp[i * 3 + 2]));
  129. }
  130. if (remain != 0)
  131. {
  132. sb.Remove(sb.Length - patch, patch);
  133. for (int i = 0; i < patch; i++)
  134. {
  135. sb.Append(m_pad);
  136. }
  137. }
  138. return sb.ToString();
  139. }
  140. }
  141. protected string EncodeUnit(params byte[] unit)
  142. {
  143. int[] obj = new int[4];
  144. obj[0] = (unit[0] & 0xfc) >> 2;
  145. obj[1] = ((unit[0] & 0x03) << 4) + ((unit[1] & 0xf0) >> 4);
  146. obj[2] = ((unit[1] & 0x0f) << 2) + ((unit[2] & 0xc0) >> 6);
  147. obj[3] = unit[2] & 0x3f;
  148. StringBuilder sb = new StringBuilder();
  149. for (int i = 0; i < obj.Length; i++)
  150. {
  151. sb.Append(this.GetEC((int)obj[i]));
  152. }
  153. return sb.ToString();
  154. }
  155. protected char GetEC(int code)
  156. {
  157. return m_t1[code];//m_codeTable[code];
  158. }
  159. /// <summary>
  160. /// 获得解码字符串
  161. /// </summary>
  162. /// <param name="source">原字符串</param>
  163. /// <returns></returns>
  164. public string Decode(string source)
  165. {
  166. if (source == null || source == "")
  167. {
  168. return "";
  169. }
  170. else
  171. {
  172. List<byte> list = new List<byte>();
  173. char[] tmp = source.ToCharArray();
  174. int remain = tmp.Length % 4;
  175. if (remain != 0)
  176. {
  177. Array.Resize(ref tmp, tmp.Length - remain);
  178. }
  179. int patch = source.IndexOf(m_pad);
  180. if (patch != -1)
  181. {
  182. patch = source.Length - patch;
  183. }
  184. int cnt = tmp.Length / 4;
  185. for (int i = 0; i < cnt; i++)
  186. {
  187. this.DecodeUnit(list, tmp[i * 4], tmp[i * 4 + 1], tmp[i * 4 + 2], tmp[i * 4 + 3]);
  188. }
  189. for (int i = 0; i < patch; i++)
  190. {
  191. list.RemoveAt(list.Count - 1);
  192. }
  193. return System.Text.Encoding.UTF8.GetString(list.ToArray());
  194. }
  195. }
  196. protected void DecodeUnit(List<byte> byteArr, params char[] chArray)
  197. {
  198. int[] res = new int[3];
  199. byte[] unit = new byte[chArray.Length];
  200. for (int i = 0; i < chArray.Length; i++)
  201. {
  202. unit[i] = this.FindChar(chArray[i]);
  203. }
  204. res[0] = (unit[0] << 2) + ((unit[1] & 0x30) >> 4);
  205. res[1] = ((unit[1] & 0xf) << 4) + ((unit[2] & 0x3c) >> 2);
  206. res[2] = ((unit[2] & 0x3) << 6) + unit[3];
  207. for (int i = 0; i < res.Length; i++)
  208. {
  209. byteArr.Add((byte)res[i]);
  210. }
  211. }
  212. protected byte FindChar(char ch)
  213. {
  214. int pos = m_t2[ch];//m_codeTable.IndexOf(ch);
  215. return (byte)pos;
  216. }
  217. /// <summary>
  218. /// 初始化双向哈希字典
  219. /// </summary>
  220. protected void InitDict()
  221. {
  222. m_t1.Clear();
  223. m_t2.Clear();
  224. m_t2.Add(m_pad[0], -1);
  225. for (int i = 0; i < m_codeTable.Length; i++)
  226. {
  227. m_t1.Add(i, m_codeTable[i]);
  228. m_t2.Add(m_codeTable[i], i);
  229. }
  230. }
  231. /// <summary>
  232. /// 检查字符串中的字符是否有重复
  233. /// </summary>
  234. /// <param name="input">待检查字符串</param>
  235. /// <returns></returns>
  236. protected void ValidateRepeat(string input)
  237. {
  238. for (int i = 0; i < input.Length; i++)
  239. {
  240. if (input.LastIndexOf(input[i]) > i)
  241. {
  242. throw new Exception("密码表中含有重复字符:" + input[i]);
  243. }
  244. }
  245. }
  246. /// <summary>
  247. /// 检查字符串是否包含补码字符
  248. /// </summary>
  249. /// <param name="input">待检查字符串</param>
  250. /// <param name="pad"></param>
  251. protected void ValidateEqualPad(string input, string pad)
  252. {
  253. if (input.IndexOf(pad) > -1)
  254. {
  255. throw new Exception("密码表中包含了补码字符:" + pad);
  256. }
  257. }
  258. /// <summary>
  259. /// 测试
  260. /// </summary>
  261. protected void Test()
  262. {
  263. //m_codeTable = @"STUVWXYZbacdefghivklABCDEFGHIJKLMNOPQRmnopqrstu!wxyz0123456789+/";
  264. //m_pad = "j";
  265. this.InitDict();
  266. string test = "abc ABC 你好!◎#¥%……!@#$%^";
  267. string encode = this.Encode("false");
  268. string decode = this.Decode(encode);
  269. Console.WriteLine(encode);
  270. Console.WriteLine(test == decode);
  271. }
  272. }
  273. }