RFC 1760 The S/KEY One-Time Password System

S/KEY One-Time Passwordとは

ユーザーがネットワークを介して計算機に接続するときを考えると、 ユーザーが入力したPasswordはそのままの形でネットワークを流れていく。 この時に、誰かがネットワーク上の通信を傍受していたとすると、 ログインしようとしたユーザーのPasswordがわかってしまう。
S/KEY One-Time Password System(以下S/KEY)は、 ネットワーク上で通信が傍受されていても ユーザーのパスワードを守ることができるシステムである。

S/KEYは基本的にはユーザーのpasswordを暗号化し、 それをネットワークに流すことで、傍受している誰かには 暗号化されたpasswordしかわからないようにするものである。 暗号化されたpasswordは、1度使用されたものは2度と使われない。 よって、その1度使用された暗号化されたpasswordを第三者が使用しても ログインすることができないので、悪用される恐れがない。

S/KEYの処理の流れ

S/KEYにおいては、暗号化する回数というものが重要である。 まず、S/KEYの初期化時にその暗号化する回数を指定する。 たとえば200回とすると、生のPasswordを200回暗号化したPasswordを サーバー側に保存しておく。
(もちろん初期化するときはサーバーに直接ログインしていなければならない)
ユーザーがログインするときは、その200から1を引いた数、 199という数字(チャレンジ)をユーザーに提示する。 ユーザーは199というチャレンジにより、 クライアント側のローカルな鍵計算プログラムで 生のPasswordを199回暗号化を行い、それをサーバーに転送する。
サーバー側ではその転送された199回暗号化されたpasswordに対して さらに1回暗号化を行い、それがサーバー側に保持してあった 生のPasswordを200回暗号化したものと一致するか比較する。 暗号化される前の生のPasswordが正しいならば、 その比較は一致するはずである。

そして一致したらサーバー側はログインを許可し、 サーバー側に保存してあった生のPasswordを200回暗号化した Passwordを削除して、 代わりにユーザーが送ってきた199回暗号化したPasswordを保存する。 そして次回のログイン時にはサーバーは199-1=198というチャレンジを ユーザーに提示し、ユーザーはクライアント側のローカルな鍵計算プログラムで 生のPasswordを198回暗号化を行い、それをサーバーに転送する。
これにより、毎回生のPasswordの暗号化する回数が違うので、 一度使用されたPasswordは2度と使われることがなく、 ネットワーク上を一度流れた暗号化されたPasswordを使っても ログインは出来ない。

利用している暗号化方式について

暗号化には、hash関数のMD4(またはMD5)が用いられる。 これは、暗号化されたデータから元のデータを推測することが 困難である。MD4はRFC1320に規定されており、任意のbit数の 入力から計算結果を128bitで出力する。 S/KEYでは入力を64bit、出力をxor演算で128bitから64bitに 折り畳んで使用する。

S/KEYの初期化時の処理の流れ

keyinitコマンドで最初のPasswordの登録、登録したPasswordの変更、 再登録を行う。keyinitを実行するとサーバーに直接ログインしているか 確認のメッセージが流れ、Passwordの入力を求められる。
(-sオプションを使うと、直接ログインしていなくても初期化は可能である) ここでパスワードを入力すると、デフォルトで99回の暗号化が行われ、 結果がサーバー側に保存され、画面に表示される。 ここで、暗号化された結果と同時にseed(種)と呼ばれる 文字列が表示される。これは、keyinitが勝手に作った文字列である。 Passwordを暗号化するときはこの文字列も使用する。 これを使うことにより、再度keyinitで初期化する時に前回の 初期化と同じPasswordを使っても暗号化されたPasswordは違うものになる。

-sオプションを使用すると、暗号化の回数とseedを聞いてくる。 その後で、暗号化されたPasswordを聞いてくる。 ここで、ローカルな暗号化プログラムを使用して 指定したseedを使って指定した回数暗号化し、 サーバー側に保存しておく暗号化されたPasswordを 結果をネットワークを介してサーバー側に伝えることにより初期化を行う。

S/KEYのログイン時の処理の流れ

クライアント側からtelnetやrlogin等で接続してログインネームを入力すると、 サーバー側からseedと暗号化する回数の数字が送られてくる。 ユーザーはその種を使い、クライアント側のローカルな暗号化 プログラムで指定された回数暗号化を行い、 その暗号化されたpasswordをサーバー側へ転送する。 サーバー側はその暗号化されたpasswordを検証してログインの可否を決める。

seedの決定方法

seedは、「One-Time Passwordを初期化する時点でのサーバーのホスト名 の先頭の数文字(デフォルトは2文字)」に「strftime()で取得した時間を 数字列に直したもの」を足したものが使われる。

設定ファイルの内容

S/KEYでは、/etc/skey.accessを設定ファイルとして使用する。 内容として記述できるものは以下の6つである。
permit hostname ホスト名
指定したホストからのログインを許可する。
permit internet アドレスマスク
指定したIPアドレスからのログインを許可する。
permit port ポート名
指定したポート名からのログインを許可する。
permit user ユーザー名
指定したユーザーとしてのログインを許可する。
permit group グループ名
指定したグループのユーザーとしてのログインを許可する。
deny
この行までの条件にあわなかったログインは許可しない。

暗号化の計算結果について

暗号化を行うと結果として6つの英単語が示される。 これは、暗号化の結果である64bitのbit列を6つにわけ、 それぞれbitの状態に対応して1~4文字の単語に変換する。 単語はRFCで指定された2048種の中から選ばれ、 それぞれに11bitづつ割り当てられる。6つの単語でそれぞれ11bit 割り当てると66bitになり2bit余るが、 その残りの2bitはパリティビットとして使用される。 逆に、入力された英単語の列からビット列を復元する時は 二分探索を用いて64bitビット分のパリティを計算して 実際のパリティと等しいか調べる。

まとめ

S/KEYは、ファイルシステムの中の情報を見られても、 ネットワークを流れる情報を傍受されても安全というシステムである。 しかし、いったんログインしてしまうと、中の通信内容は 暗号化しない限り筒抜けになることは注意しなければならない。 例えば、ネットワークを介してログインして、そこからさらに別の計算機に ログインしようとする場合は通信路そのものが暗号化されていないと Passwordはそのまま流れてしまう。 自分の環境がどれだけ安全であるのかということを ユーザーはいつも意識する必要があるといえるだろう。