SMLでSHA3を実装しました

SHA(3)はNISTが定めたセキュアなハッシュアルゴリズムの標準規格です。
今回SHA2のSML実装に続きSMLでSHA3を実装し、SHA3SMLとして公開しました。

現在のところSML/NJ 110.99で動作を確認しています。

実装状況

SHA3SMLは直接FIPS 202を確認して実装しました。
以下に対応状況を示します。

SHA3にはSHA2と同じく4つの出力ビット幅によるバリエーションが用意されており、SHA3SMLはこれらには全て対応していますが、SHAKE は未実装です*1

SHA3-224 SHA3-256 SHA3-384 SHA3-512 SHAKE128 SHAKE256
実装

(SHAKE というのはハッシュ関数ではないものの、他の関数と同じくFIPS202で定義されておりハッシュを一般化したような関数です。)


またNISTは、ある実装がFIPS 202に適合しているかのテスト方法をSHA3VSとして公開しています。ここでは以下のような実装の制限についても定められていますが、SHA3SMLではどれも対応済みです。

✅ 空入力のサポート
✅ バイト指向入力のサポート
✅ ビット指向入力のサポート

インストール方法

ml-makedependsを使うと依存関係が取得出来ることに気付いたので Makefile を書きました。なので普通に make install 出来ます。
ただし PATHCONFIG ファイルはどこに置くか人によるため Makefile を複雑にするより手動に任せることにしました。

$ make install PREFIX=~/.smlnj
(* ..snip.. *)
================================================================
libsha3sml has been installed to:
        /home/eldesh/.smlnj/lib/libsha3sml.cm
Add an entry to your pathconfig (e.g. ~/.smlnj-pathconfig) such like:
        libsha3sml.cm /home/eldesh/.smlnj/lib/libsha3sml.cm
Then you can load the library like
        "CM.make "$/libsha3sml.cm";".
================================================================

make installすると上記のようにメッセージが出るので(例えば)以下のように PATHCONFIG ファイルに追記します。

$ echo "libsha3sml.cm /home/eldesh/.smlnj/lib/libsha3sml.cm" >> ~/.smlnj-pathconfig

使い方

いつも通り普通に CM.make するだけです。

$ sml
- CM.make "$/libsha3sml.cm";
(* ..snip.. *)
- Sha3.toString (Sha3.hashString Sha3Kind.Sha3_256 "");
val it = "A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A" :
  string


念のためsha3sumコマンドで確認します。

$ echo -n "" | sha3sum -a 256 | tr [:lower:] [:upper:]
A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A  -

一致してますね。

テスト

NISTの提供している入出力例と適合試験 CAVP のテストベクタを全てパスすることを確認しています。
手元で実行するには make test します。

終わりに

SHA3はSHA2に比べて非常に簡単な構造で実装し易かったです。
例えばSHA2には内部的に用いるナゾの数値テーブルがビット幅ごとに用意されているんですが、SHA3にはその類いのマジックナンバーは全くありません。
また規格の文書自体もかなり読みやすく書かれていると思います。

SMLのプロジェクトとしては、NJ向けの Makefile が書けるようになった点が収穫でした。
これで .cm/ をコピーとかする必要が無いのでユーザとしても*2大分手間が省けます。

*1:すぐ実装します

*2:そんなもん存在しないが