← 用語集一覧へ戻る

パスワード認証

Password Authentication
security beginner
ユーザーが設定した秘密の文字列(パスワード)と、システムに登録されている文字列を比較して本人確認を行う、最も一般的な認証方式。
パスワード認証 (Password Authentication)

概要(サマリー)

パスワード認証とは、ユーザーが事前に設定した「秘密の文字列(パスワード)」をシステムに入力し、システム側に登録されているデータと一致するかどうかを比較して本人であることを確認する、最も一般的で古典的な認証方式である。

身近な例で言えば、秘密の会員制クラブの入り口で「山」と問いかけられたのに対し、「川」という正しい合言葉を答えることで中に入れてもらうような仕組みである。ユーザー名(ID)が「誰であるか(主張)」を示し、パスワードが「本人であることの証明(認証)」の役割を果たす。

詳細解説

最も身近な「秘密の合言葉」

パスワード認証は、知識要素(本人が知っていること)に基づく認証方式である。特別な機器を用意しなくても、ユーザーが頭の中で記憶している文字列さえあればいつでも認証を行えるため、古くからWebサービスやシステムログインの主役に据えられてきた。

パスワード認証の仕組みとデータベース保存

パスワード認証を行うWebアプリを作る際、最も注意しなければならないのが「ユーザーのパスワードをどのようにデータベースに保管するか」である。

ユーザーが入力した生のパスワード(平文)をそのままデータベースに保存してしまうと、万が一データベースがハッキングなどで外部に漏洩した際、すべてのユーザーのパスワードがそのまま流出してしまい、他のサイトへの不正ログインなどに悪用される。

極めて危険な例(平文での保存)

// パスワードをそのままSQLに流し込んで保存(絶対にやってはいけない)
$query = "INSERT INTO users (username, password) VALUES ('user1', '" . $_POST['password'] . "')";

パスワードのハッシュ化(ソルトとストレッチング)

安全にパスワードを保存するためには、パスワードをハッシュ(元に戻せないように変換)して保管する。

ハッシュ化とは、あるデータを入力すると、規則性のない固定長の文字列(ハッシュ値)を出力する処理である。ハッシュ値から元のパスワードを復元することは極めて困難(不可逆)であるため、データベースにはハッシュ化された値のみを保存する。

安全な例(ハッシュ化して保存)

// パスワードを安全なハッシュ関数(bcryptなど)でハッシュ化
$hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT);

// データベースにはハッシュ化された文字列を保存する
$query = "INSERT INTO users (username, password) VALUES ('user1', '" . $hashedPassword . "')";

検証(ログイン)時は、ユーザーが入力したパスワードを同じ仕組みで検証し、ハッシュ値が一致するかどうかを確認する。

// データベースから取得したハッシュ値と、入力されたパスワードを検証
if (password_verify($_POST['password'], $dbHashedPassword)) {
    echo "ログイン成功";
}

ハッシュ化をさらに安全にするため、以下の技術が自動的、または手動で適用される。
- ソルト(Salt): パスワードの先頭や末尾に、ランダムな文字列(塩)を付け足してからハッシュ化する。これにより、同じ「password123」という単純なパスワードを設定したユーザー同士であっても、データベース上のハッシュ値が異なるようになり、ハッシュ値の対照表(レインボーテーブル)を使った解析を防ぐ。
- ストレッチング(Stretching): ハッシュ化の計算を数千回、数万回と繰り返す。計算コストを意図的に高くすることで、攻撃者が総当たりでパスワードを推測する速度を大幅に低下させる。

パスワード認証のセキュリティリスク(漏洩と推測)

パスワード認証には、その手軽さゆえに以下のような固有の脆弱性がある。

  1. 推測されやすいパスワードの使用: 「123456」や「password」といった簡単な文字列、誕生日やペットの名前などを設定してしまうことによる、第三者からの不正ログイン。
  2. パスワードの使い回し: 複数のサービスで同じIDとパスワードを使い回していると、セキュリティの甘い1つのサイトから漏洩したリストを使って、他の主要なサイト(SNSや金融機関など)に次々とログインされてしまう(リスト型アカウントハック)。
  3. キーロガーやフィッシング: ユーザー自身が偽のWebサイトに入力してしまったり、PCに感染したウイルスによってキー入力を盗み取られたりするリスク。

パスワード認証を強化する多要素認証(MFA)

これらのリスクを軽減するため、現在のWeb開発ではパスワード認証単体に頼るのではなく、スマートフォンの認証アプリやSMSに送信されるワンタイムパスワードなどを組み合わせた二要素認証(多要素認証)を導入することが強く推奨されている。

AIコーディングとの関係

AIに「ユーザー登録機能のサンプルコードを書いて」と頼むと、言語やフレームワークによっては、パスワードをハッシュ化せずに平文で保存する簡易的なコードを出力することがある。

開発の現場や本番環境でそのまま使えるセキュアなコードにするためには、AIに対して「パスワードのハッシュ化には最新の推奨アルゴリズム(bcryptArgon2 など)を使い、生のパスワードはログやデータベースに一切残さないようにしてください」と明示的に求めることが重要である。

よくある勘違い

暗号化(可逆)してデータベースに保存すれば安全?

暗号化」と「ハッシュ化」は異なる技術である。

暗号化は、鍵(キー)を使えば元のデータに戻すことができる「可逆」な処理である。もしサーバー内に保存されている暗号化キーが漏洩した場合、データベース内の暗号化されたパスワードはすべて元に戻されてしまう。パスワード保存においては、元に戻す必要がないため、復元不可能な「ハッシュ化」を用いるのが鉄則である。

パスワードが長ければ長いほど絶対に安全?

パスワードの長さ(桁数)を増やすことは、総当たり攻撃(ブルートフォース攻撃)に対する強度を飛躍的に高めるため、基本的には非常に有効である。

しかし、「password1234567890」のように、予測しやすい並びで長くしただけでは、辞書攻撃(よく使われる単語やパターンの組み合わせ)によって簡単に破られてしまう。長さだけでなく、文字の種類(大文字・小文字・数字・記号)を混ぜること、そして何より使い回しを避けることが重要である。

定期的にパスワードを変更させるのが最も効果的?

かつては「数ヶ月に一度パスワードを変更すること」がセキュリティ対策として推奨されていた。

しかし現在では、頻繁な変更を強制すると、ユーザーが忘れないように「password1」「password2」といった安易なパターンの使い回しや、メモの貼り付けなどを行うようになり、かえってセキュリティが低下することがわかっている。そのため、現在は「推測されにくい複雑なパスワードを設定し、使い回さずに使い続ける(二要素認証を併用する)」という方針が推奨されている。

まとめ

  • パスワード認証は、ユーザーだけが知っている文字列と登録データを比較する本人確認方法。
  • 生のパスワード(平文)をデータベースに保存することは絶対に避け、ハッシュ化して保存する。
  • ハッシュ化する際は、解析を防ぐために「ソルト(Salt)」や「ストレッチング」を適用する。
  • パスワードの使い回しや単純なパスワードは、他のアカウントへの不正ログインを引き起こす原因になる。
  • セキュリティを高めるために、二要素認証(多要素認証)の併用や、パスキーなどの新しい認証手段への移行が進んでいる。

情報ソース

より詳しくAIに聞いてみよう

  • パスワードのハッシュ化における「ソルト(Salt)」の役割を、ポテトチップスに塩を振る比喩を使って初心者向けに説明してください。
  • bcryptscryptArgon2 の違いと、現在Webアプリケーション開発でどのハッシュアルゴリズムを使うべきかを教えてください。
  • Node.jsbcrypt ライブラリを使って、パスワードをハッシュ化してデータベースに保存し、ログイン時にパスワードを検証するJavaScriptコードを書いてください。
  • AIにログイン機能を備えたWebアプリのコードを書かせるとき、セキュリティの脆弱性を防ぎ、パスワードを安全に扱うためのプロンプトのコツを教えてください。
  • 「パスワードリスト攻撃(リスト型攻撃)」とは何か、そしてシステム開発者がこの攻撃からユーザーを守るためにできる対策を教えてください。