AES
表一:
| 算法 | 秘鑰長度 | 秘鑰長度默認值 | 工作模式 | 填充模式 | 備註 |
|---|---|---|---|---|---|
| AES | 128,192,256 | 128 | ECB,CBC,PCBC,CTR,CTS,CFB,CFB8至CFB128,OFB,OFB8至OFB128 | NoPadding,PKCS5Padding,ISO10126Padding | Java6實現若使用256位秘鑰需要獲得無政策限制權限文件(Unlimited Strength Jurisdiction Policy Files) |
| AES | 同上 | 同上 | 同上 | PKCS7Padding,ZeroBytePadding | Bouncy Castle實現 |
表二:
| AES | 秘鑰長度(比特) | 分組長度(比特) | 向量長度(比特) | 加密輪數 |
|---|---|---|---|---|
| AES-128 | 128 | 128 | 128 | 10 |
| AES-192 | 192 | 128 | 128 | 12 |
| AES-256 | 256 | 128 | 128 | 14 |
-
1
根據密鑰長度不同,分為AES128、AES192、AES256
- 1.特點
- ECB模式和CBC模式的區別
- 對稱加密算法裏,使用NOPadding,加密的明文必須等於分組長度倍數,否則報錯
- 如果使用PKCS5Padding,會對加密的明文填充1字節-1個分組的長度
- 沒有指明加密模式和填充方式,表示使用默認的AES/ECB/PKCS5Padding
- 加密後的字節數組可以編碼成Hex、Base64
- AES算法明文按128位進行分組加密,可以調用cipher.getBlockSize()來獲取
- 要復現一個對稱加密算法,需要得到明文、key、iv、mode、padding
- 明文、key、iv需要注意解析方式,而且不一定是字符串形式
- 如果加密模式是ECB,則不需要加iv,加了的話會報錯
- 如果明文中有兩個分組的內容相同,ECB會得到完全一樣的密文,CBC不會
- 加密算法的結果通常與明文等長或者更長,如果變短了,那可能是gzip、protobuf
-
2.代碼實現
public static String encryptAES(String plaintext) throws Exception { // 初始化秘鑰 和加密算法 秘鑰為16位 SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); // 得到Cipher的實例 026fcbe02f76529d0a5bb3904aa6efdc C5sV2ktEoPUVHc/EwB811b8xuRnjiS3cO1khLWp7EeY= Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 對Cipher 實例進行初始化, des.init(Cipher.ENCRYPT_MODE,keySpec,ivParameterSpec); // update並不會每次都增加要加密的字符串的長度,並不可靠。理想中的狀態是 xiaojianbang +hengdi 解密發現只有banghengdi // des.update("xiaojianbang".getBytes(StandardCharsets.UTF_8)); // 加密 由字符串 得到的byte[] byte[] res=des.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); Log.d("hengdi","AES byte test" + Arrays.toString(res)); // 將 byte[] 實例化為 ByteString 對象 ByteString bty= ByteString.of(res); // hex 編碼 String str_hex= bty.hex(); // base64 編碼 String str_base64 = bty.base64(); return str_hex + " || " + str_base64; } public static String decryptAES(String cipherText) throws Exception { // 將加密後base64編碼的字符串 解碼,並還原成 byte[] // byte[] cipherTextBytes = ByteString.decodeHex(cipherText).toByteArray(); byte[] cipherTextBytes = ByteString.decodeBase64(cipherText).toByteArray(); SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); // 得到Cipher的實例 026fcbe02f76529d0a5bb3904aa6efdc Am/L4C92Up0KW7OQSqbv3A== Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); des.init(Cipher.DECRYPT_MODE,keySpec,ivParameterSpec); byte[] res=des.doFinal(cipherTextBytes); return new String(res); }