赞
踩
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'补足
- package com.study;
-
-
- import com.sun.org.slf4j.internal.Logger;
- import com.sun.org.slf4j.internal.LoggerFactory;
-
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.spec.IvParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import java.nio.charset.StandardCharsets;
- import java.security.InvalidAlgorithmParameterException;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.util.Base64;
-
- /**
- * AES对称加密:AES常用的有ECB和CBC两种模式。常用的填充方式有PKCS5Padding、PKCS7Padding、zeropadding
- * CBC模式比ECB模式安全,ECB模式比CBC模式快。 推荐使用CBC模式。
- * 相同密码的加密结果不会变化,是固定的。
- * 这个标准用来替代原先的DES
- * <p>
- * key的字节长度只能是16位、24位、32位。
- * iv的字节长度只能是16位。
- * KEY和IV可以相同,也可以不相同。
- * key和iv长度不足时,这里将以0x00自动填充,超出部分将被忽略。注意:其他系统不一定是这种逻辑,所以key建议设置为16/24/32位,iv设置为16位。
- * <p>
- * 说明:AES数据块长度为128位(16字节),所以IV长度需要为16个字节(ECB模式不用IV),IV与KEY超过长度则截取,不足则在末尾填充'\0'补足
- * @date 2019年12月23日 下午7:56:33
- */
- public class AESUtil {
- private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
- private static final String CBCMode = "AES/CBC/PKCS5Padding";//填充方式
- private static final String ECBMode = "AES/ECB/PKCS5Padding";//填充方式
-
- public static void main(String[] args) {
- String key = "1234567812345678";// key长度建议设置为16位或者24位或者32位。
- String iv = "1234567887654321";// iv长度建议设置为16位。
- String msg = "测试字符串";
-
- //CBC模式
- String cbcEncrypt = AESUtil.encryptCBC(msg, key, iv);
- System.out.println(cbcEncrypt);
- String cbcDecryptStr = AESUtil.decryptCBC(cbcEncrypt, key, iv);
- System.out.println(cbcDecryptStr);
-
- //ECB模式
- String ecbEncrypt = AESUtil.encryptECB(msg, key);
- System.out.println(ecbEncrypt);
- String decryptStr = AESUtil.decryptECB(ecbEncrypt, key);
- System.out.println(decryptStr);
- }
-
- /**
- * AES CBC 加密
- * @param message 需要加密的字符串
- * @param key 密匙
- * @param iv IV,需要和key长度相同
- * @return 返回加密后密文,编码为base64
- */
- public static String encryptCBC(String message, String key, String iv) {
- try {
- byte[] content = message.getBytes(StandardCharsets.UTF_8);
- byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
- keyByte = fillKey(keyByte);
- SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
- byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8);
- ivByte = fillIv(ivByte);
- IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
- Cipher cipher = Cipher.getInstance(CBCMode);
- cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
- byte[] data = cipher.doFinal(content);
- return Base64.getEncoder().encodeToString(data);
- } catch (NoSuchAlgorithmException e) {
- logger.error("没有这样的算法", e);
- } catch (NoSuchPaddingException e) {
- logger.error("没有这样的填充", e);
- } catch (InvalidKeyException e) {
- logger.error("无效的密钥", e);
- } catch (InvalidAlgorithmParameterException e) {
- logger.error("无效的算法参数", e);
- } catch (IllegalBlockSizeException e) {
- logger.error("非法块大小", e);
- } catch (BadPaddingException e) {
- logger.error("不良填充", e);
- }
- return null;
- }
-
- /**
- * AES CBC 解密
- * @param messageBase64 密文,base64编码
- * @param key 密匙,和加密时相同
- * @param iv IV,需要和key长度相同
- * @return 解密后数据
- */
- public static String decryptCBC(String messageBase64, String key, String iv) {
- try {
- byte[] messageByte = Base64.getDecoder().decode(messageBase64);
- byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
- keyByte = fillKey(keyByte);
- SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
- byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8);
- ivByte = fillIv(ivByte);
- IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
- Cipher cipher = Cipher.getInstance(CBCMode);
- cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
- byte[] content = cipher.doFinal(messageByte);
- return new String(content, StandardCharsets.UTF_8);
- } catch (NoSuchAlgorithmException e) {
- logger.error("没有这样的算法", e);
- } catch (NoSuchPaddingException e) {
- logger.error("没有这样的填充", e);
- } catch (InvalidKeyException e) {
- logger.error("无效的密钥", e);
- } catch (InvalidAlgorithmParameterException e) {
- logger.error("无效的算法参数", e);
- } catch (IllegalBlockSizeException e) {
- logger.error("非法块大小", e);
- } catch (BadPaddingException e) {
- logger.error("不良填充", e);
- }
- return null;
- }
-
- /**
- * AES ECB 加密
- * @param message 需要加密的字符串
- * @param key 密匙
- * @return 返回加密后密文,编码为base64
- */
- public static String encryptECB(String message, String key) {
- try {
- byte[] content = message.getBytes(StandardCharsets.UTF_8);
- byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
- keyByte = fillKey(keyByte);
- SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
- Cipher cipher = Cipher.getInstance(ECBMode);
- cipher.init(Cipher.ENCRYPT_MODE, keySpec);
- byte[] data = cipher.doFinal(content);
- return Base64.getEncoder().encodeToString(data);
- } catch (NoSuchAlgorithmException e) {
- logger.error("没有这样的算法", e);
- } catch (NoSuchPaddingException e) {
- logger.error("没有这样的填充", e);
- } catch (InvalidKeyException e) {
- logger.error("无效的密钥", e);
- } catch (IllegalBlockSizeException e) {
- logger.error("非法块大小", e);
- } catch (BadPaddingException e) {
- logger.error("不良填充", e);
- }
- return null;
- }
-
- /**
- * AES ECB 解密
- * @param messageBase64 密文,base64编码
- * @param key 密匙,和加密时相同
- * @return 解密后数据
- */
- public static String decryptECB(String messageBase64, String key) {
- try {
- byte[] messageByte = Base64.getDecoder().decode(messageBase64);
- byte[] keyByte = key.getBytes(StandardCharsets.UTF_8);
- keyByte = fillKey(keyByte);
- SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
- Cipher cipher = Cipher.getInstance(ECBMode);
- cipher.init(Cipher.DECRYPT_MODE, keySpec);
- byte[] content = cipher.doFinal(messageByte);
- return new String(content, StandardCharsets.UTF_8);
- } catch (NoSuchAlgorithmException e) {
- logger.error("没有这样的算法", e);
- } catch (NoSuchPaddingException e) {
- logger.error("没有这样的填充", e);
- } catch (InvalidKeyException e) {
- logger.error("无效的密钥", e);
- } catch (IllegalBlockSizeException e) {
- logger.error("非法块大小", e);
- } catch (BadPaddingException e) {
- logger.error("不良填充", e);
- }
- return null;
- }
-
-
- /**
- * 填充key
- * key的字节长度只能是16位、24位、32位。
- * key长度不足时,这里将以0x00填充,超出部分将被忽略。
- * @return 填充后的key
- */
- public static byte[] fillKey(byte[] keyByte) {
- int length = keyByte.length;
- int len;
- if (length == 16 || length == 24 || length == 32) {
- return keyByte;
- } else if (length < 16) {
- len = 16;
- } else if (length < 24) {
- len = 24;
- } else {
- len = 32;
- }
- byte[] newKeyByte = new byte[len];
- System.arraycopy(keyByte, 0, newKeyByte, 0, length < len ? length : len);
- return newKeyByte;
- }
-
- /**
- * 填充iv
- * iv的字节长度只能是16位。
- * iv长度不足时,这里将以0x00填充,超出部分将被忽略。
- * @return 填充后的iv
- */
- public static byte[] fillIv(byte[] ivByte) {
- int length = ivByte.length;
- int len;
- if (length == 16) {
- return ivByte;
- } else {
- len = 16;
- }
- byte[] newIvByte = new byte[len];
- System.arraycopy(ivByte, 0, newIvByte, 0, length < len ? length : len);
- return newIvByte;
- }
- }
AES GCM 模式
- package com.study;
-
-
- import org.apache.commons.codec.binary.Base64;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.util.StringUtils;
-
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.GCMParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import java.nio.charset.StandardCharsets;
- import java.security.NoSuchAlgorithmException;
-
- public class AESUtil {
- private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
- private static String gcm256algorithm = "AES/GCM/PKCS5Padding";
-
- public static void main(String[] args) {
- KeyGenerator generator = null;
- try {
- generator = KeyGenerator.getInstance("AES");
- //初始化密钥生成器,AES要求密钥长度为128位、192位、256位
- generator.init(256);
- SecretKey secretKey = generator.generateKey();
- // String gcmSecretKey = Base64.encodeBase64String(secretKey.getEncoded());
- String key = "1234567812345678";//key长度为16的倍数
- String gcmSecretKey = Base64.encodeBase64String(key.getBytes(StandardCharsets.UTF_8));
- System.out.println("生成密钥key: " + key + "\n");
-
- String toDoStr = "12345678";
- System.out.println("明文文本:" + toDoStr);
- String encryptResult = AEGCMEncrypt(toDoStr, gcmSecretKey);
- System.out.println("加密结果: " + encryptResult);
-
- String decryptResult = AEGCMDecrypt(encryptResult, gcmSecretKey);
- System.out.println("解密结果: " + decryptResult + "\n");
-
-
- } catch (NoSuchAlgorithmException e) {
- logger.error("密钥生成异常,error:", e);
- }
- }
-
- //解密
- public static String AEGCMDecrypt(String content, String keyStr) {
- try {
- if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
- throw new Exception("AESGCM256解密异常,检查文本或密钥");
- }
- Cipher cipher = Cipher.getInstance(gcm256algorithm);
- SecretKey key = new SecretKeySpec(Base64.decodeBase64(keyStr), "AES");
-
- cipher.init(Cipher.ENCRYPT_MODE, key);
- byte[] message = Base64.decodeBase64(content);
- // 这里的12和16是加密的时候设置的偏移参数及加密长度
- if (message.length < 12 + 16) throw new IllegalArgumentException();
- GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
- cipher.init(Cipher.DECRYPT_MODE, key, params);
- byte[] decryptData = cipher.doFinal(message, 12, message.length - 12);
- String decript = new String(decryptData);
- return decript;
- } catch (Exception e) {
- logger.error("AESGCM256解密文本处理失败,error:{}", e);
- }
- return null;
- }
-
- //加密
- public static String AEGCMEncrypt(String content, String keyStr) {
- try {
- if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
- throw new Exception("AESGCM256加密异常,检查文本或密钥");
- }
-
- SecretKey secretKey = new SecretKeySpec(Base64.decodeBase64(keyStr), "AES");
-
- Cipher cipher = Cipher.getInstance(gcm256algorithm);
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
- byte[] iv = cipher.getIV();
- assert iv.length == 12;// 偏移参数及长度要在解密的时候保持一致
- byte[] encryptData = cipher.doFinal(content.getBytes());
- assert encryptData.length == content.getBytes().length + 16;
- byte[] message = new byte[12 + content.getBytes().length + 16];
- System.arraycopy(iv, 0, message, 0, 12);
- System.arraycopy(encryptData, 0, message, 12, encryptData.length);
- return Base64.encodeBase64String(message);
- } catch (Exception e) {
- logger.error("AESGCM256加密文本处理失败,error:{}", e);
- }
- return null;
-
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。