Written on
AESを実装しよう(1)
共通鍵暗号アルゴリズムの1つであるAESは,無線LAN通信(Wi-Fi)の暗号化をはじめとして身の回りの様々な場所で使われています.それがどのように動作しているのかの学習として,実装しながら理解を深めていこうと思います.
AESについて
AESはその公募を勝ち抜いたRijndaelと呼ばれるアルゴリズムが元になっています.Rijndaelではブロック長,鍵長がいくつかから選べるようになっていましたが,AESとして採用されるにあたりデータ長が128bit,鍵長が128, 192, 256bitの中から選択するようになりました.
AESの構成部品は大きく分けて暗号化部で用いられる4つの関数(SubBytes, ShiftRows, MixColumns, AddRoundKey)と,鍵拡張関数(KeyExpansion)があり,これらを複数ラウンド適用することにより暗号文を得ます.
またラウンド数は鍵長によって決められています.
- 128bit鍵 -> 10ラウンド
- 192bit鍵 -> 12ラウンド
- 256bit鍵 -> 14ラウンド
今回は鍵長128bitのAES(AES-128)をD言語を用いて実装していきます.
暗号化概要
今回は128bit鍵としましたので,ラウンド数は10ラウンドとなります. 全体としての構造は下図のようになっています.最終ラウンドだけMixColumnsが省かれていることに注意してください.
コードに起こしてみます.
ubyte[16] text = { ... };
ubyte[16] key = { ... };
void encryption(){
addRoundKey();
foreach(i; 0 .. 9){
subBytes();
shiftRows();
mixColumns();
keyExpansion(i);
addRoundKey();
}
subBytes();
shiftRows();
keyExpansion(9);
addRoundKey();
}
まだむずかしいところはなさそうです.
SubBytes
各バイトに対してS-boxと呼ばれる非線形な置換を施します.そのS-boxは以下のように2段階の操作を行って求められます.
まず1つ目の操作として,入力に対して,有限体
ここで
例として
これを見るに掛け算表を作ってしまえば逆元を求められそうです.AESでは
そして2つ目の操作として,各ビットに対して以下の行列変換を施します.
これらを毎ラウンド実行しても良いのですがなかなか大変そうな処理です.そこで前もってS-boxの変換表を作成しておき,SubBytesを実行する際にはそれを用いることにしてしまいます.
その2に続きます.