CodeUtil.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package com.happy.Unitil_elc;
  2. import javax.crypto.Cipher;
  3. import javax.crypto.spec.IvParameterSpec;
  4. import javax.crypto.spec.SecretKeySpec;
  5. import java.nio.charset.StandardCharsets;
  6. import java.security.MessageDigest;
  7. import java.security.NoSuchAlgorithmException;
  8. public class CodeUtil {
  9. /**
  10. * 解密
  11. * @param src 源数据
  12. * @param secret 秘钥
  13. * @param iv 初始化向量
  14. * @return String
  15. */
  16. public static String dataDecode(String src, String secret, String iv){
  17. try {
  18. // 判断Key是否正确
  19. if (secret == null) {
  20. System.out.print("Key为空null");
  21. return null;
  22. }
  23. // 判断Key是否为16位
  24. if (secret.length() != 16) {
  25. System.out.print("Key长度不是16位");
  26. return null;
  27. }
  28. byte[] raw = secret.getBytes(StandardCharsets.US_ASCII);
  29. SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
  30. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  31. IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
  32. cipher.init(Cipher.DECRYPT_MODE, skeySpec, ips);
  33. // byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
  34. byte[] encrypted1 = Base64.decode(src);
  35. try {
  36. byte[] original = cipher.doFinal(encrypted1);
  37. return new String(original, StandardCharsets.UTF_8);
  38. } catch (Exception e) {
  39. System.out.println(e.toString());
  40. return null;
  41. }
  42. } catch (Exception ex) {
  43. System.out.println(ex.toString());
  44. return null;
  45. }
  46. }
  47. /**
  48. * 加密
  49. * @param src 源数据
  50. * @param secret 秘钥
  51. * @param iv 初始化向量
  52. * @return String
  53. */
  54. public static String dataEncode(String src, String secret, String iv) throws Exception {
  55. if (secret == null) {
  56. System.out.print("Key为空null");
  57. return null;
  58. }
  59. // 判断Key是否为16位
  60. if (secret.length() != 16) {
  61. System.out.print("Key长度不是16位");
  62. return null;
  63. }
  64. byte[] raw = secret.getBytes(StandardCharsets.UTF_8);
  65. SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
  66. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
  67. IvParameterSpec ips = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
  68. cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ips);
  69. byte[] encrypted = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));
  70. // return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
  71. return Base64.encode(encrypted);
  72. }
  73. /**
  74. * 获取签名
  75. * @param src 源数据
  76. * @param signKey 签名秘钥
  77. * @return String
  78. */
  79. public static String getSign(String src,String signKey){
  80. String result = "";
  81. try {
  82. byte[] keyByte = signKey.getBytes(StandardCharsets.UTF_8);
  83. byte[] dataByte = src.getBytes(StandardCharsets.UTF_8);
  84. byte[] hmacMd5Byte = getHmacMd5Bytes(keyByte, dataByte);
  85. StringBuilder md5Str = new StringBuilder();
  86. for (byte b : hmacMd5Byte) {
  87. if (Integer.toHexString(0xFF & b).length() == 1) md5Str.append("0").append(Integer.toHexString(0xFF & b));
  88. else md5Str.append(Integer.toHexString(0xFF & b));
  89. }
  90. result = md5Str.toString().toUpperCase();
  91. } catch (Exception ignored) {
  92. }
  93. return result;
  94. }
  95. /**
  96. * 将待加密数据data,通过密钥key,使用hmac-md5算法进行加密,然后返回加密结果。 参照rfc2104 HMAC算法介绍实现。
  97. *
  98. * @author sc
  99. * @param key 密钥
  100. * @param data 待加密数据
  101. * @return 加密结果
  102. */
  103. private static byte[] getHmacMd5Bytes(byte[] key, byte[] data) throws NoSuchAlgorithmException {
  104. /*
  105. * HmacMd5 calculation formula: H(K XOR opad, H(K XOR ipad, text)) HmacMd5 计算公式:H(K XOR opad, H(K XOR ipad,
  106. * text)) H代表hash算法,本类中使用MD5算法,K代表密钥,text代表要加密的数据 ipad为0x36,opad为0x5C。
  107. */
  108. int length = 64;
  109. byte[] ipad = new byte[length];
  110. byte[] opad = new byte[length];
  111. for (int i = 0; i < 64; i++) {
  112. ipad[i] = 0x36;
  113. opad[i] = 0x5C;
  114. }
  115. byte[] actualKey = key; // Actual key.
  116. byte[] keyArr = new byte[length]; // Key bytes of 64 bytes length
  117. /*
  118. * If key's length is longer than 64,then use hash to digest it and use the result as actual key.
  119. * 如果密钥长度,大于64字节,就使用哈希算法,计算其摘要,作为真正的密钥。
  120. */
  121. if (key.length > length) {
  122. actualKey = md5(key);
  123. }
  124. System.arraycopy(actualKey, 0, keyArr, 0, actualKey.length);
  125. /*
  126. * append zeros to K 如果密钥长度不足64字节,就使用0x00补齐到64字节。
  127. */
  128. if (actualKey.length < length) {
  129. for (int i = actualKey.length; i < keyArr.length; i++)
  130. keyArr[i] = 0x00;
  131. }
  132. /*
  133. * calc K XOR ipad 使用密钥和ipad进行异或运算。
  134. */
  135. byte[] kIpadXorResult = new byte[length];
  136. for (int i = 0; i < length; i++) {
  137. kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
  138. }
  139. /*
  140. * append "text" to the end of "K XOR ipad" 将待加密数据追加到K XOR ipad计算结果后面。
  141. */
  142. byte[] firstAppendResult = new byte[kIpadXorResult.length + data.length];
  143. System.arraycopy(kIpadXorResult, 0, firstAppendResult, 0, kIpadXorResult.length);
  144. System.arraycopy(data, 0, firstAppendResult, keyArr.length, data.length);
  145. /*
  146. * calc H(K XOR ipad, text) 使用哈希算法计算上面结果的摘要。
  147. */
  148. byte[] firstHashResult = md5(firstAppendResult);
  149. /*
  150. * calc K XOR opad 使用密钥和opad进行异或运算。
  151. */
  152. byte[] kOpadXorResult = new byte[length];
  153. for (int i = 0; i < length; i++) {
  154. kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
  155. }
  156. /*
  157. * append "H(K XOR ipad, text)" to the end of "K XOR opad" 将H(K XOR ipad, text)结果追加到K XOR opad结果后面
  158. */
  159. byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
  160. System.arraycopy(kOpadXorResult, 0, secondAppendResult, 0, kOpadXorResult.length);
  161. System.arraycopy(firstHashResult, 0, secondAppendResult, keyArr.length, firstHashResult.length);
  162. /*
  163. * H(K XOR opad, H(K XOR ipad, text)) 对上面的数据进行哈希运算。
  164. */
  165. return md5(secondAppendResult);
  166. }
  167. /**
  168. * 计算参数的md5信息
  169. *
  170. * @param str 待处理的字节数组
  171. * @return md5摘要信息
  172. */
  173. private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
  174. MessageDigest md = MessageDigest.getInstance("MD5");
  175. md.update(str);
  176. return md.digest();
  177. }
  178. }