AES 加密又稱對稱性加密,在開發中常用於對流數據對加密,尤其是流數據在網絡傳輸過程中,擔心被泄露,AES 加密被常用於這塊的校驗中。下面是 AES 加密的百度百科說明解釋:
AES加密標準又稱爲高級加密標準 Rijndael 加密法,是美國國家標準技術研究所NIST旨在取代 DES 的 21 世紀的加密標準。AES 的基本要求是,採用對稱分組密碼體制,密鑰長度可以爲 128、192 或 256 位,分組長度 128 位,算法應易在各種硬件和軟件上實現。1998 年 NIST 開始 AES 第一輪分析、測試和徵集,共產生了 15 個候選算法。
1999 年 3 月完成了第二輪 AES2 的分析、測試。2000 年 10 月 2 日美國政府正式宣佈選中比利時密碼學家 Joan Daemen 和 Vincent Rijmen 提出的一種密碼算法 Rijndael作爲 AES 的加密算法。
AES 加密數據塊和密鑰長度可以是 128b、192b、256b 中的任意一個。AES 加密有很多輪的重複和變換。大致步驟如下:
①密鑰擴展(Key Expansion)
②初始輪(InitialRound)
③重複輪(Rounds),每一重複輪又包括字節間減法運算(SubBytes)、行移位(ShiftRows)、列混合(MixColumns)、輪密鑰加法運算(AddRoundKey) 等操作
④最終輪(Final Round),最終輪沒有列混合操作(MixColumns)
接下來把 Android 的代碼貼一下:
- 解密
public static byte[] decryptData(byte[] data, byte[] key, byte[] iv, String transformation) throws Exception {
if (data == null || data.length == 0
|| key == null || key.length < 16
|| iv == null || iv.length < 16
|| transformation == null || transformation.length() == 0) {
throw (new InvalidParameterException());
}
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec newKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance(transformation,"BC");
cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(data);
}
- 加密
public static byte[] encryptEncode(byte[] data, byte[] key, byte[] iv, String transformation) throws Exception {
if (data == null || data.length == 0
|| key == null || key.length == 0
|| iv == null || iv.length == 0
|| transformation == null || transformation.length() == 0) {
throw (new InvalidParameterException());
}
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec newKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance(transformation,"BC");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(data);
}
-
key 密鑰必須是 16 位以上
-
iv:偏移量,最少 16 位數
-
transformation 的選擇
一般選擇 PKCS7Padding,因爲 PKCS5Padding 最終調用的是 PKCS7Padding 只是做了塊位數的限制 詳情請看
另外要注意 Java 是不支持 PKCS7Padding,需要引入 bouncycastle https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16
組件實現 -
base64 編碼
與後臺人員協商,如果是需要對數據進行編碼解碼,協商好,只需要通過以下方式中轉就可以了
byte[] baseData = Base64.encode(cipher.doFinal(data), Base64.DEFAULT)
例子
@Test
public void test(){
byte[] data = {0x01,0x02,0x03,0x04,0x05};
byte[] mAESKey = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
byte[] iv = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
String mAESTransformation = "AES/CBC/PKCS7Padding";
try {
byte[] encrypt = EncryptUtil.encryptEncode(data, mAESKey, iv, mAESTransformation);
byte[] decrypt = EncryptUtil.decryptData(encrypt, mAESKey, iv, mAESTransformation);
System.out.println("加密前:"+bytes2HexString(data));
System.out.println("加密後:"+bytes2HexString(encrypt));
System.out.println("解密後:"+bytes2HexString(decrypt));
} catch (Exception e) {
e.printStackTrace();
}
}
public static String bytes2HexString(byte[] bytes) {
String ret = "";
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
結果
加密前:0102030405
加密後:F2C0C2091ABB5CC09FC71E4614E0733B
解密後:0102030405