網頁

2021/1/27

Java Cipher AES CBC加密解密簡單範例 AES CBC mode encrypt decrypt example

Java Cipher AES CBC加密解密簡單範例。

AES CBC模式 128bit Key 加解密範例。

package com.abc.demo;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.security.*;
import java.util.Base64;

public class Main {

    public static void main(String[] args) {
        String data = "hello world";

        Key key = genKey(); // 產生密鑰
        IvParameterSpec iv = genIv(); // 產生初始向量(initialization vector)

        String ecryptData = encrypt(key, data, iv); // 加密
        System.out.println(ecryptData); // x3n15BnLoe4tchDrzx0hDQ==

        String decryptData = decrypt(key, ecryptData, iv); // 解密
        System.out.println(decryptData); // hello world

    }

    /**
     * 產生隨機密鑰
     *
     * @return 密鑰
     */
    public static Key genKey() {
        int keySize = 128; // 密鑰長度
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES"); // 取得AES密鑰產生器實例
            keyGen.init(keySize, new SecureRandom()); // 密鑰產生器初始化
            return keyGen.generateKey(); // 產生密鑰
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 產生初始向量
     *
     * @return 初始向量
     */
    public static IvParameterSpec genIv() {
        byte[] ivBytes = new byte[16]; // 128/8=16, AES block size is 128bits
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(ivBytes); // 隨機生成bytes內容
        return new IvParameterSpec(ivBytes); // initialization vector
    }

    /**
     * AES CBC mode PKCS5Padding加密
     *
     * @param key  密鑰
     * @param data 未加密資料
     * @param iv   初始向量
     * @return 密文 (hex string)
     */
    public static String encrypt(Key key, String data, IvParameterSpec iv) {
        try {
            String transformation = "AES/CBC/PKCS5Padding"; // transformation form:algorithm/mode/padding
            Cipher cipher = Cipher.getInstance(transformation); // 取得AES CBC mode, PKCS5Padding的Cipher實例
            cipher.init(Cipher.ENCRYPT_MODE, key, iv); // Cipher初始化為加密模式
            byte[] encryptDataBytes = cipher.doFinal(data.getBytes()); // 加密資料

//            return Hex.encodeHexString(encryptDataBytes); // Apache Commons Codec轉hex字串方便傳輸
            return Base64.getEncoder().encodeToString(encryptDataBytes); // 轉Base64編碼方便傳輸
        } catch (NoSuchAlgorithmException
                | NoSuchPaddingException
                | IllegalBlockSizeException
                | BadPaddingException
                | InvalidKeyException
                | InvalidAlgorithmParameterException e
        ) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES CBC mode PKCS5Padding解密
     *
     * @param key         密鑰
     * @param encryptData 密文 (hex string)
     * @param iv          初始向量
     * @return 解密資料
     */
    public static String decrypt(Key key, String encryptData, IvParameterSpec iv) {
        try {
//            byte[] encryptDataBytes = Hex.decodeHex(encryptData); // 解碼hex字串為bytes
            byte[] encryptDataBytes = Base64.getDecoder().decode(encryptData); // 解碼Base64編碼的字串為bytes
            String transformation = "AES/CBC/PKCS5Padding";
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(Cipher.DECRYPT_MODE, key, iv); // Cipher初始化為解密模式
            byte[] decryptData = cipher.doFinal(encryptDataBytes); // 解密資料

            return new String(decryptData);
        } catch (NoSuchAlgorithmException
                | NoSuchPaddingException
                | IllegalBlockSizeException
                | BadPaddingException
                | InvalidKeyException
//                | DecoderException
                | InvalidAlgorithmParameterException e
        ) {
            e.printStackTrace();
            return null;
        }
    }

}

這些密碼學的東西跟天書一樣,上面也是東抄西抄拼湊來的,對於AES在幹嘛及Java JCA架構下的用法也不是很清楚。

本篇如有幫助到您還幫忙按個廣告支持。


沒有留言:

張貼留言