AES加密實現


起因

這段時間因為要對接一個外部接口,其參數的加密方式為AES,就需要學下AES的加密寫法,但網上的資料不是很全,自己記錄下遇到的坑;

基本寫法

String str = "hello";
        String password = "1234567890123456";
        //新建一個密碼編譯器的實例,由三部分構成,用"/"分隔,分別代表加密的類型(如AES,DES,RC2等),模式(AES中包含ECB,CBC,CFB,CTR,CTS等),補碼方式(包含nopadding/PKCS5Padding等等),依據這三個參數可以創建很多種加密方式
        Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", SymmetricAlgorithm.AES.name(), Mode.ECB.name(), Padding.PKCS5Padding.name()));
        //構建密鑰
        SecretKeySpec key  = new SecretKeySpec(password.getBytes(Charset.forName("utf-8")),"AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);//使用加密模式初始化 密鑰
        byte[] encrypt = cipher.doFinal(str.getBytes()); //按單部分操作加密或解密數據,或者結束一個多部分操作。
        System.out.println(Base64.encode(encrypt));
        System.out.println("method2-加密:" + Arrays.toString(encrypt));
        cipher.init(Cipher.DECRYPT_MODE, key);//使用解密模式初始化 密鑰
        byte[] decrypt = cipher.doFinal(encrypt);
        System.out.println("method2-解密后:" + new String(decrypt));

  

優化寫法

這樣一個最簡單的AES加解密就完成了,但有一個缺點,密碼的長度必須為128位,也就是16個字節,否則會報錯;
當使用AES/ECB/NoPadding模式時,加密的內容的字節長度也必須為16的整倍數,否則也會提示錯誤;
可采用的方法是:如果key的長度小於16,則補全16位,否則截取16位
加密內容補全為16的整倍數,以下為示例代碼:

/**
     * 測試AES加密,使用ECB/Nopadding的方式,要求key的長度為128位,內容的長度也為128位的整數倍
     * @param content
     * @param password
     * @return
     */
private String testAes(String content,String password) throws Exception {
        //原始字節數組
        byte[] passwordBytes = password.getBytes(Charset.forName("utf-8"));
        //填充為16位
        byte[] keyBytes  = new byte[16];
        byte[] contentBytes = content.getBytes(Charset.forName("utf-8"));
        byte[] contentBytesTarget ;
        Cipher cipher = Cipher.getInstance(String.format("%s/%s/%s", SymmetricAlgorithm.AES.name(), Mode.ECB.name(), Padding.NoPadding.name()));
        if(passwordBytes.length < 16)
            System.arraycopy(passwordBytes,0,keyBytes,0,passwordBytes.length);
        else
            System.arraycopy(passwordBytes,0,keyBytes,0,16);

        if(contentBytes.length % 16 == 0)
            contentBytesTarget = contentBytes;
        else{
            contentBytesTarget = new byte[contentBytes.length + 16 - contentBytes.length % 16 ];
            System.arraycopy(contentBytes,0,contentBytesTarget,0,contentBytes.length);
        }

        SecretKeySpec key = new SecretKeySpec(keyBytes,"AES");

        cipher.init(Cipher.ENCRYPT_MODE, key);//使用加密模式初始化 密鑰
        byte[] encrypt = cipher.doFinal(contentBytesTarget); //按單部分操作加密或解密數據,或者結束一個多部分操作。
        System.out.println(Base64.encode(encrypt));
        System.out.println("method2-加密:" + Arrays.toString(encrypt));
        cipher.init(Cipher.DECRYPT_MODE, key);//使用解密模式初始化 密鑰
        byte[] decrypt = cipher.doFinal(encrypt);
        System.out.println("method2-解密后:" + new String(decrypt));
        return Base64.encode(encrypt);
    }

  

測試

可以使用在線工具進行測試:http://tool.chacuo.net/cryptaes

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM