情報処理安全確保支援士 2010年 春期 午前2 問04
問題文
S/KEYワンタイムパスワードに関する記述のうち、適切なものはどれか。
選択肢
ア:クライアントは認証要求のたびに、サーバへシーケンス番号と種(Seed)からなるチャレンジデータを送信する。
イ:サーバはクライアントから送られた使い捨てパスワードを演算し、サーバで記憶している前回の使い捨てパスワードと比較することによって、クライアントを認証する。(正解)
ウ:時刻情報を基にパスワードを生成し、クライアント、サーバ間でパスワードを時刻で同期させる。
エ:利用者が設定したパスフレーズは1回ごとに使い捨てる。
🔒 解説は解答すると表示されます
S/KEYワンタイムパスワード【午前2解説】
正解の理由
S/KEYはハッシュ関数の反復(ハッシュチェーン)を利用したワンタイムパスワード方式です。利用者は秘密のパスフレーズ(シークレット)を使ってあらかじめハッシュを反復し、その最終値をサーバに保管します。認証時はサーバがクライアントにシーケンス番号とシード(必要に応じてチャレンジとして提示することが一般的)を示し、クライアントは指定回数だけハッシュを適用した値を送信します。サーバは受け取った値を一度ハッシュし、サーバに記憶している前回の値と一致するかを比較して認証を行います。したがって、選択肢イの記述(サーバが送られた使い捨てパスワードを演算して保存値と比較する)は方式の動作を正確に表しています。
解法ステップ
- S/KEYの基本原理を思い出す:ハッシュ関数Hを用いた反復でワンタイム値を生成する(ハッシュチェーン)。
- 認証フローを整理する:
- 初期登録時にサーバは最終ハッシュ値 を記憶する。
- 認証時、サーバは(場合によっては)シーケンス番号nとシードを提示する。
- クライアントは を送る。サーバは受け取った値を一回ハッシュして と比較する。
- 一致すれば認証成功、サーバは保存値を受け取った値に更新する。
- 各選択肢を上記フローに照らして評価する。
選択肢別の誤答解説
- ア: クライアントは認証要求のたびに、サーバへシーケンス番号と種(Seed)からなるチャレンジデータを送信する。
- 誤り。シーケンス番号とシードは通常サーバ側が保持・提示するものであり、クライアントが毎回送るものではありません。サーバがチャレンジ(シーケンス番号とシード)を示すことが一般的です。
- イ: サーバはクライアントから送られた使い捨てパスワードを演算し、サーバで記憶している前回の使い捨てパスワードと比較することによって、クライアントを認証する。
- 正しい。受信値をハッシュして記憶値と比較する、という動作がS/KEYの本質です。
- ウ: 時刻情報を基にパスワードを生成し、クライアント、サーバ間でパスワードを時刻で同期させる。
- 誤り。時刻同期型のOTP(例:TOTP)とは異なり、S/KEYはハッシュチェーンに基づくもので、時刻同期を必要としません。
- エ: 利用者が設定したパスフレーズは1回ごとに使い捨てる。
- 誤り。利用者のパスフレーズ(シークレット)は複数回のワンタイムパスワード生成に使われます。使い捨てられるのは生成されるワンタイムパスワードそのものであり、シークレット自体は保持されるか再利用されます(端末側で保管・使用される)。
よくある誤解
- サーバはチャレンジを出さない/S/KEYは「チャレンジレス」であるという誤解:
- 実際にはサーバがシーケンス番号とシードを提示することが一般的で、これをチャレンジとして用いる設計が多いです。チャレンジの提示なしに動く設計も理論的には可能ですが、典型的な運用ではサーバ提示が行われます。
- シークレット(パスフレーズ)も毎回使い捨てると考える誤解:
- シークレットはワンタイム値を生成する元になる固定の秘密です。毎回ワンタイム値そのものが使い捨てられますが、シークレットは端末側で引き続き使用されます。
補足コラム
S/KEYはRFC 1760やRFC 2289に規定されている古典的なワンタイムパスワード方式です。概念的には次のように表現できます。秘密をx、ハッシュ関数をHとすると、サーバに保存される初期値は です。認証時にクライアントが を送ると、サーバは受け取った値を一度ハッシュして と比較します。比べて一致すれば、その値は使い捨てとして更新され、次回は n を一つ減らして同様の手続きを行います。
簡単な実装例(概念確認用):
import hashlib
def H(b):
return hashlib.sha1(b).digest()
def iter_hash(secret: bytes, n: int) -> bytes:
v = secret
for _ in range(n):
v = H(v)
return v
# 例: 初期登録
secret = b"mypassword"
n = 1000
stored = iter_hash(secret, n) # サーバ保管値
# 認証時(クライアントが送る値)
client_value = iter_hash(secret, n-1)
# サーバ側検証
if H(client_value) == stored:
# 認証成功 -> stored を client_value に更新
stored = client_value
この例は概念説明用であり、実運用ではシードやシーケンス管理、通信の保護、ハッシュ関数選びに注意が必要です。
FAQ
Q. S/KEYは時刻同期が必要ですか?
A. いいえ。S/KEYはハッシュチェーン方式であり、時刻同期を要求しません。時刻同期型はTOTP等の別方式です。
Q. サーバはいつチャレンジ(シード/シーケンス番号)を出すのですか?
A. 多くの実装では認証前にサーバがクライアントにシーケンス番号とシードを示します。これによりクライアントは正しい反復回数のハッシュ値を計算して送信します。
Q. シークレットが漏えいしたらどうなる?
A. シークレットが漏れると、その人のワンタイム列が予測され得るため危険です。S/KEYはパスフレーズを安全に保つことが前提です。
関連キーワード: S/KEY、ワンタイムパスワード、ハッシュチェーン、RFC2289、チャレンジ応答、OTP

\ せっかくなら /
情報処理安全確保支援士を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

