当前位置:   article > 正文

AES对称加密_aes key iv

aes key iv

AES对称加密,比DES安全性高。

AES通常用于移动通信系统加密以及基于SSH协议的软件。

AES对称加密:AES常用的有ECB和CBC两种模式。常用的填充方式有PKCS5Padding、PKCS7Padding、zeropadding
CBC模式比ECB模式安全,ECB模式比CBC模式快。 推荐使用CBC模式。
相同密码的加密结果不会变化,是固定的。
这个标准用来替代原先的DES

key的字节长度只能是16位、24位、32位。
iv的字节长度只能是16位。
KEY和IV可以相同,也可以不相同。
key和iv长度不足时,这里将以0x00自动填充,超出部分将被忽略。注意:其他系统不一定是这种逻辑,所以key建议设置为16/24/32位,iv设置为16位。

说明:AES数据块长度为128位(16字节),所以IV长度需要为16个字节(ECB模式不用IV),IV与KEY超过长度则截取,不足则在末尾填充'\0'补足

  1. package com.study;
  2. import com.sun.org.slf4j.internal.Logger;
  3. import com.sun.org.slf4j.internal.LoggerFactory;
  4. import javax.crypto.BadPaddingException;
  5. import javax.crypto.Cipher;
  6. import javax.crypto.IllegalBlockSizeException;
  7. import javax.crypto.NoSuchPaddingException;
  8. import javax.crypto.spec.IvParameterSpec;
  9. import javax.crypto.spec.SecretKeySpec;
  10. import java.nio.charset.StandardCharsets;
  11. import java.security.InvalidAlgorithmParameterException;
  12. import java.security.InvalidKeyException;
  13. import java.security.NoSuchAlgorithmException;
  14. import java.util.Base64;
  15. /**
  16. * AES对称加密:AES常用的有ECB和CBC两种模式。常用的填充方式有PKCS5Padding、PKCS7Padding、zeropadding
  17. * CBC模式比ECB模式安全,ECB模式比CBC模式快。 推荐使用CBC模式。
  18. * 相同密码的加密结果不会变化,是固定的。
  19. * 这个标准用来替代原先的DES
  20. * <p>
  21. * key的字节长度只能是16位、24位、32位。
  22. * iv的字节长度只能是16位。
  23. * KEY和IV可以相同,也可以不相同。
  24. * key和iv长度不足时,这里将以0x00自动填充,超出部分将被忽略。注意:其他系统不一定是这种逻辑,所以key建议设置为16/24/32位,iv设置为16位。
  25. * <p>
  26. * 说明:AES数据块长度为128位(16字节),所以IV长度需要为16个字节(ECB模式不用IV),IV与KEY超过长度则截取,不足则在末尾填充'\0'补足
  27. * @date 2019年12月23日 下午7:56:33
  28. */
  29. public class AESUtil {
  30. private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
  31. private static final String CBCMode = "AES/CBC/PKCS5Padding";//填充方式
  32. private static final String ECBMode = "AES/ECB/PKCS5Padding";//填充方式
  33. public static void main(String[] args) {
  34. String key = "1234567812345678";// key长度建议设置为16位或者24位或者32位。
  35. String iv = "1234567887654321";// iv长度建议设置为16位。
  36. String msg = "测试字符串";
  37. //CBC模式
  38. String cbcEncrypt = AESUtil.encryptCBC(msg, key, iv);
  39. System.out.println(cbcEncrypt);
  40. String cbcDecryptStr = AESUtil.decryptCBC(cbcEncrypt, key, iv);
  41. System.out.println(cbcDecryptStr);
  42. //ECB模式
  43. String ecbEncrypt = AESUtil.encryptECB(msg, key);
  44. System.out.println(ecbEncrypt);
  45. String decryptStr = AESUtil.decryptECB(ecbEncrypt, key);
  46. System.out.println(decryptStr);
  47. }
  48. /**
  49. * AES CBC 加密
  50. * @param message 需要加密的字符串
  51. * @param key 密匙
  52. * @param iv IV,需要和key长度相同
  53. * @return 返回加密后密文,编码为base64
  54. */
  55. public static String encryptCBC(String message, String key, String iv) {
  56. try {
  57. byte[] content = message.getBytes(StandardCharsets.UTF_8);
  58. byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
  59. keyByte = fillKey(keyByte);
  60. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  61. byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8);
  62. ivByte = fillIv(ivByte);
  63. IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
  64. Cipher cipher = Cipher.getInstance(CBCMode);
  65. cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
  66. byte[] data = cipher.doFinal(content);
  67. return Base64.getEncoder().encodeToString(data);
  68. } catch (NoSuchAlgorithmException e) {
  69. logger.error("没有这样的算法", e);
  70. } catch (NoSuchPaddingException e) {
  71. logger.error("没有这样的填充", e);
  72. } catch (InvalidKeyException e) {
  73. logger.error("无效的密钥", e);
  74. } catch (InvalidAlgorithmParameterException e) {
  75. logger.error("无效的算法参数", e);
  76. } catch (IllegalBlockSizeException e) {
  77. logger.error("非法块大小", e);
  78. } catch (BadPaddingException e) {
  79. logger.error("不良填充", e);
  80. }
  81. return null;
  82. }
  83. /**
  84. * AES CBC 解密
  85. * @param messageBase64 密文,base64编码
  86. * @param key 密匙,和加密时相同
  87. * @param iv IV,需要和key长度相同
  88. * @return 解密后数据
  89. */
  90. public static String decryptCBC(String messageBase64, String key, String iv) {
  91. try {
  92. byte[] messageByte = Base64.getDecoder().decode(messageBase64);
  93. byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
  94. keyByte = fillKey(keyByte);
  95. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  96. byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8);
  97. ivByte = fillIv(ivByte);
  98. IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
  99. Cipher cipher = Cipher.getInstance(CBCMode);
  100. cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
  101. byte[] content = cipher.doFinal(messageByte);
  102. return new String(content, StandardCharsets.UTF_8);
  103. } catch (NoSuchAlgorithmException e) {
  104. logger.error("没有这样的算法", e);
  105. } catch (NoSuchPaddingException e) {
  106. logger.error("没有这样的填充", e);
  107. } catch (InvalidKeyException e) {
  108. logger.error("无效的密钥", e);
  109. } catch (InvalidAlgorithmParameterException e) {
  110. logger.error("无效的算法参数", e);
  111. } catch (IllegalBlockSizeException e) {
  112. logger.error("非法块大小", e);
  113. } catch (BadPaddingException e) {
  114. logger.error("不良填充", e);
  115. }
  116. return null;
  117. }
  118. /**
  119. * AES ECB 加密
  120. * @param message 需要加密的字符串
  121. * @param key 密匙
  122. * @return 返回加密后密文,编码为base64
  123. */
  124. public static String encryptECB(String message, String key) {
  125. try {
  126. byte[] content = message.getBytes(StandardCharsets.UTF_8);
  127. byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
  128. keyByte = fillKey(keyByte);
  129. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  130. Cipher cipher = Cipher.getInstance(ECBMode);
  131. cipher.init(Cipher.ENCRYPT_MODE, keySpec);
  132. byte[] data = cipher.doFinal(content);
  133. return Base64.getEncoder().encodeToString(data);
  134. } catch (NoSuchAlgorithmException e) {
  135. logger.error("没有这样的算法", e);
  136. } catch (NoSuchPaddingException e) {
  137. logger.error("没有这样的填充", e);
  138. } catch (InvalidKeyException e) {
  139. logger.error("无效的密钥", e);
  140. } catch (IllegalBlockSizeException e) {
  141. logger.error("非法块大小", e);
  142. } catch (BadPaddingException e) {
  143. logger.error("不良填充", e);
  144. }
  145. return null;
  146. }
  147. /**
  148. * AES ECB 解密
  149. * @param messageBase64 密文,base64编码
  150. * @param key 密匙,和加密时相同
  151. * @return 解密后数据
  152. */
  153. public static String decryptECB(String messageBase64, String key) {
  154. try {
  155. byte[] messageByte = Base64.getDecoder().decode(messageBase64);
  156. byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
  157. keyByte = fillKey(keyByte);
  158. SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
  159. Cipher cipher = Cipher.getInstance(ECBMode);
  160. cipher.init(Cipher.DECRYPT_MODE, keySpec);
  161. byte[] content = cipher.doFinal(messageByte);
  162. return new String(content, StandardCharsets.UTF_8);
  163. } catch (NoSuchAlgorithmException e) {
  164. logger.error("没有这样的算法", e);
  165. } catch (NoSuchPaddingException e) {
  166. logger.error("没有这样的填充", e);
  167. } catch (InvalidKeyException e) {
  168. logger.error("无效的密钥", e);
  169. } catch (IllegalBlockSizeException e) {
  170. logger.error("非法块大小", e);
  171. } catch (BadPaddingException e) {
  172. logger.error("不良填充", e);
  173. }
  174. return null;
  175. }
  176. /**
  177. * 填充key
  178. * key的字节长度只能是16位、24位、32位。
  179. * key长度不足时,这里将以0x00填充,超出部分将被忽略。
  180. * @return 填充后的key
  181. */
  182. public static byte[] fillKey(byte[] keyByte) {
  183. int length = keyByte.length;
  184. int len;
  185. if (length == 16 || length == 24 || length == 32) {
  186. return keyByte;
  187. } else if (length < 16) {
  188. len = 16;
  189. } else if (length < 24) {
  190. len = 24;
  191. } else {
  192. len = 32;
  193. }
  194. byte[] newKeyByte = new byte[len];
  195. System.arraycopy(keyByte, 0, newKeyByte, 0, length < len ? length : len);
  196. return newKeyByte;
  197. }
  198. /**
  199. * 填充iv
  200. * iv的字节长度只能是16位。
  201. * iv长度不足时,这里将以0x00填充,超出部分将被忽略。
  202. * @return 填充后的iv
  203. */
  204. public static byte[] fillIv(byte[] ivByte) {
  205. int length = ivByte.length;
  206. int len;
  207. if (length == 16) {
  208. return ivByte;
  209. } else {
  210. len = 16;
  211. }
  212. byte[] newIvByte = new byte[len];
  213. System.arraycopy(ivByte, 0, newIvByte, 0, length < len ? length : len);
  214. return newIvByte;
  215. }
  216. }

AES GCM 模式

  1. package com.study;
  2. import org.apache.commons.codec.binary.Base64;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.util.StringUtils;
  6. import javax.crypto.Cipher;
  7. import javax.crypto.KeyGenerator;
  8. import javax.crypto.SecretKey;
  9. import javax.crypto.spec.GCMParameterSpec;
  10. import javax.crypto.spec.SecretKeySpec;
  11. import java.nio.charset.StandardCharsets;
  12. import java.security.NoSuchAlgorithmException;
  13. public class AESUtil {
  14. private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
  15. private static String gcm256algorithm = "AES/GCM/PKCS5Padding";
  16. public static void main(String[] args) {
  17. KeyGenerator generator = null;
  18. try {
  19. generator = KeyGenerator.getInstance("AES");
  20. //初始化密钥生成器,AES要求密钥长度为128位、192位、256位
  21. generator.init(256);
  22. SecretKey secretKey = generator.generateKey();
  23. // String gcmSecretKey = Base64.encodeBase64String(secretKey.getEncoded());
  24. String key = "1234567812345678";//key长度为16的倍数
  25. String gcmSecretKey = Base64.encodeBase64String(key.getBytes(StandardCharsets.UTF_8));
  26. System.out.println("生成密钥key: " + key + "\n");
  27. String toDoStr = "12345678";
  28. System.out.println("明文文本:" + toDoStr);
  29. String encryptResult = AEGCMEncrypt(toDoStr, gcmSecretKey);
  30. System.out.println("加密结果: " + encryptResult);
  31. String decryptResult = AEGCMDecrypt(encryptResult, gcmSecretKey);
  32. System.out.println("解密结果: " + decryptResult + "\n");
  33. } catch (NoSuchAlgorithmException e) {
  34. logger.error("密钥生成异常,error:", e);
  35. }
  36. }
  37. //解密
  38. public static String AEGCMDecrypt(String content, String keyStr) {
  39. try {
  40. if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
  41. throw new Exception("AESGCM256解密异常,检查文本或密钥");
  42. }
  43. Cipher cipher = Cipher.getInstance(gcm256algorithm);
  44. SecretKey key = new SecretKeySpec(Base64.decodeBase64(keyStr), "AES");
  45. cipher.init(Cipher.ENCRYPT_MODE, key);
  46. byte[] message = Base64.decodeBase64(content);
  47. // 这里的12和16是加密的时候设置的偏移参数及加密长度
  48. if (message.length < 12 + 16) throw new IllegalArgumentException();
  49. GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
  50. cipher.init(Cipher.DECRYPT_MODE, key, params);
  51. byte[] decryptData = cipher.doFinal(message, 12, message.length - 12);
  52. String decript = new String(decryptData);
  53. return decript;
  54. } catch (Exception e) {
  55. logger.error("AESGCM256解密文本处理失败,error:{}", e);
  56. }
  57. return null;
  58. }
  59. //加密
  60. public static String AEGCMEncrypt(String content, String keyStr) {
  61. try {
  62. if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
  63. throw new Exception("AESGCM256加密异常,检查文本或密钥");
  64. }
  65. SecretKey secretKey = new SecretKeySpec(Base64.decodeBase64(keyStr), "AES");
  66. Cipher cipher = Cipher.getInstance(gcm256algorithm);
  67. cipher.init(Cipher.ENCRYPT_MODE, secretKey);
  68. byte[] iv = cipher.getIV();
  69. assert iv.length == 12;// 偏移参数及长度要在解密的时候保持一致
  70. byte[] encryptData = cipher.doFinal(content.getBytes());
  71. assert encryptData.length == content.getBytes().length + 16;
  72. byte[] message = new byte[12 + content.getBytes().length + 16];
  73. System.arraycopy(iv, 0, message, 0, 12);
  74. System.arraycopy(encryptData, 0, message, 12, encryptData.length);
  75. return Base64.encodeBase64String(message);
  76. } catch (Exception e) {
  77. logger.error("AESGCM256加密文本处理失败,error:{}", e);
  78. }
  79. return null;
  80. }
  81. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/911401
推荐阅读
相关标签
  

闽ICP备14008679号