前言:
這篇不會跟你解釋AES裡面怎麼XOR、怎麼移位,這篇我想說的是哪幾個規格以及怎麼寫。
在我的百寶箱中,使用頻率最高也最重要的莫過於加密相關,其中AES是重點之一。
程式碼:
這份程式碼裡面包括多個程式語言的AES實做,是我自己常用的百寶箱工具。裡面的AES程式碼基本上相互驗證過,原則上都能互相正常編碼解碼(除了my_browser_js_test,能編碼,不能解碼)。
https://gitlab.com/ycfunet/my_aes_code_test
說明:
AES是對稱加密演算法,邏輯是你用一個密碼把字串加密,另一個人用同一個密碼把字串解密,密碼就是鑰匙,關鍵字叫金鑰(Key),加密後的資料叫密文,未加密的原始字串叫明文。
AES的核心邏輯是,用固定長度的金鑰,把固定長度的明文加密成密文,反過來,固定長度的密文用固定長度的金鑰解密成明文。
因此,最基本的認知是,金鑰長度固定,明文長度也固定,咦...我使用時,沒聽說明文規定長度啊,有些AES金鑰也沒規定長度啊。
這時引出兩個AES的重點,一個叫金鑰雜湊,一個叫Padding。
因為密碼(金鑰)可能長度不一,為了讓密碼(金鑰)可以是任意長度,通常會用SHA256把密碼進行雜湊,就能取出固定長度的金鑰,而這個長度就跟使用的加密規格相關,例如AES256,就表示256 Bits,SHA也用256 Bits。
Padding翻譯叫填充,剛剛提到加密和解密時,明文必須是固定長度,不固定長度怎麼辦呢?會把明文填充固定字元,讓它長度固定。
Padding有多種填充內容,直覺想到填0,對這是一種,目前常用的是根據空白數量填數字,例如空3格就填0x03 0x03 0x03,這種目前是主流叫做PKCS7Padding。
到這裡,我們知道能用SHA256把密碼雜湊成密文,能用Padding把明文填充成固定長度,這時候會發現,固定的金鑰+固定的明文=固定的密文。
這很OK,但感覺每次的密文都一樣好像怪怪的,有沒有辦法讓它每次密文都不同?這時引出加密常見的重點,加鹽(Salt)。
所謂的加鹽,真的如字面意思,就是加料,在AES中,規範了多種模式,我們只要記得常用的2種,ECB和CBC,ECB就是上面寫的未加鹽的就稱為ECB,加鹽的模式就稱為CBC。
AES-CBC的加鹽是說,CBC規定了一個欄位,稱為IV,這個欄位就是加鹽的鹽巴,AES-CBC加密時將密鑰+IV當密鑰,一起將明文加密,解密時將密鑰+IV當密鑰,一起將密文解密。IV通常是16字元(128Bits)。
因為IV是鹽巴,通常會用亂數產生,那既然是亂數產生,解密時如何知道?
一般會把IV加在密文最前面,變成
IV(16個字)+密文
解密時,先切割出IV和密文,然後把設定IV和手上的密鑰,把密文解密成明文。
IV放密文最前面是慣例,也可以和密文一起放在兩端,傳送時只傳送密文,但既然是加鹽,通常目的是讓密文判讀性更低,放在密文最前面會讓密文每次都不一樣,減少一致性。
最後一個知識點,實作會發現,AES加密後的密文,是Bytes的Binary,這不好處理呀。
在最後要提供密文時,Binary不容易使用,通常會編碼讓它字串化,一般都用BASE64或HEX,這裡有個小小誤區,BASE64有2種,一種是一般的BASE64,但一般的BASE64會有特殊字元,在網頁傳輸時,可能因為HTTP GET不支援的字元,因此有個變形是BASE64 URLEncoding,這兩種BASE64的結果是不同的。
以上就是AES知識點,還是蠻長的,但不用管底層XOR、移位邏輯。
結論:
這次的文章放了一陣子,圖片是Claude-Code (GLM-5/GLM-4.7) 用Excalidraw MCP畫的。









沒有留言:
張貼留言