先貼代碼:重要的參數都有註釋,自己摸索的,有不對的地方大家指正
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * * @ClassName: DESUtil * @Description: 加解密工具類 * @author: panpan * @date: 2019年1月29日 下午5:01:48 * */ public class AESUtil { private static final String CHARSET_NAME = "UTF-8"; public static String encode(String plainText, String key, String vi) { try { // 根據字符串key生成 Cipher 初始化使用的 secretKey SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES"); // 獲取Cipher實例,指定加密方法、加密模式、補位模式 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 加密器初始化,參數分別是: 加密器編碼模式(加密或解密)、祕鑰、加密向量 cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(vi.getBytes())); // cipher 可以 add 但是最終需要使用 doFinal結束,返回byte[],這裏通過base64編碼成字符串 return java.util.Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes(CHARSET_NAME))); } catch (Exception e) { throw new RuntimeException(e); } } public static String decode(String encryptText, String key, String vi) { try { SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(vi.getBytes())); return new String(cipher.doFinal(java.util.Base64.getDecoder().decode(encryptText)), CHARSET_NAME); } catch (Exception e) { throw new RuntimeException(e); } } public static void main(String[] args) { String vi = "f4CAHEW85Daszbwi"; // 16字節加密向量 String message = "Uibn1aICzX"; // 任意大小需要加密的文字 String key = "JvOybH9j7Qs0wSxi"; // 128bit、16字節祕鑰 String encryptedCode = encode(message,key,vi); System.out.println(encryptedCode); String decryptedCode = decode(encryptedCode,key,vi); System.out.println(decryptedCode); } }
接着放參考資料:
首先第一位的是 JAVA API:
http://www.matools.com/api/java8
需要注意的是,獲取Cipher實例時,可以選擇很多加密模式,這是寫這個工具類的核心。
1、加密方法有: AES、DES、DESede、RSA
2、加密模式有: CBC、ECB,這兩種是JDK中提供的實例有的,如果你需要寫其他的加密模式,如:CFB、OFB
可以參考這篇文章的原理:
https://blog.csdn.net/sunqiujing/article/details/75065218
當然,想要demo的話,這裏有一個CFB的例子:
https://download.csdn.net/download/langeldep/9749421
3、最後一個參數: Padding or not: 是否補位,這個初次接觸加密的童鞋可能有點懵,說實話今早我剛剛看到這個的時候也有點懵逼,後來參考了 https://blog.csdn.net/sunqiujing/article/details/75065218 這篇文章講述的原理,有點明白了,其實AES、DES在加密時,是以 8 bit 作爲一個單元的,如果不滿 8 bit,如果你選擇了 PKCS5Padding,則會給你補位,CFB中那位老哥寫的demo,使用的是 NoPadding,但是自己在代碼了擼了補位的操作,具體爲什麼他不使用工具裏自帶的補位,沒有細細研究。
4、還有一點,括號中的數字,說的是你的 加密key需要的位數,也是 AES加密快的大小
引用一個圖
比如我使用 AES/CBC/PKCS5Padding,官方文檔中說要 128 bit,即 key需要 128/8 = 16 字符的字符串,
如果你的位數不滿 16 位,就會報以下錯誤:
java.lang.RuntimeException: java.security.InvalidKeyException: Invalid AES key length: 17 bytes
接下來的一個核心,是Cipher加密器的初始化:
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(vi.getBytes()));
1、加密器模式: ENCRYPT_MODE是加密 DECRYPT_MODE是解密
2、 secretKey 是祕鑰,當然你不能直接把直接放字符串祕鑰,得使用JAVA提供的祕鑰生成器,並制定加密方式,因爲不同加密方式,使用的key構成是不一樣的,並且祕鑰的大小也不同,重點需要特別注意。
3、 加密向量,注意 上面代碼裏採用的 AES/CBC/PKCS5Padding 需要 16字節128bit的加密向量,否則則會報錯:
java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
加密向量幹啥用的嘞? 大家可以回想一下大學學得 線性代數,加密的每個明文模塊、祕鑰模塊、密文模塊其實都是一個矩陣,這裏的加密向量其實和線代裏的向量應該是一致的。
再借用一張圖
大概原理差不多是: 明文矩陣 X 祕鑰矩陣 X 基礎向量 = 明文矩陣
這篇文章寫得很詳細,大家可以看一下
https://blog.csdn.net/wufaliang003/article/details/79619027
嗯嗯,總算對對稱加密的幾種方法有了個大概瞭解,做一篇文章,mark一下,也是分享經驗,有不對的地方大家評論