Android 加密 AES

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章