AES,高级加密标准(英语:Advanced Encryption Standard,缩写:AES)
在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。严格地说,AES 和 Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大范围的区块和密钥长度:AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限。包括AES-ECB,AES-CBC,AES-CTR,AES-OFB,AES-CFB
AES 加密实现(ECB)
AES-ECB 加密模式实现
import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; /** * AES 加密 */ public final class AESCoder2 { public static final String ALGORITHM = "AES"; /** * 加密 */ public static byte[] encrypt(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 加密+Base64 */ public static String encryptString(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] bytes = cipher.doFinal(data); return Base64Utils.encode(bytes); } /** * 解密 */ public static byte[] decrypt(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 解密 + Base64 */ public static String decryptString(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] bytes = cipher.doFinal(data); return new String(bytes, "UTF-8"); } public static void main(String[] args) throws Exception { String key = "A3EAC779D508B83583C3C2DB906E8CFA"; String data = "八百里逐日听风,抖音账号:Lrk1056"; // byte[] encrypt = encrypt(data.getBytes(StandardCharsets.UTF_8), key); // System.out.println("encrypt = " + new String(encrypt, StandardCharsets.UTF_8)); // byte[] decrypt = decrypt(encrypt, key); // System.out.println("decrypt = " + new String(decrypt)); String encrypt = encryptString(data.getBytes(StandardCharsets.UTF_8), key); System.out.println("encrypt = " + encrypt); String decrypt = decryptString(Base64Utils.decode(encrypt), key); System.out.println("decrypt = " + decrypt); } }
加密结果
encrypt = N3CXWqUZOXV8/lBG3ZRjgfOgGTaKNFjk7e8qvEafsM4Lwz0HLnFE3PhAlvMasheB
decrypt = 八百里逐日听风,抖音账号:Lrk1056
AES 加密实现(CBC/PKCS7Padding)
这里使用 CBC 模式,PKCS7Padding 填充方式实现,首先需要导入三方包依赖(java自带的是PKCS5Padding填充,不支持PKCS7Padding填充),否者会出现异常情况。
java.security.NoSuchAlgorithmException:Cannot find any provider supporting AES/CBC/PKCS7Padding
解决办法:添加静态代码块,通过BouncyCastle组件来让java里面支持PKCS7Padding填充。
import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.Security; /** * AES 加密 CBC 模式 */ public final class AESCoder { /** * 算法/模式/补码方式 */ public static final String AES_CBC_PKCS7 = "AES/CBC/PKCS7Padding"; /** * 解决java不支持AES/CBC/PKCS7Padding模式解密 */ static { Security.addProvider(new BouncyCastleProvider()); } /** * 加密 + Base64 * * @param iv 初始向量 */ public static String encryptString(byte[] data, String key, String iv) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_CBC_PKCS7); Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7); // CBC模式,需要向量iv,增加算法强度 IvParameterSpec spec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec); byte[] bytes = cipher.doFinal(data); return Base64Utils.encode(bytes); } /** * 解密 + Base64 * * @param iv 初始向量 */ public static String decryptString(byte[] data, String key, String iv) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_CBC_PKCS7); Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7); IvParameterSpec spec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); byte[] bytes = cipher.doFinal(data); return new String(bytes, "UTF-8"); } public static void main(String[] args) throws Exception { String key = "A3EAC779D508B83583C3C2DB906E8CFA"; String data = "八百里逐日听风,抖音账号:Lrk1056"; String iv = "023a0cee22cecabe"; String encrypt = encryptString(data.getBytes(StandardCharsets.UTF_8), key, iv); System.out.println("encrypt = " + encrypt); String decrypt = decryptString(Base64Utils.decode(encrypt), key, iv); System.out.println("decrypt = " + decrypt); } }
加密结果
encrypt = cQF/KoEE/B34BRcRSClq0WmyDi4AxJItCvzRxexj/VTO6khBFQOarZpem8r0/uUR
decrypt = 八百里逐日听风,抖音账号:Lrk1056
相关阅读
DES/3DES/AES 三种对称加密算法在 Java 中的实现:http://www.ibloger.net/article/1980.html
漫画:什么是AES算法:http://www.ibloger.net/article/2785.html
漫画:AES算法的底层原理:http://www.ibloger.net/article/2786.html
未经允许请勿转载:程序喵 » Java 实现 AES/CBC/PKCS7Padding 对称加密算法