JSによるcrypt関数の実装

だいぶ前にJSで実装したcrypt関数を紹介します。crypt関数はパスワードを暗号化するための関数です。

char *crypt(const char *key, const char *salt);

Perlではビルトインで使えます。実際に使ってみるとこんな感じです。keyは8文字(8 bytes)まで、saltには2文字(2 bytes)までしか使えません。

% perl -e "print(crypt('Hello', 'wl'))"
 wlCoUbJ6h11vY

saltとkey、どちらが変わっても出力結果が変わります。パスワード認証をするときはユーザーのパスワードをそのまま保存するのではなく、このような関数でハッシュにしてから保存しなさいというのはよく言われていますが、さらにその際にユーザーの入力をそのままハッシュに掛けるとハッシュ表が盗まれた時にレインボー攻撃と呼ばれる攻撃ができてしまうので、keyにユーザーごとに異なるsalt(塩)も加えてからハッシュにかける…というのが典型的な使い方です(受け売りです)。

2chのトリップはこのcrypt関数を使っており、この(ledyba.org)サイトに設置してあったCGI「2chトリップ生成システム」をCGIからJSへ移植するために必要になったので書いたというわけです。

Apacheから流行りのnginxに移行したのですが、nginxではCGIを動かすのがかなり面倒臭くなっており、JSで書きなおすのが一番楽そうだったのでそうしました。Public DomainのcryptのCでの実装があったので、それをほぼそのまま移植しています。

ただし、暗号は理論だけでなく実装も注意深く行う必要があり、たとえばキーによって処理時間が変わるような実装だとその差を使ったタイミング攻撃ができたりします。 この実装は私が適当に作ったものなので、2chのトリップのようなどうでもいいアプリならともかく、実際に暗号に用いる場合はもっと有名で枯れた実装を使うのをお勧めします。