本文介紹AES加密,並以JAVA實作AES256加解密程式。

AES

AES(Advanced Encryption Standard)高階加密標準,最常見的為對稱加密演算法,對稱加密演算法即為加密解密方均使用同一組密鑰。

加密介紹

代號 意義
明文
密鑰
AES加密函式
AES解密函式
密文

C = E(P,K)
明文(P)使用密鑰(K)透過加密函式(E)產生密文(C)。

P = D(C,K)
密文(C)使用密鑰(K)透過解密函式(D)產生明文(P)。

AES金鑰長度分類

AES 密鑰長度(bytes) 分組長度(bytes) 加密回合(rounds)
AES-128 16 16 10
AES-192 24 16 12
AES-256 32 16 14

AES加密中,明文每個分組只能是128位(16bytes),而金鑰可以是128、192、256位,依照密鑰長度不同,加密回合數也會不同。

限制

AES加密演算法中,原始資料明文(P)長度須為16bytes的倍數,所以當資料不足16bytes時,加密前必須先將資料補足為16bytes,解密後再將之移除還原為原始資料明文。

加密步驟

依照密鑰長度不同,加密回合數(round)也不同。

回合數

AES-128 -> 10 rounds
AES-192 -> 12 rounds
AES-256 -> 14 rounds

加密函數

參考資料:維基百科

  1. Add round key: 對資料(128bits or 16 bytes) ⊕ 回合金鑰。回合金鑰是由主金鑰在每回合(透過Rijndael方法產生)產生之密鑰。
  2. SubBytes:矩陣中的各位元組透過一個8位元的S-box進行轉換。
    S_box
  3. ShiftRows:每一列都向左循環位移某個偏移量。
    shiftrows
  4. MixColumns:每一行的四個位元組透過線性變換互相結合。
    mixcolumn

每round行為

假設共有N rounds。

加密ROUND behaviers

ROUND 0

  1. Add round key

ROUND 1 ~ ROUND (N-1)

  1. SubBytes()
  2. ShiftRows()
  3. MixColumns()
  4. AddRoundKey()

ROUND N

  1. SubBytes()
  2. ShiftRows()
  3. AddRoundKey()

解密ROUND behaviers

以回合數相反方向開始。

ROUND N

  1. AddRoundKey()
  2. ShiftRows()
  3. SubBytes()

ROUND (N-1) ~ ROUND 1

  1. AddRoundKey()
  2. MixColumns()
  3. ShiftRows()
  4. SubBytes()

ROUND 0

  1. AddRoundKey()

實作 (JAVA)

以下內容使用JAVA實作AES-256加解密。

程式碼解析

首先我們使用的是AES加密算法

接著是以參數定義transformation,

參數意義如下表:

參數 意義
algorithm AES 必填,使用之加密算法(EX: RSA, AES, SHA-256等)
mode ECB 非必填,分組密碼運作模式。詳細請參考下方"Mode表"。
padding NoPadding 非必填,指定每次處理的bit數量。詳細請參考下方"Transform表"。

Mode表

Mode 名稱 描述
ECB Electronic CodeBook 使用相同密鑰對明文分組加密
CBC Cipher Block Chaining 加密算法之input為上個密文組合下個明文組之XOR。(加密算法=前一密文組⊕下一明文組)
CFB Cipher FeedBack 與CBC相似,前一密文作為加密算法之input,產生之密文MSB (X bit)與明文之X bit XOR後產生密文之X bit。
OFB Output FeedBack 與CFB相似,只是加密算法之input為前次加密算法之output。
CTR Counter 每組明文都與一經過加密之counter XOR,之後counter遞增。

Transform表

Transform 16byte加密後長度 不滿16byte加密後長度
AES/CBC/NoPadding 16 不支援
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始數據長度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支援
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始數據長度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支援
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16

金鑰 (私鑰)

我們可以初始化一固定金鑰作為密鑰,也可以自動生成。

固定金鑰:
Key之byte[] 長度為16bytes。

自動生成金鑰

加解密Cipher屬性設定

Cipher之7屬性:

Modifier and Type Field and Description
static int DECRYPT_MODE用於解密模式下的 Cipher 初始化。
static int ENCRYPT_MODE用於加密模式下的 Cipher 初始化。
static int PRIVATE_KEY用於說明解包模式下密鑰是是私鑰。
static int PUBLIC_KEY用於說明解包模式下密鑰是公鑰。
static int SECRET_KEY用於說明解包模式下密鑰是密鑰。
static int UNWRAP_MODE用於解包密鑰模式下的 Cipher 初始化。
static int WRAP_MODE用於包裝密鑰模式下的 Cipher 初始化。

JAVA – 加密預設金鑰長度限制

如出現以下錯誤訊息:
java.security.InvalidKeyException: Illegal key size or default parameters

請先至Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 下載policy檔案,後將local_policy.jar及US_export_policy.jar 取代jre/security底下的兩個檔案即可解除JAVA金鑰長度問題。

可能需用到之Functions

使用不同的Padding方式會影響當分組明文不足16bytes之加密過程,明文的編碼不同也需要先轉換編碼再進行加密。下方列出進行加密前可能所需的額外明文處理funtions。

HEX String to Byte[]

Byte[] to HEX String

String Split According to Input Length

以上為JAVA實作AES256加解密之方法。

最後修改日期: 2021-03-31

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。