AESUtils.java 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package com.huaxu.util;
  2. import sun.misc.BASE64Decoder;
  3. import sun.misc.BASE64Encoder;
  4. import javax.crypto.Cipher;
  5. import javax.crypto.KeyGenerator;
  6. import javax.crypto.SecretKey;
  7. import java.io.*;
  8. import java.security.SecureRandom;
  9. import java.util.Date;
  10. /**
  11. * AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥长度,并且用128位分组长度加密和解密数据。
  12. * AES的加密过程:对数据的加密过程是通过把输入的明文和密钥由轮函数经N轮迭代来实现的,结尾轮与前N-1轮不同。
  13. * 前N-1轮依次进行S盒变换、行移位变换、列混淆变换和轮密钥加变换;第N轮与前N-1轮相比去掉了列混淆变换
  14. * @author lihui
  15. * @since 2021-03-23
  16. */
  17. public class AESUtils {
  18. /** 密钥长度: 128, 192 or 256 */
  19. private static final int KEY_SIZE = 128;
  20. /** 加密/解密算法名称 */
  21. private static final String ALGORITHM = "AES";
  22. /** 随机数生成器(RNG)算法名称 */
  23. private static final String RNG_ALGORITHM = "SHA1PRNG";
  24. /** 允许最大的时间差 */
  25. private static final int MAX_TIME = 1;
  26. /**
  27. * 生成密钥对象
  28. */
  29. private static SecretKey generateKey(byte[] key) throws Exception {
  30. // 创建安全随机数生成器
  31. SecureRandom random = SecureRandom.getInstance(RNG_ALGORITHM);
  32. // 设置 密钥key的字节数组 作为安全随机数生成器的种子
  33. random.setSeed(key);
  34. // 创建 AES算法生成器
  35. KeyGenerator gen = KeyGenerator.getInstance(ALGORITHM);
  36. // 初始化算法生成器
  37. gen.init(KEY_SIZE, random);
  38. // 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);
  39. return gen.generateKey();
  40. }
  41. /**
  42. * 数据加密: 明文 -> 密文
  43. */
  44. public static byte[] encryptBye(byte[] plainBytes, byte[] key) throws Exception {
  45. // 生成密钥对象
  46. SecretKey secKey = generateKey(key);
  47. // 获取 AES 密码器
  48. Cipher cipher = Cipher.getInstance(ALGORITHM);
  49. // 初始化密码器(加密模型)
  50. cipher.init(Cipher.ENCRYPT_MODE, secKey);
  51. // 加密数据, 返回密文
  52. byte[] cipherBytes = cipher.doFinal(plainBytes);
  53. return cipherBytes;
  54. }
  55. /**
  56. * 数据加密: 明文 -> 密文
  57. */
  58. public static String encryptString(byte[] plainBytes, byte[] key) throws Exception {
  59. return new BASE64Encoder().encode(encryptBye(plainBytes, key));
  60. }
  61. /**
  62. * 数据解密: 密文 -> 明文
  63. */
  64. public static byte[] decryptByte(byte[] cipherBytes, byte[] key) throws Exception {
  65. // 生成密钥对象
  66. SecretKey secKey = generateKey(key);
  67. // 获取 AES 密码器
  68. Cipher cipher = Cipher.getInstance(ALGORITHM);
  69. // 初始化密码器(解密模型)
  70. cipher.init(Cipher.DECRYPT_MODE, secKey);
  71. // 解密数据, 返回明文
  72. byte[] plainBytes = cipher.doFinal(cipherBytes);
  73. return plainBytes;
  74. }
  75. /**
  76. * 数据解密: 密文 -> 明文
  77. */
  78. public static String decryptString(String cipherString, String key) throws Exception {
  79. return new String(decryptByte(new BASE64Decoder().decodeBuffer(cipherString), key.getBytes()), "utf-8");
  80. }
  81. /**
  82. * 数据验证:
  83. * 解密后的值再根据当前的时间进行加密
  84. * 是否等同于
  85. * 传过来的加密
  86. * @param date 加密的时间
  87. * @param text 明文
  88. * @param encryptValue 加密后内容
  89. * @param appSecret 秘钥
  90. */
  91. public static boolean verifyEncrypt(String encryptValue, String text, Long date, String appSecret) {
  92. try {
  93. // 获取当前时间
  94. long differ = Long.parseLong(DatesUtil.formatDate(new Date(), "yyyyMMddHHmm")) - date;
  95. if (differ > MAX_TIME || differ < 0) {
  96. return false;
  97. }
  98. // 重新组装key,验证加密是否相同
  99. String encryptValue2 = encryptString((text + "_" + date).getBytes(), appSecret.getBytes());
  100. return encryptValue2.equals(encryptValue);
  101. } catch (Exception e) {
  102. return false;
  103. }
  104. }
  105. /**
  106. * 加密文件: 明文输入 -> 密文输出
  107. */
  108. public static void encryptFile(File plainIn, File cipherOut, byte[] key) throws Exception {
  109. aesFile(plainIn, cipherOut, key, true);
  110. }
  111. /**
  112. * 解密文件: 密文输入 -> 明文输出
  113. */
  114. public static void decryptFile(File cipherIn, File plainOut, byte[] key) throws Exception {
  115. aesFile(plainOut, cipherIn, key, false);
  116. }
  117. /**
  118. * AES 加密/解密文件
  119. */
  120. private static void aesFile(File plainFile, File cipherFile, byte[] key, boolean isEncrypt) throws Exception {
  121. // 获取 AES 密码器
  122. Cipher cipher = Cipher.getInstance(ALGORITHM);
  123. // 生成密钥对象
  124. SecretKey secKey = generateKey(key);
  125. // 初始化密码器
  126. cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secKey);
  127. // 加密/解密数据
  128. InputStream in = null;
  129. OutputStream out = null;
  130. try {
  131. if (isEncrypt) {
  132. // 加密: 明文文件为输入, 密文文件为输出
  133. in = new FileInputStream(plainFile);
  134. out = new FileOutputStream(cipherFile);
  135. } else {
  136. // 解密: 密文文件为输入, 明文文件为输出
  137. in = new FileInputStream(cipherFile);
  138. out = new FileOutputStream(plainFile);
  139. }
  140. byte[] buf = new byte[1024];
  141. int len = -1;
  142. // 循环读取数据 加密/解密
  143. while ((len = in.read(buf)) != -1) {
  144. out.write(cipher.update(buf, 0, len));
  145. }
  146. out.write(cipher.doFinal()); // 最后需要收尾
  147. out.flush();
  148. } finally {
  149. close(in);
  150. close(out);
  151. }
  152. }
  153. private static void close(Closeable c) {
  154. if (c != null) {
  155. try {
  156. c.close();
  157. } catch (IOException e) {
  158. // nothing
  159. }
  160. }
  161. }
  162. public static void main(String[] args) throws Exception{
  163. String appId = "868083_1001_123456_202103241637"; // 原文内容
  164. String appSecret = "123456"; // AES加密/解密用的原始密码
  165. // 加密数据, 返回密文
  166. String cipherString = AESUtils.encryptString(appId.getBytes(), appSecret.getBytes());
  167. // 解密数据, 返回明文
  168. String plainString = AESUtils.decryptString(cipherString, appSecret);
  169. System.out.println(cipherString);
  170. System.out.println(plainString);
  171. //System.out.println(AESUtils.verifyEncrypt(cipherString, plainString, appSecret));
  172. }
  173. }