AES加密工具的實現及其基礎原理

先貼代碼:重要的參數都有註釋,自己摸索的,有不對的地方大家指正

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @ClassName:  DESUtil
 * @Description: 加解密工具類
 * @author: panpan
 * @date:   2019年1月29日 下午5:01:48
 *
 */
public class AESUtil {

    private static final String CHARSET_NAME = "UTF-8";

    public static String encode(String plainText, String key, String vi) {
        try {
            // 根據字符串key生成 Cipher 初始化使用的 secretKey
            SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES");
            // 獲取Cipher實例,指定加密方法、加密模式、補位模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            // 加密器初始化,參數分別是: 加密器編碼模式(加密或解密)、祕鑰、加密向量
            cipher.init(Cipher.ENCRYPT_MODE, secretKey,
                    new IvParameterSpec(vi.getBytes()));
            // cipher 可以 add 但是最終需要使用 doFinal結束,返回byte[],這裏通過base64編碼成字符串
            return java.util.Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes(CHARSET_NAME)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String decode(String encryptText, String key, String vi) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey,
                    new IvParameterSpec(vi.getBytes()));
            return new String(cipher.doFinal(java.util.Base64.getDecoder().decode(encryptText)), CHARSET_NAME);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String vi = "f4CAHEW85Daszbwi"; // 16字節加密向量
        String message = "Uibn1aICzX";  // 任意大小需要加密的文字
        String key = "JvOybH9j7Qs0wSxi"; // 128bit、16字節祕鑰
        String encryptedCode = encode(message,key,vi);
        System.out.println(encryptedCode);
        String decryptedCode = decode(encryptedCode,key,vi);
        System.out.println(decryptedCode);
    }
}

  接着放參考資料:

  首先第一位的是 JAVA API:

http://www.matools.com/api/java8

   需要注意的是,獲取Cipher實例時,可以選擇很多加密模式,這是寫這個工具類的核心。

   1、加密方法有: AES、DES、DESede、RSA

   2、加密模式有: CBC、ECB,這兩種是JDK中提供的實例有的,如果你需要寫其他的加密模式,如:CFB、OFB

   可以參考這篇文章的原理:

   https://blog.csdn.net/sunqiujing/article/details/75065218

   當然,想要demo的話,這裏有一個CFB的例子:

    https://download.csdn.net/download/langeldep/9749421

   3、最後一個參數: Padding or not: 是否補位,這個初次接觸加密的童鞋可能有點懵,說實話今早我剛剛看到這個的時候也有點懵逼,後來參考了   https://blog.csdn.net/sunqiujing/article/details/75065218 這篇文章講述的原理,有點明白了,其實AES、DES在加密時,是以 8 bit 作爲一個單元的,如果不滿 8 bit,如果你選擇了 PKCS5Padding,則會給你補位,CFB中那位老哥寫的demo,使用的是 NoPadding,但是自己在代碼了擼了補位的操作,具體爲什麼他不使用工具裏自帶的補位,沒有細細研究。

   4、還有一點,括號中的數字,說的是你的 加密key需要的位數,也是 AES加密快的大小

                     

                                                                              引用一個圖

 比如我使用 AES/CBC/PKCS5Padding,官方文檔中說要 128 bit,即 key需要 128/8 = 16 字符的字符串,

 如果你的位數不滿 16 位,就會報以下錯誤:

 java.lang.RuntimeException: java.security.InvalidKeyException: Invalid AES key length: 17 bytes

 

接下來的一個核心,是Cipher加密器的初始化:

cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(vi.getBytes()));

1、加密器模式: ENCRYPT_MODE是加密  DECRYPT_MODE是解密

2、 secretKey 是祕鑰,當然你不能直接把直接放字符串祕鑰,得使用JAVA提供的祕鑰生成器,並制定加密方式,因爲不同加密方式,使用的key構成是不一樣的,並且祕鑰的大小也不同,重點需要特別注意。

3、 加密向量,注意 上面代碼裏採用的 AES/CBC/PKCS5Padding 需要 16字節128bit的加密向量,否則則會報錯:

java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long

       加密向量幹啥用的嘞? 大家可以回想一下大學學得 線性代數,加密的每個明文模塊、祕鑰模塊、密文模塊其實都是一個矩陣,這裏的加密向量其實和線代裏的向量應該是一致的。

                                               再借用一張圖

    大概原理差不多是:  明文矩陣 X 祕鑰矩陣 X 基礎向量 = 明文矩陣    

    這篇文章寫得很詳細,大家可以看一下

    https://blog.csdn.net/wufaliang003/article/details/79619027

 

    嗯嗯,總算對對稱加密的幾種方法有了個大概瞭解,做一篇文章,mark一下,也是分享經驗,有不對的地方大家評論

       

 

 

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