對稱加密技術 - AES加密

AES發展歷史

  • 1997年NIST發起了整機替代DES算法的活動:高級數據加密標準(Advanced Encryption Standard);
  • NIST要求算法比3DES塊,安全性高,具有128位分組長度,支持128、192、256位長度的密鑰;
  • 2000年Rijndael算法當選AES算法標準;
  • AES:密鑰建立時間短、靈敏性好、內存需求低,被廣泛應用;
  • AES跟進密鑰長度分爲AES-128、AES-256幾種。

應用

AES是用來替代DES的,所以凡是使用DES的地方都應該優先考慮使用AES替換,DES作爲遺留系統或者學習保留,實際建議使用AES,一般場景AES-128即可,高安全場景可以使用AES-257,在JDK 6中若要使用256的加密方式,需要:無政策性限制權限文件

Java中使用步驟

AES的使用和DES一樣,也是經過三步,Java的API封裝的很好,使用SPI機制實現策略模式,外部代碼改動很小。

在使用其他對稱加密算法:RC2、RC4、Blowfish算法的時候都可以參照下面的模式。

  • 構建密鑰:使用KeyGenerator,這個步驟對稱加密算法和非對稱加密算法都需要;
  • 構建AES專用的SecretKey:和DES和3DES不同,使用SecretKeySpec即可,這步是針對存儲下來的密鑰進行處理;
  • 進行加解密:要注意設置Cipher的工作模式。
public class AESTest {

    // private static final String CIPHER_ALGORITHM = "DESede";
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final String KEY_ALGORITHM = "AES";

    public static void main(String[] args) throws Exception {
        // 產生Key,一般只產生一次
        byte[] key = generateKey();
        String keyStr = Base64.getEncoder().encodeToString(key);
        String input = "加密我";

        // 加密數據
        byte[] encryptData = encrypt(input.getBytes(), key);
        // 解密數據
        byte[] dencryData = decrypt(encryptData, key);

        String msg = String.format("原始數據: %s , Key : %s , 加密數據: %s , 解密數據: %s", input, keyStr,
                HexBin.encode(encryptData), new String(dencryData));
        System.out.println(msg);
    }

    /**
     * 產生符合要求的Key,如果不用KeyGenerator隨機性不好,而且要求自己對算法比較熟悉,能產生符合要求的Key
     *
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[] generateKey() throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        // 3DES要求使用112或者168位密鑰
        // kg.init(112);
        kg.init(128);
        SecretKey secretKey = kg.generateKey();
        byte[] key = secretKey.getEncoded();
        return key;
    }

    /**
     * 獲取算法需要的安全密鑰,這步比DES和3DES簡單
     *
     * @param key
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws InvalidKeySpecException
     */
    public static SecretKey getSecretKey(byte[] key)
            throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        SecretKey keySpec = new SecretKeySpec(key, KEY_ALGORITHM);
        return keySpec;
    }

    /**
     * 加密數據
     *
     * @param input
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] input, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
        return cipher.doFinal(input);
    }

    /**
     * 解密數據
     *
     * @param input
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] input, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
        return cipher.doFinal(input);
    }

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