AES加密演算法入門
1. AES簡介
AES是一個對稱密碼演算法。
AES支援五中模式:ECB,CBC,CFB,OFB,PCBC;支援三種填充:NoPadding,PKCS5Padding,ISO10126Padding。
這章只講AES加密的使用,不講具體原理,後面可能會具體講原理(博主不偷懶的話)。
值得注意的是:NoPadding填充方式只能加密長度為16n的內容
2. 程式碼示例
2.1程式碼
package com.tricycle.aes; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import com.tricycle.utils.Log; public class AES { static Cipher cipher; static final String AES_ALGORITHMS = "AES"; static final String ALGORITHMS_ECB_PKCS5Padding = "AES/ECB/PKCS5Padding"; static final String ALGORITHMS_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding"; static final String ALGORITHMS_CBC_NoPadding = "AES/CBC/NoPadding"; static final String ALGORITHMS_ECB_NoPadding = "AES/ECB/NoPadding"; static SecretKey secretKey; public static void main(String[] args) { encryptECB(ALGORITHMS_ECB_PKCS5Padding, "0123456789abcde"); encryptECB(ALGORITHMS_ECB_PKCS5Padding, "0123456789abcdef"); encryptECB(ALGORITHMS_ECB_NoPadding, "0123456789abcdef"); encryptECB(ALGORITHMS_ECB_NoPadding, "0123456789abcde"); encryptCBC(ALGORITHMS_CBC_PKCS5Padding, "0123456789abcde"); encryptCBC(ALGORITHMS_CBC_PKCS5Padding, "0123456789abcdef"); encryptCBC(ALGORITHMS_CBC_NoPadding, "0123456789abcdef"); encryptCBC(ALGORITHMS_CBC_NoPadding, "0123456789abcde"); } private static void encryptECB(String padding, String source) { try { cipher = Cipher.getInstance(padding); secretKey = KeyGenerator.getInstance(AES_ALGORITHMS).generateKey(); Log.print(padding + "; key length: " + secretKey.getEncoded().length); Log.print(Arrays.toString(secretKey.getEncoded())); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encrypt = cipher.doFinal(source.getBytes()); Log.print(Arrays.toString(encrypt)); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decrypt = cipher.doFinal(encrypt); Log.print(new String(decrypt)); } catch (Exception e) { e.printStackTrace(); } } /* * CBC need an initial vector; IV length must be 16 bytes long */ private static byte[] getIV() { String iv = "1234567812345678"; return iv.getBytes(); } private static void encryptCBC(String padding, String source) { try { cipher = Cipher.getInstance(padding); secretKey = KeyGenerator.getInstance(AES_ALGORITHMS).generateKey(); Log.print(padding + "; key length: " + secretKey.getEncoded().length); Log.print(Arrays.toString(secretKey.getEncoded())); cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec( getIV())); byte[] encrypt = cipher.doFinal(source.getBytes()); Log.print(Arrays.toString(encrypt)); cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec( getIV())); byte[] decrypt = cipher.doFinal(encrypt); Log.print(new String(decrypt)); } catch (Exception e) { e.printStackTrace(); } } }
2.2輸出
AES/ECB/PKCS5Padding; key length: 16
[88, -41, 105, 86, -18, -91, -88, -4, -21, -56, 51, 72, 87, 114, -38, 13]
[-76, 11, -17, 55, 108, -52, -38, -96, -22, -124, -102, 61, 113, 81, 34, -84]
0123456789abcde
AES/ECB/PKCS5Padding; key length: 16
[104, -13, 9, 8, 95, -107, -96, 46, 71, -11, 34, 122, -20, -73, 19, -42]
[45, 118, 127, 84, -18, -122, -4, 105, 105, 56, -59, 94, -115, -108, -12, -8, -62, -71, 55, 13, 63, -82, 78, -5, -65, 10, 30, -9, 54, -9, -39, 70]
0123456789abcdef
AES/ECB/NoPadding; key length: 16
[-62, -48, -55, 82, -83, 115, 17, 122, 89, -25, -19, -31, -84, -111, -11, 16]
[39, 103, 109, 16, -83, 67, 109, 104, -111, -65, -30, -64, 11, -19, 4, 18]
0123456789abcdef
AES/ECB/NoPadding; key length: 16
[-10, 106, 99, -14, 25, 6, -64, -52, 88, 6, 24, 74, -90, 20, -52, 74]
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:854)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:828)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at com.tricycle.aes.AES.encryptECB(AES.java:57)
at com.tricycle.aes.AES.main(AES.java:37)
AES/CBC/PKCS5Padding; key length: 16
[68, -70, -14, -73, -14, 85, 113, -46, 37, 55, 5, 3, 52, -127, 12, 68]
[94, -18, 6, -27, 10, 97, 61, -69, -50, 0, 30, -49, 125, 106, -114, 20]
0123456789abcde
AES/CBC/PKCS5Padding; key length: 16
[1, -72, -50, 41, -111, 39, -26, -49, 78, -9, -27, -67, 29, 127, 8, 114]
[90, -65, 72, 108, -75, -54, 45, -45, 109, 117, -29, -99, -91, 118, -24, -37, 61, -43, -119, 119, 68, -50, 83, 105, -76, 70, 75, -80, 120, -60, -6, -40]
0123456789abcdef
AES/CBC/NoPadding; key length: 16
[25, -3, 116, -8, -9, 14, 119, 54, -18, -49, 11, -85, -56, 110, 17, -19]
[-114, -123, -43, 55, -85, -98, 24, 125, -45, 43, -3, 65, -98, -104, -34, -30]
0123456789abcdef
AES/CBC/NoPadding; key length: 16
[-79, 28, -10, 43, -50, -108, 7, -59, -116, -110, -42, 38, 56, 75, 71, 32]
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:854)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:828)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at com.tricycle.aes.AES.encryptCBC(AES.java:88)
at com.tricycle.aes.AES.main(AES.java:42)