ZigでCamelliaブロック暗号を実装する
はじめに
3年近く前にCamelliaのRust実装のcamelliaクレートを書きましたが、最近はZigも少し書くようになったのでZigでも実装してみたいと思って実装しました。
この記事では、上記の実装を参照しながらCamelliaを実装する方法について述べたいと思います。
Camelliaについて
Camelliaは、2000年にNTTと三菱電機によって開発されたブロック暗号です。
CamelliaのインターフェースはAES互換で、ブロック長は128ビット、鍵長は128ビット、192ビット、256ビットです。
CamelliaはAESと同等の安全性と処理性能を有しており、AESと同じくCRYPTRECの電子政府推奨暗号リストに載っています。
CamelliaのアルゴリズムはRFC 3713で説明されています。
RFCの日本語訳もあります。
実装
RFCで仕様が説明されているので、そのとおりに実装すれば暗号化と復号ができます。
Camelliaでは鍵スケジュール部で与えられた鍵から副鍵を生成して、生成した副鍵を使って暗号化と復号を行います。
定数
Camelliaではマスク用の定数値MASK8、MASK32、MASK64、MASK128が定義されています。
今回の実装ではMASK8、MASK128は使用しないので実装内で定義していません。
鍵スケジュール
鍵スケジュール部では与えられた鍵Kから暗号化と復号に使用する副鍵を生成します。
鍵スケジュール部では128ビット変数のKL、KR、KA、KBを使用します。
KL、KRは鍵Kから生成します。
Camellia-128の場合は128ビット鍵KをKLとして使用し、KRには0を設定します。
RFCにはバイトオーダーについて書かれていませんが、アルゴリズム仕様書にバイトオーダーがビッグエンディアンあると書かれているのでKをビッグエンディアンで読み取ります。
Camellia-192の場合は192ビット鍵Kの上位128ビットをKLとして使用し、Kの下位64ビットを64桁左シフトした値とKの下位64ビットをビット反転した値の論理和をKRとして使用します。
Camellia-256の場合は256ビット鍵Kの上位128ビットをKLとして使用し、Kの下位128ビットをKRとして使用します。
KA、KBはKL、KRから生成します。
KA、KBの生成時に使用する64ビット定数Sigma1からSigma6は以下のように定義されています。
副鍵はこれらの変数を左循環シフトした結果の上位64ビットか下位64ビットを使用して生成します。
Camellia-128の場合はKL、KAを使用して64ビットの副鍵kw(ホワイトニングで使用)4個、k(ラウンド鍵)18個、ke(6ラウンドごとに使用)4個の計26個生成します。
Camellia-192、Camellia-256の場合はKL、KR、KA、KBを使用して64ビットの副鍵kw(ホワイトニングで使用)4個、k(ラウンド鍵)24個、ke(6ラウンドごとに使用)6個の計34個生成します。
Zigで左循環シフトはstd.math.rotlでできます。
暗号化
暗号化では最初に128ビットの平文Mを上位64ビットのD1と下位64ビットのD2に分割します。
18ラウンド(Camellia-128)または24ラウンド(Camellia-192、Camellia-256)のFeistel構造を使って行います。
6ラウンドごとにFL関数とFLINV関数を挿入します。
128ビットの暗号文CはD2を64桁左シフトした値とD1の論理和です。
復号
復号は副鍵の順序を反転させて暗号化と同じ処理をすることで行えます。
コンポーネント
F関数
ラウンド関数Fはhttps://datatracker.ietf.org/doc/html/rfc3713#section-2.4.1で説明されています。
今回の実装ではRFCのものよりも高速に処理できることからBotanのF関数を利用しています。
Camelliaでは4つのS-boxを使用します。
SBOX1は以下のように定義されています。
SBOX2からSBOX4は以下の式で求めることができます。
sbox_2[x] = math.rotl(u8, sbox_1[x], 1);
sbox_3[x] = math.rotl(u8, sbox_1[x], 7);
sbox_4[x] = sbox_1[math.rotl(u8, x, 1)];
今回の実装ではSBOX2からSBOX4は事前に計算したものを使用しています。
FL関数とFLINV関数
FL関数とFLINV関数はhttps://datatracker.ietf.org/doc/html/rfc3713#section-2.4.2で説明されています。
テスト
https://datatracker.ietf.org/doc/html/rfc3713#appendix-Aにテストベクターがあるのでこれで正しく実装できたか検証できます。
また、https://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txtにより大きなテストベクターがあります。
今回の実装ではこのテストベクターをYAMLにして、それをZigの標準ライブラリで読み取れるJSONに変換してテストしています。
終わりに
Zig以外のプログラミング言語でも上記のようにRFCに従ったコードを書くことでCamelliaを実装できます。
Zigは128ビット整数型がプリミティブ型なので他のプログラミング言語よりも簡単に実装できるように思いました。
Discussion