CryptUtil.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. package com.platform.yijia.utils;
  2. import javax.crypto.*;
  3. import javax.crypto.spec.DESKeySpec;
  4. import javax.crypto.spec.DESedeKeySpec;
  5. import javax.crypto.spec.IvParameterSpec;
  6. import javax.crypto.spec.SecretKeySpec;
  7. import java.security.*;
  8. import java.security.spec.InvalidKeySpecException;
  9. public class CryptUtil {
  10. private CryptUtil() {
  11. }
  12. /**
  13. * 字符串进行加密
  14. */
  15. public static String useMD5(String passWord) {
  16. try {
  17. MessageDigest digest = MessageDigest.getInstance("MD5");
  18. digest.update(passWord.getBytes());
  19. return getHashString(digest);
  20. } catch (NoSuchAlgorithmException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. }
  24. return null;
  25. }
  26. private static String getHashString(MessageDigest digest) {
  27. StringBuilder builder = new StringBuilder();
  28. for (byte b : digest.digest()) {
  29. builder.append(Integer.toHexString((b >> 4) & 0xf));
  30. builder.append(Integer.toHexString(b & 0xf));
  31. }
  32. return builder.toString().toLowerCase();
  33. }
  34. /**
  35. * MD5 消息摘要,对输入的内容,进行唯一表示的计算
  36. *
  37. * @param data 原数据
  38. * @return byte[] 计算后的 MD5 值
  39. */
  40. public static byte[] md5(byte[] data) {
  41. byte[] ret = null;
  42. if (data != null) {
  43. try {
  44. // 创建 消息摘要对象
  45. MessageDigest messageDigest = MessageDigest.getInstance("MD5");
  46. ret = messageDigest.digest(data);
  47. } catch (NoSuchAlgorithmException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. return ret;
  52. }
  53. /**
  54. * SHA1 消息摘要,对输入的内容,进行唯一表示的计算
  55. *
  56. * @param data 原数据
  57. * @return byte[] 计算后的 SHA1 值
  58. */
  59. public static byte[] sha1(byte[] data) {
  60. byte[] ret = null;
  61. if (data != null) {
  62. try {
  63. // 创建 消息摘要对象
  64. MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
  65. ret = messageDigest.digest(data);
  66. } catch (NoSuchAlgorithmException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. return ret;
  71. }
  72. /**
  73. * RC4对称加密
  74. */
  75. public static byte[] HloveyRC4(byte[] aInput, byte[] aKey) {
  76. int[] iS = new int[256];
  77. byte[] iK = new byte[256];
  78. for (int i = 0; i < 256; i++) {
  79. iS[i] = i;
  80. }
  81. int j = 1;
  82. for (short i = 0; i < 256; i++) {
  83. iK[i] = aKey[(i % aKey.length)];
  84. }
  85. j = 0;
  86. for (int i = 0; i < 256; i++) {
  87. j = (j + iS[i] & 0xff + iK[i] & 0xff) % 256;
  88. int temp = iS[i];
  89. iS[i] = iS[j];
  90. iS[j] = temp;
  91. }
  92. int i = 0;
  93. j = 0;
  94. byte[] iOutputChar = new byte[aInput.length];
  95. for (int x = 0; x < iOutputChar.length; x++) {
  96. i = (i + 1) % 256;
  97. j = (j + iS[i] & 0xff) % 256;
  98. int temp = iS[i] & 0xff;
  99. iS[i] = iS[j];
  100. iS[j] = temp;
  101. int t = (iS[i] + (iS[j] & 0xff % 256)) % 256;
  102. int iY = iS[t] & 0xff;
  103. byte iCY = (byte) iY;
  104. iOutputChar[x] = (byte) (aInput[x] ^ iCY);
  105. }
  106. return iOutputChar;
  107. }
  108. /**
  109. * DES 的加密方法
  110. *
  111. * @param data 原始的数据
  112. * @param pwd 密码 8 个字节
  113. * @return byte[] 加密后的数据
  114. */
  115. public static byte[] desEncrypt(byte[] data, byte[] pwd) {
  116. byte[] ret = null;
  117. if (data != null && pwd != null && pwd.length == 8) {
  118. try {
  119. Cipher cipher = Cipher.getInstance("DES");
  120. SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
  121. SecretKey secretKey = secretKeyFactory.generateSecret(new DESKeySpec(pwd));
  122. // 代表当前是解密状态
  123. cipher.init(Cipher.DECRYPT_MODE, secretKey);
  124. ret = cipher.doFinal(data);
  125. } catch (NoSuchAlgorithmException e) {
  126. e.printStackTrace();
  127. } catch (NoSuchPaddingException e) {
  128. e.printStackTrace();
  129. } catch (InvalidKeySpecException e) {
  130. e.printStackTrace();
  131. } catch (InvalidKeyException e) {
  132. e.printStackTrace();
  133. } catch (BadPaddingException e) {
  134. e.printStackTrace();
  135. } catch (IllegalBlockSizeException e) {
  136. e.printStackTrace();
  137. }
  138. }
  139. return ret;
  140. }
  141. /**
  142. * DES 的解密方法
  143. *
  144. * @param enData 经过加密之后的数据
  145. * @param pwd 密码 8 个字节
  146. * @return byte[] 解密后的原数据
  147. */
  148. public static byte[] desDecrypt(byte[] enData, byte[] pwd) {
  149. byte[] ret = null;
  150. if (enData != null && pwd != null && pwd.length == 8) {
  151. try {
  152. Cipher cipher = Cipher.getInstance("DES");
  153. SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
  154. SecretKey secretKey = secretKeyFactory.generateSecret(new DESKeySpec(pwd));
  155. // 代表当前是解密状态
  156. cipher.init(Cipher.DECRYPT_MODE, secretKey);
  157. ret = cipher.doFinal(enData);
  158. } catch (NoSuchAlgorithmException e) {
  159. e.printStackTrace();
  160. } catch (NoSuchPaddingException e) {
  161. e.printStackTrace();
  162. } catch (InvalidKeySpecException e) {
  163. e.printStackTrace();
  164. } catch (InvalidKeyException e) {
  165. e.printStackTrace();
  166. } catch (BadPaddingException e) {
  167. e.printStackTrace();
  168. } catch (IllegalBlockSizeException e) {
  169. e.printStackTrace();
  170. }
  171. }
  172. return ret;
  173. }
  174. /**
  175. * DESede (3DES)加密方法
  176. *
  177. * @param data 原始数据
  178. * @param pwd 密码,长度 <= 24 个字节
  179. * @return byte[] 加密后的数据
  180. */
  181. public static byte[] desedeEncrypt(byte[] data, byte[] pwd) {
  182. byte[] ret = null;
  183. if (data != null && pwd != null) {
  184. int plen = pwd.length;
  185. // 确保密码是24 个字节
  186. if (plen < 24) {
  187. byte[] fully = new byte[24];
  188. System.arraycopy(pwd, 0, fully, 0, plen);
  189. pwd = fully;
  190. }
  191. try {
  192. Cipher cipher = Cipher.getInstance("DESede");
  193. SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
  194. SecretKey secretKey = secretKeyFactory.generateSecret(new DESedeKeySpec(pwd));
  195. // 代表当前是解密状态
  196. cipher.init(Cipher.ENCRYPT_MODE, secretKey);
  197. ret = cipher.doFinal(data);
  198. } catch (NoSuchAlgorithmException e) {
  199. e.printStackTrace();
  200. } catch (NoSuchPaddingException e) {
  201. e.printStackTrace();
  202. } catch (InvalidKeySpecException e) {
  203. e.printStackTrace();
  204. } catch (InvalidKeyException e) {
  205. e.printStackTrace();
  206. } catch (BadPaddingException e) {
  207. e.printStackTrace();
  208. } catch (IllegalBlockSizeException e) {
  209. e.printStackTrace();
  210. }
  211. }
  212. return ret;
  213. }
  214. /**
  215. * DESede (3DES)解密方法
  216. *
  217. * @param data 加密后数据
  218. * @param pwd 密码,长度 <= 24 个字节
  219. * @return byte[] 解密后的数据
  220. */
  221. public static byte[] desedeDecrypt(byte[] data, byte[] pwd) {
  222. byte[] ret = null;
  223. if (data != null && pwd != null) {
  224. int plen = pwd.length;
  225. // 确保密码是24 个字节
  226. if (plen < 24) {
  227. byte[] fully = new byte[24];
  228. System.arraycopy(pwd, 0, fully, 0, plen);
  229. pwd = fully;
  230. }
  231. try {
  232. Cipher cipher = Cipher.getInstance("DESede");
  233. SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
  234. SecretKey secretKey = secretKeyFactory.generateSecret(new DESedeKeySpec(pwd));
  235. // 代表当前是解密状态
  236. cipher.init(Cipher.DECRYPT_MODE, secretKey);
  237. ret = cipher.doFinal(data);
  238. } catch (NoSuchAlgorithmException e) {
  239. e.printStackTrace();
  240. } catch (NoSuchPaddingException e) {
  241. e.printStackTrace();
  242. } catch (InvalidKeySpecException e) {
  243. e.printStackTrace();
  244. } catch (InvalidKeyException e) {
  245. e.printStackTrace();
  246. } catch (BadPaddingException e) {
  247. e.printStackTrace();
  248. } catch (IllegalBlockSizeException e) {
  249. e.printStackTrace();
  250. }
  251. }
  252. return ret;
  253. }
  254. /**
  255. * 非对称加密
  256. * RSA 加密部分,加密的部分支持 PrivateKey 加密,同时也支持 Publickey 加密
  257. * 因为 Privatekey 实现 Key 接口,同时 Publickey 也实现了 Key 接口
  258. *
  259. * @param data 要加密的数据
  260. * @param key 秘钥
  261. * @return byte[] 加密后的字节数组
  262. */
  263. public static byte[] rsaEncrypt(byte[] data, Key key) {
  264. byte[] ret = null;
  265. if (data != null && key != null) {
  266. if (key instanceof PublicKey || key instanceof PrivateKey) {
  267. try {
  268. Cipher cipher = Cipher.getInstance("RSA");
  269. // 初始化操作
  270. cipher.init(Cipher.ENCRYPT_MODE, key);
  271. ret = cipher.doFinal(data);
  272. } catch (NoSuchAlgorithmException e) {
  273. e.printStackTrace();
  274. } catch (NoSuchPaddingException e) {
  275. e.printStackTrace();
  276. } catch (InvalidKeyException e) {
  277. e.printStackTrace();
  278. } catch (BadPaddingException e) {
  279. e.printStackTrace();
  280. } catch (IllegalBlockSizeException e) {
  281. e.printStackTrace();
  282. }
  283. }
  284. }
  285. return ret;
  286. }
  287. /**
  288. * 非对称加密
  289. * RSA 解密部分,解密的部分支持 PrivateKey 解密,同时也支持 Publickey 解密
  290. * 因为 Privatekey 实现 Key 接口,同时 Publickey 也实现了 Key 接口
  291. *
  292. * @param data RSA 加密后的数据
  293. * @param key 秘钥
  294. * @return byte[] 解密后的原数据
  295. */
  296. public static byte[] rsaDecrypt(byte[] data, Key key) {
  297. byte[] ret = null;
  298. if (data != null && key != null) {
  299. if (key instanceof PublicKey || key instanceof PrivateKey) {
  300. try {
  301. Cipher cipher = Cipher.getInstance("RSA");
  302. // 初始化操作
  303. cipher.init(Cipher.DECRYPT_MODE, key);
  304. ret = cipher.doFinal(data);
  305. } catch (NoSuchAlgorithmException e) {
  306. e.printStackTrace();
  307. } catch (NoSuchPaddingException e) {
  308. e.printStackTrace();
  309. } catch (InvalidKeyException e) {
  310. e.printStackTrace();
  311. } catch (BadPaddingException e) {
  312. e.printStackTrace();
  313. } catch (IllegalBlockSizeException e) {
  314. e.printStackTrace();
  315. }
  316. }
  317. }
  318. return ret;
  319. }
  320. /**
  321. * AES 加密
  322. * 采用 Cipher.getInstance("AES") 方式,并且直接指定密码的加密
  323. *
  324. * @param data 数据
  325. * @param pwd 密码,密码长度建议 16 个字节
  326. * @return byte[] 加密后的数据
  327. */
  328. public static byte[] aesEncrypt(byte[] data, byte[] pwd) {
  329. byte[] ret = null;
  330. if (data != null && pwd != null) {
  331. // 检测密码长度,进行补充操作
  332. int plen = pwd.length;
  333. if (plen < 16) { // 128 bit
  334. byte[] fully = new byte[16];
  335. System.arraycopy(pwd, 0, fully, 0, plen);
  336. pwd = fully;
  337. }
  338. try {
  339. // !!! AES 的加密,算法部分是支持多种形式的
  340. // 如果写的是 AES,那么对应的解密方法,使用的算法必须是 AES
  341. // !!! AES 的加密,还可以使用 AES/CBC/PKCS5Padding 这个算法
  342. // 对应的解密算法 必须使用 "AES/CBC/PKCS5Padding" 才可以解密
  343. Cipher cipher = Cipher.getInstance("AES");
  344. SecretKeySpec key = new SecretKeySpec(pwd, "AES");
  345. cipher.init(Cipher.ENCRYPT_MODE, key);
  346. ret = cipher.doFinal(data);
  347. } catch (NoSuchAlgorithmException e) {
  348. e.printStackTrace();
  349. } catch (NoSuchPaddingException e) {
  350. e.printStackTrace();
  351. } catch (InvalidKeyException e) {
  352. e.printStackTrace();
  353. } catch (BadPaddingException e) {
  354. e.printStackTrace();
  355. } catch (IllegalBlockSizeException e) {
  356. e.printStackTrace();
  357. }
  358. }
  359. return ret;
  360. }
  361. /**
  362. * AES 解密
  363. * 采用 Cipher.getInstance("AES") 方式,并且直接指定密码的加密
  364. *
  365. * @param data 需要解密的数据
  366. * @param pwd 密码,长度建议 16 个字节
  367. * @return byte[] 解密后的数据
  368. */
  369. public static byte[] aesDecrypt(byte[] data, byte[] pwd) {
  370. byte[] ret = null;
  371. if (data != null && pwd != null) {
  372. // 检测密码长度,进行补充操作
  373. int plen = pwd.length;
  374. if (plen < 16) { // 128 bit
  375. byte[] fully = new byte[16];
  376. System.arraycopy(pwd, 0, fully, 0, plen);
  377. pwd = fully;
  378. }
  379. try {
  380. // !!! AES 的加密,算法部分是支持多种形式的
  381. // 如果写的是 AES,那么对应的解密方法,使用的算法必须是 AES
  382. // !!! AES 的加密,还可以使用 AES/CBC/PKCS5Padding 这个算法
  383. // 对应的解密算法 必须使用 "AES/CBC/PKCS5Padding" 才可以解密
  384. Cipher cipher = Cipher.getInstance("AES");
  385. SecretKeySpec key = new SecretKeySpec(pwd, "AES");
  386. cipher.init(Cipher.DECRYPT_MODE, key);
  387. ret = cipher.doFinal(data);
  388. } catch (NoSuchAlgorithmException e) {
  389. e.printStackTrace();
  390. } catch (NoSuchPaddingException e) {
  391. e.printStackTrace();
  392. } catch (InvalidKeyException e) {
  393. e.printStackTrace();
  394. } catch (BadPaddingException e) {
  395. e.printStackTrace();
  396. } catch (IllegalBlockSizeException e) {
  397. e.printStackTrace();
  398. }
  399. }
  400. return ret;
  401. }
  402. /**
  403. * 使用密码和Iv两个参数来进行加密,可以理解为用两个密码进行加密
  404. * Iv 可以看做另外一个密码,对于解密而言,密码和Iv 同样要一致
  405. * 自定义填充方式的 AES 加密
  406. * 使加密的内容,强度更高
  407. *
  408. * @param data 要加密的数据
  409. * @param pwd 密码,长度 <= 16 个字节
  410. * @param ivData IvParameter
  411. * @return byte[] 加密后的数据
  412. */
  413. public static byte[] aesIvEncrypt(byte[] data, byte[] pwd, byte[] ivData) {
  414. byte[] ret = null;
  415. if (data != null && pwd != null && ivData != null) {
  416. int plen = pwd.length;
  417. if (plen < 16) { // 128 bit
  418. byte[] fully = new byte[16];
  419. System.arraycopy(pwd, 0, fully, 0, plen);
  420. pwd = fully;
  421. }
  422. plen = ivData.length;
  423. if (plen < 16) { // 128 bit
  424. byte[] fully = new byte[16];
  425. System.arraycopy(ivData, 0, fully, 0, plen);
  426. ivData = fully;
  427. }
  428. try {
  429. // 支持的算法
  430. // AES/CBC/PKCS5Padding
  431. // AES/ECB/PKCS5Padding
  432. // AES/CBC/NoPadding
  433. // AES/ECB/NoPadding
  434. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  435. SecretKeySpec keySpec = new SecretKeySpec(pwd, "AES");
  436. // 使用 Iv 增加 AES 的加密强度,参数必须是 16 个字节
  437. IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
  438. // Iv 就是AES 中,另一套密码
  439. cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
  440. ret = cipher.doFinal(data);
  441. } catch (NoSuchAlgorithmException e) {
  442. e.printStackTrace();
  443. } catch (NoSuchPaddingException e) {
  444. e.printStackTrace();
  445. } catch (InvalidAlgorithmParameterException e) {
  446. e.printStackTrace();
  447. } catch (InvalidKeyException e) {
  448. e.printStackTrace();
  449. } catch (BadPaddingException e) {
  450. e.printStackTrace();
  451. } catch (IllegalBlockSizeException e) {
  452. e.printStackTrace();
  453. }
  454. }
  455. return ret;
  456. }
  457. /**
  458. * 使用密码和Iv两个参数来进行解密,可以理解为用两个密码进行加密
  459. * Iv 可以看做另外一个密码,对于解密而言,密码和Iv 同样要一致
  460. * 自定义填充方式的 AES 加密
  461. * 使加密的内容,强度更高
  462. *
  463. * @param data 需要进行解密的数据
  464. * @param pwd 密码,长度 <= 16 个字节
  465. * @param ivData IvParameter
  466. * @return byte[] 解密后的原数据
  467. */
  468. public static byte[] aesIvDecrypt(byte[] data, byte[] pwd, byte[] ivData) {
  469. byte[] ret = null;
  470. if (data != null && pwd != null && ivData != null) {
  471. int plen = pwd.length;
  472. if (plen < 16) { // 128 bit
  473. byte[] fully = new byte[16];
  474. System.arraycopy(pwd, 0, fully, 0, plen);
  475. pwd = fully;
  476. }
  477. plen = ivData.length;
  478. if (plen < 16) { // 128 bit
  479. byte[] fully = new byte[16];
  480. System.arraycopy(ivData, 0, fully, 0, plen);
  481. ivData = fully;
  482. }
  483. try {
  484. // 支持的算法
  485. // AES/CBC/PKCS5Padding
  486. // AES/ECB/PKCS5Padding
  487. // AES/CBC/NoPadding
  488. // AES/ECB/NoPadding
  489. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  490. SecretKeySpec keySpec = new SecretKeySpec(pwd, "AES");
  491. // 使用 Iv 增加 AES 的加密强度,参数必须是 16 个字节
  492. IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
  493. // Iv 就是AES 中,另一套密码
  494. cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
  495. ret = cipher.doFinal(data);
  496. } catch (NoSuchAlgorithmException e) {
  497. e.printStackTrace();
  498. } catch (NoSuchPaddingException e) {
  499. e.printStackTrace();
  500. } catch (InvalidAlgorithmParameterException e) {
  501. e.printStackTrace();
  502. } catch (InvalidKeyException e) {
  503. e.printStackTrace();
  504. } catch (BadPaddingException e) {
  505. e.printStackTrace();
  506. } catch (IllegalBlockSizeException e) {
  507. e.printStackTrace();
  508. }
  509. }
  510. return ret;
  511. }
  512. }