基本情報技術者 2014年 春期 午前(科目A) 問42
問題文
パスワードを用いて利用者を認証する方法のうち、適切なものはどれか。
選択肢
ア:パスワードに対応する利用者IDのハッシュ値を登録しておき、認証時に入力されたパスワードをハッシュ関数で変換して比較する。
イ:パスワードに対応する利用者IDのハッシュ値を登録しておき、認証時に入力された利用者IDをハッシュ関数で変換して比較する。
ウ:パスワードをハッシュ値に変換して登録しておき、認証時に入力されたパスワードをハッシュ関数で変換して比較する。(正解)
エ:パスワードをハッシュ値に変換して登録しておき、認証時に入力された利用者IDをハッシュ関数で変換して比較する。
🔒 解説は解答すると表示されます
パスワードハッシュ認証【午前解説】
正解の理由
選択肢ウは、パスワードそのものではなくパスワードのハッシュ値を保存し、認証時に入力されたパスワードを同じハッシュ関数で変換して保存値と比較する方式を示しています。これはパスワードを平文で保存するリスクを減らす基本的な方法です。正しい認証の比較式は
のように表され、保存値はすでに元のパスワードをハッシュした結果であるため、認証時は入力をハッシュして保存値と比較します(保存値をさらにハッシュする=二重ハッシュは意味が異なるので避ける)。よってパスワードのハッシュを保存して比較する選択肢が適切です。
のように表され、保存値はすでに元のパスワードをハッシュした結果であるため、認証時は入力をハッシュして保存値と比較します(保存値をさらにハッシュする=二重ハッシュは意味が異なるので避ける)。よってパスワードのハッシュを保存して比較する選択肢が適切です。
解法ステップ
- 問題が「パスワードを用いて認証する方法」を問うていることを確認する(認証の対象は「秘匿情報」であるパスワード)。
- 各選択肢が何を保存し、認証時に何を比較するかを整理する(保存対象:利用者IDかパスワードか、比較対象:入力されたIDかパスワードか)。
- 保存すべきは「パスワードのハッシュ」であり、認証時に比較すべきは「入力パスワードをハッシュした値」であることを満たす選択肢を選ぶ。
- 上の条件に合致するのが選択肢ウであると判断する。
選択肢別の誤答解説
-
ア: 「パスワードに対応する利用者IDのハッシュ値を登録しておき、認証時に入力されたパスワードをハッシュして比較する」
→ 保存値が(ハッシュ化された)利用者IDであり、認証時に比較するのはハッシュ化されたパスワードです。IDとパスワードは別の情報なので一致せず、認証が成立しません。誤りです。 -
イ: 「パスワードに対応する利用者IDのハッシュ値を登録しておき、認証時に入力された利用者IDをハッシュして比較する」
→ これはIDの一致確認(しかもIDをハッシュして比較)であり、パスワードを用いた認証ではありません。認証要件を満たさないため誤りです。 -
ウ: 「パスワードをハッシュ値に変換して登録しておき、認証時に入力されたパスワードをハッシュして比較する」
→ 保存値が で、認証時に と比較する流れを正しく示しています。適切です。 -
エ: 「パスワードをハッシュ値に変換して登録しておき、認証時に入力された利用者IDをハッシュして比較する」
→ 保存値はパスワードのハッシュですが、比較対象が利用者IDのハッシュになっており目的の認証になりません。誤りです。
よくある誤解
- ハッシュ化すれば無条件に安全になる
- ハッシュ化は平文保存より安全ですが、ソルトやストレッチ(反復)を行わないとレインボーテーブル攻撃や総当たりに弱くなります。さらに強力な専用アルゴリズム(bcrypt, scrypt, Argon2)を使うべきです。
- ユーザIDもハッシュ化すれば同じ扱いで良い
- ユーザIDは識別子であり認証の秘密情報ではありません。IDをハッシュ化しても認証の代替にはなりません(また検索性などで不便になります)。
- 保存値をさらにハッシュ(H(保存値))して比較すれば安全だと思う誤解
- 保存値が既に の場合、認証時に と比較するのが正しい。 のような二重ハッシュの表記/実装は意味が変わり誤りになる可能性があります。
補足コラム
実務では以下を必ず考慮してください。
- ソルト(ユーザごとにランダムな値)を使い、保存は「ソルト + ハッシュ値」。たとえば保存形式は
salt || H(salt || password)。 - ハッシュ関数は高速な一般ハッシュ(SHA系)ではなく、計算コストを調整できる専用関数(bcrypt, scrypt, Argon2)を推奨。これにより総当たり攻撃のコストを上げられます。
- 設計例(概念): ログイン時はまずユーザ名で記録を取得し、保存されたソルトを取り出して入力パスワードに対して同じ処理を行い、保存ハッシュと比較する。
- 実装例(簡易、教育目的):
# 注意: 実運用では bcrypt や argon2 を使ってください
import hashlib, os
def hash_with_salt(password, salt=None):
if salt is None:
salt = os.urandom(16)
h = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100_000)
return salt, h
# 登録時
salt, stored_h = hash_with_salt('ユーザのパスワード')
# 認証時
salt_from_db = salt
_, h_attempt = hash_with_salt('入力されたパスワード', salt_from_db)
assert h_attempt == stored_h # Trueなら認証成功
FAQ
Q: なぜユーザIDをハッシュして比較する方式はダメなのですか?
A: 認証は「本人しか知らない秘密(パスワード)」で行うべきで、IDは公開されることが多い識別子です。IDの一致確認だけでは本人確認になりません。
A: 認証は「本人しか知らない秘密(パスワード)」で行うべきで、IDは公開されることが多い識別子です。IDの一致確認だけでは本人確認になりません。
Q: ハッシュ化した値をさらにハッシュして保存すれば安全ですか?
A: 二重ハッシュは設計上の意図が不明瞭になりやすく、正しく運用しないと逆にセキュリティの穴を作る場合があります。標準的な対策はソルト+適切なストレッチング(bcrypt等)です。
A: 二重ハッシュは設計上の意図が不明瞭になりやすく、正しく運用しないと逆にセキュリティの穴を作る場合があります。標準的な対策はソルト+適切なストレッチング(bcrypt等)です。
Q: クライアント側でハッシュしてサーバに送るのは有効ですか?
A: 一部のリスク軽減にはなるものの、ネットワーク上に流れるハッシュ値自体がそのまま「代替パスワード」になり得ます。TLS等で通信を保護し、サーバ側でも適切にハッシュ(+ソルト)して保存するのが望ましいです。
A: 一部のリスク軽減にはなるものの、ネットワーク上に流れるハッシュ値自体がそのまま「代替パスワード」になり得ます。TLS等で通信を保護し、サーバ側でも適切にハッシュ(+ソルト)して保存するのが望ましいです。
関連キーワード: パスワードハッシュ、ソルト、ストレッチング、bcrypt、Argon2、レインボーテーブル、ハッシュ関数、認証方式、ペッパー

\ せっかくなら /
基本情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

