SecurityBiz.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using System;
  2. using System.Collections.Generic;
  3. using Top.Api.Util;
  4. using System.Text;
  5. namespace Top.Api.Security
  6. {
  7. public class SecurityBiz : SecurityConstants
  8. {
  9. private static IDictionary<string, Nullable<char>> SEPARATOR_CHAR_MAP = InitSeparatorCharMap();
  10. private static IDictionary<string, string> SEPARATOR_MAP = InitSeparatorMap();
  11. private static IDictionary<string, Nullable<char>> InitSeparatorCharMap()
  12. {
  13. IDictionary<string, Nullable<char>> map = new Dictionary<string, Nullable<char>>();
  14. map.Add(NICK, SIMPLE_CHAR);
  15. map.Add(RECEIVER_NAME, SIMPLE_CHAR);
  16. map.Add(NORMAL, NORMAL_SEPARATOR_CHAR);
  17. map.Add(PHONE, PHONE_SEPARATOR_CHAR);
  18. map.Add(SIMPLE, SIMPLE_CHAR);
  19. map.Add(SEARCH, SIMPLE_CHAR);
  20. return map;
  21. }
  22. private static IDictionary<string, string> InitSeparatorMap()
  23. {
  24. IDictionary<string, string> map = new Dictionary<string, string>();
  25. map.Add(NICK, SIMPLE_SEPARATOR);
  26. map.Add(RECEIVER_NAME, SIMPLE_SEPARATOR);
  27. map.Add(NORMAL, NORMAL_SEPARATOR);
  28. map.Add(PHONE, PHONE_SEPARATOR);
  29. map.Add(SIMPLE, SIMPLE_SEPARATOR);
  30. map.Add(SEARCH, SIMPLE_SEPARATOR);
  31. return map;
  32. }
  33. public static IDictionary<string, Nullable<char>> GetSeparatorCharMap()
  34. {
  35. return SEPARATOR_CHAR_MAP;
  36. }
  37. public static IDictionary<string, string> GetSeparatorMap()
  38. {
  39. return SEPARATOR_MAP;
  40. }
  41. /// <summary>
  42. /// 判断是否密文数据
  43. /// </summary>
  44. /// <param name="data"></param>
  45. /// <param name="type">加密字段类型(例如:simple\phone)</param>
  46. /// <returns></returns>
  47. public static bool IsEncryptData(string data, string type)
  48. {
  49. if (string.IsNullOrEmpty(data) || data.Length < 4)
  50. {
  51. return false;
  52. }
  53. Nullable<char> charValue = null;
  54. SEPARATOR_CHAR_MAP.TryGetValue(type, out charValue);
  55. if (charValue == null)
  56. {
  57. throw new SecretException("type error");
  58. }
  59. char separatorChar = charValue.Value;
  60. if (!(data[0] == charValue && data[data.Length - 1] == charValue))
  61. {
  62. return false;
  63. }
  64. if (separatorChar == PHONE_SEPARATOR_CHAR)
  65. {
  66. // 拆分元素
  67. string[] dataArray = StringUtil.Split(data, separatorChar);
  68. if (dataArray.Length != 3)
  69. {
  70. return false;
  71. }
  72. if (data[data.Length - 2] == separatorChar)
  73. {
  74. return CheckEncryptData(dataArray);
  75. }
  76. else
  77. {
  78. string version = dataArray[dataArray.Length - 1];
  79. if (StringUtil.IsNumeric(version))
  80. {
  81. bool isBase64Value = SecurityUtil.IsBase64Value(dataArray[dataArray.Length - 2]);
  82. if (isBase64Value)
  83. {
  84. return true;
  85. }
  86. return false;
  87. }
  88. }
  89. }
  90. else
  91. {
  92. // 拆分元素
  93. string[] dataArray = StringUtil.Split(data, separatorChar);
  94. if (data[data.Length - 2] == separatorChar)
  95. {
  96. if (dataArray.Length != 3)
  97. {
  98. return false;
  99. }
  100. return CheckEncryptData(dataArray);
  101. }
  102. else
  103. {
  104. if (dataArray.Length != 2)
  105. {
  106. return false;
  107. }
  108. return CheckEncryptData(dataArray);
  109. }
  110. }
  111. return false;
  112. }
  113. /// <summary>
  114. /// 判断是否密文数据
  115. /// </summary>
  116. /// <param name="dataArray"></param>
  117. /// <returns></returns>
  118. private static bool CheckEncryptData(string[] dataArray)
  119. {
  120. string version = dataArray[dataArray.Length - 1];
  121. if (StringUtil.IsNumeric(version))
  122. {
  123. bool isBase64Value = SecurityUtil.IsBase64Value(dataArray[0]);
  124. if (isBase64Value)
  125. {
  126. if (dataArray.Length == 3)
  127. {
  128. isBase64Value = SecurityUtil.IsBase64Value(dataArray[1]);
  129. if (isBase64Value)
  130. {
  131. return true;
  132. }
  133. }
  134. else
  135. {
  136. return true;
  137. }
  138. }
  139. }
  140. return false;
  141. }
  142. /// <summary>
  143. /// 加密手机尾号后8位
  144. /// </summary>
  145. /// <param name="data"></param>
  146. /// <param name="separator"></param>
  147. /// <param name="secretContext"></param>
  148. /// <returns></returns>
  149. public static string EncryptPhone(string data, string separator, SecretContext secretContext)
  150. {
  151. if (data.Length < 11)
  152. {
  153. return data;
  154. }
  155. string prefixNumber = data.Substring(0, data.Length - 8);
  156. // 取后8位置
  157. string last8Number = data.Substring(data.Length - 8);
  158. return separator + prefixNumber + separator + SecurityUtil.AESEncrypt(last8Number, secretContext.Secret) + separator
  159. + secretContext.SecretVersion + separator;
  160. }
  161. /// <summary>
  162. /// 加密手机后4位转H-MAC
  163. /// </summary>
  164. /// <param name="data"></param>
  165. /// <param name="separator"></param>
  166. /// <param name="secretContext"></param>
  167. /// <returns></returns>
  168. public static string EncryptPhoneIndex(string data, string separator, SecretContext secretContext)
  169. {
  170. if (data.Length < 11)
  171. {
  172. return data;
  173. }
  174. // 取后4位
  175. string last4Number = data.Substring(data.Length - 4);
  176. return separator + SecurityUtil.HmacMD5EncryptToBase64(last4Number, secretContext.Secret) + separator
  177. + SecurityUtil.AESEncrypt(data, secretContext.Secret) + separator + secretContext.SecretVersion
  178. + separator + separator;
  179. }
  180. /// <summary>
  181. /// 手机号后4位H-MAC值
  182. /// </summary>
  183. /// <param name="data"></param>
  184. /// <param name="separator"></param>
  185. /// <param name="secretContext"></param>
  186. /// <returns></returns>
  187. public static string SearchPhoneIndex(string data, string separator, SecretContext secretContext)
  188. {
  189. if (data.Length != 4)
  190. {
  191. throw new SecretException("phoneNumber error");
  192. }
  193. return separator + SecurityUtil.HmacMD5EncryptToBase64(data, secretContext.Secret) + separator;
  194. }
  195. /// <summary>
  196. /// 生成密文数据
  197. /// </summary>
  198. /// <param name="data"></param>
  199. /// <param name="separator"></param>
  200. /// <param name="secretContext"></param>
  201. /// <returns></returns>
  202. public static string EncryptNormal(string data, string separator, SecretContext secretContext)
  203. {
  204. return separator + SecurityUtil.AESEncrypt(data, secretContext.Secret) + separator + secretContext.SecretVersion
  205. + separator;
  206. }
  207. /// <summary>
  208. /// 滑窗加密
  209. /// </summary>
  210. /// <param name="data"></param>
  211. /// <param name="compressLen"></param>
  212. /// <param name="slideSize"></param>
  213. /// <param name="separator"></param>
  214. /// <param name="secretContext"></param>
  215. /// <returns></returns>
  216. public static string EncryptNormalIndex(string data, int compressLen, int slideSize, string separator,
  217. SecretContext secretContext)
  218. {
  219. List<string> slideList = SecurityUtil.GetSlideWindows(data, slideSize);
  220. StringBuilder builder = new StringBuilder();
  221. foreach (string slide in slideList)
  222. {
  223. builder.Append(SecurityUtil.HmacMD5EncryptToBase64(slide, secretContext.Secret, compressLen));
  224. }
  225. return separator + SecurityUtil.AESEncrypt(data, secretContext.Secret) + separator + builder.ToString() + separator
  226. + secretContext.SecretVersion + separator + separator;
  227. }
  228. /// <summary>
  229. /// 密文检索
  230. /// </summary>
  231. /// <param name="data"></param>
  232. /// <param name="compressLen"></param>
  233. /// <param name="slideSize"></param>
  234. /// <param name="secretContext"></param>
  235. /// <returns></returns>
  236. public static string SearchNormalIndex(string data, int compressLen, int slideSize, SecretContext secretContext)
  237. {
  238. List<string> slideList = SecurityUtil.GetSlideWindows(data, slideSize);
  239. StringBuilder builder = new StringBuilder();
  240. foreach (string slide in slideList)
  241. {
  242. builder.Append(SecurityUtil.HmacMD5EncryptToBase64(slide, secretContext.Secret, compressLen));
  243. }
  244. return builder.ToString();
  245. }
  246. /// <summary>
  247. /// 获取秘钥版本、加密原始数据
  248. /// </summary>
  249. /// <param name="data"></param>
  250. /// <param name="separatorChar"></param>
  251. /// <returns></returns>
  252. public static SecretData GetSecretData(string data, char separatorChar)
  253. {
  254. SecretData secretData = null;
  255. if (PHONE_SEPARATOR_CHAR == separatorChar)
  256. {
  257. string[] dataArray = StringUtil.Split(data, separatorChar);
  258. if (dataArray.Length != 3)
  259. {
  260. return null;
  261. }
  262. string version = dataArray[2];
  263. if (StringUtil.IsNumeric(version))
  264. {
  265. secretData = new SecretData();
  266. secretData.OriginalValue = dataArray[0]; ;// 手机号码前缀
  267. secretData.OriginalBase64Value = dataArray[1];
  268. secretData.SecretVersion = Convert.ToInt64(version);
  269. }
  270. }
  271. else
  272. {
  273. string[] dataArray = StringUtil.Split(data, separatorChar);
  274. if (dataArray.Length != 2)
  275. {
  276. return null;
  277. }
  278. string version = dataArray[1];
  279. if (StringUtil.IsNumeric(version))
  280. {
  281. secretData = new SecretData();
  282. secretData.OriginalBase64Value = dataArray[0];
  283. secretData.SecretVersion = Convert.ToInt64(version);
  284. }
  285. }
  286. return secretData;
  287. }
  288. /// <summary>
  289. /// 获取秘钥版本、加密原始数据(支持密文检索)
  290. /// </summary>
  291. /// <param name="data"></param>
  292. /// <param name="separatorChar"></param>
  293. /// <returns></returns>
  294. public static SecretData GetIndexSecretData(string data, char separatorChar)
  295. {
  296. SecretData secretData = null;
  297. if (PHONE_SEPARATOR_CHAR == separatorChar)
  298. {
  299. string[] dataArray = StringUtil.Split(data, separatorChar);
  300. if (dataArray.Length != 3)
  301. {
  302. return null;
  303. }
  304. string version = dataArray[2];
  305. if (StringUtil.IsNumeric(version))
  306. {
  307. secretData = new SecretData();
  308. secretData.OriginalValue = dataArray[0];// H-MAC(手机号码后4位)
  309. secretData.OriginalBase64Value = dataArray[1];
  310. secretData.SecretVersion = Convert.ToInt64(version);
  311. }
  312. }
  313. else
  314. {
  315. string[] dataArray = StringUtil.Split(data, separatorChar);
  316. if (dataArray.Length != 3)
  317. {
  318. return null;
  319. }
  320. string version = dataArray[2];
  321. if (StringUtil.IsNumeric(version))
  322. {
  323. secretData = new SecretData();
  324. secretData.OriginalBase64Value = dataArray[0];
  325. secretData.OriginalValue = dataArray[1];// H-MAC value
  326. secretData.SecretVersion = Convert.ToInt64(version);
  327. }
  328. }
  329. if (secretData == null)
  330. {
  331. return secretData;
  332. }
  333. secretData.Search = true;
  334. return secretData;
  335. }
  336. }
  337. }