AES 資料加密

進階加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱 Rijndael 加密法,是美國聯邦政府採用的一種區塊加密標準

加密方式比對

  • 對稱加密:採用單密鑰加密方法,同一個密鑰可以同時用來加密解密。常用的對稱加密算法有 DES3DESAES 等。

  • 非對稱加密,需要兩個密鑰來進行加密解密,這兩個密鑰是公開密鑰(public key,簡稱公鑰)私有密鑰(private key,簡稱私鑰)。常用的非對稱加密算法有 RSAElgamalECC 等。

簡單做一下兩者的比對:

功能特性 對稱加密 非對稱加密
密鑰特徵 加密方和解密方使用同一個密鑰 加密方和解密方使用不同的密鑰
加密效率 效率高,速度快 速度慢
密鑰安全性 傳輸過程中容易洩漏 安全性高

設計思維

  • 安全性(Security) :演算法足夠強,抗攻擊。
  • 經濟性(Efficiency) : 演算法運算效率高。
  • 金鑰捷變(Key Agility) :更改金鑰所引入的損失儘量小,即最小消耗的金鑰擴充套件演算法。
  • 適應性 (Versatility) :適用於不同的CPU架構,軟體或硬件平臺的實現。
  • 設計簡單(Simplicity) :輪函式的設計精簡,只是多輪迭代。

評判要求

NIST在徵集演算法的時候就提出了幾項硬性要求:

  • 分組加密演算法:支援 128 位分組大小,128/192/256 位金鑰 。
  • 安全性不低於 3DES,但實施與執行要比 3DES 的更高效 。
  • 優化過的 ANSI C 的實現程式碼 KAT(Known-Answer tests) 及 MCT(Monte Carlo Tests) 測試及驗證 。
  • 軟體及硬體實現的便捷 。
  • 可抵禦已知攻擊。

設計準則

  • 混淆 (Confusion) 最大限度地複雜化密文、明文與金鑰之間的關係,通常用非線性變換演算法達到最大化的混淆。
  • 擴散 (Diffusion) 明文或金鑰每變動一位將最大化地影響密文中的位數,通常採用線性變換演算法達到最大化的擴散。

實作原理

AES算法主要有四種操作處理,分別是輪 密鑰加層(Add Round Key)字節代換層(SubBytes)行位移層(Shift Rows)列混淆層(Mix Columns) 。AES加密的過程,並不是明文和密鑰簡單運算一下。

在上面的幾個步驟中,我們是對輸入對數據進行混淆AddRoundKey每執行一次叫做一輪加密,這一步會執行多次。簡單來說就是把密鑰和混淆後的結果進行 xor 運算,但在每一輪使用的密鑰都是根據上一輪的密鑰變換而來的。

看一下動畫:


(圖片來源)

加密模式

AES只能對固定長度的數據進行加密,對於不定長的數據,我們需要把它切分成若干定長的數據,再進行加密解密,這就是我們常說的分組加密。分組加密有 ECBCBCCFBOFB 這幾種加密模式,我們介紹一下 ECB 模式和 CBC 模式。

ECB

最簡單的塊密碼加密模式,加密前根據加密塊大小(如AES為128位)分成若干塊,之後將每塊使用相同的密鑰單獨加密,解密同理。具體見圖:

ECB 模式由於每塊數據的加密是獨立的,所以可以分塊進行並行加密或者解密。它的缺點是相同的明文塊會被加密成相同的密文塊,所以這種方法在某些條件下安全性相對不是很高。

CBC

每個待加密的密碼塊在加密前會先與前一個密碼塊的密文異或然後再用加密器加密,第一個明文塊與一個叫初始化向量IV的數據塊異或。具體見下圖:

完成加密或解密後會更新初始化向量IV,CBC模式安全性更高,但由於對每個數據塊的加密依賴前一個數據塊的加密,所以加密是無法並行的。

PHP 實作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$sourceKey = "TestKey";
$sourceIv = "TestIV";
$cypher = "AES-256-CBC";
$options = OPENSSL_RAW_DATA; //OPENSSL_RAW_DATA、OPENSSL_ZERO_PADDING

$key = substr(hash("sha256", $sourceKey), 0, 32);
$iv = substr(hash('sha256', $sourceIv), 0, 16);

# 加密
$e = base64_encode(openssl_encrypt('YoYoLin', $cypher, $key, $options, $iv));
# 解密
$d = openssl_decrypt(base64_decode($e), $cypher, $key, $options, $iv);

echo $e;
echo '</br>';
echo $d;

Mysql 實作

1
2
3
4
5
6
7
8
# 設置模式
SET block_encryption_mode = 'aes-256-cbc';

# 輸出加密字串 (str, key, iv)
SELECT TO_BASE64(AES_ENCRYPT('我是小飛俠', 'd713884fffad4dc8dd5da087efde2287', 'a49eed4cb8bddb3a')) AS '加密字符串'

# 輸出解密字串 (str, key, iv)
SELECT AES_DECRYPT(FROM_BASE64("IrNseqV16ZDYZWNiI4fAcA=="),'d713884fffad4dc8dd5da087efde2287', 'a49eed4cb8bddb3a') AS '解密字符串'
Author

LinYoYo

Posted on

2021-10-01

Updated on

2022-03-25

Licensed under