SSH鍵認証 vs パスワード認証 - なぜ鍵が安全なのか

SSH鍵認証 vs パスワード認証 - なぜ鍵が安全なのか

この記事で解決できること

  • SSH鍵認証とパスワード認証の 本質的な違い が分かる
  • 「なぜ鍵の方が安全なのか」を 暗号の仕組みから 説明できる
  • ssh-keygen での鍵作成・設置・パスワード認証無効化まで 実務の型 が身につく

結論(先に要点)

  • パスワード認証は 秘密(パスワード)をサーバ側で照合 する。鍵認証は 秘密(秘密鍵)をクライアントから一切出さない
  • 鍵認証は 総当たり攻撃・パスワード使い回し・漏洩リスク に構造的に強い
  • 本番サーバは 鍵認証 + パスワード認証無効化 が定番の型

前提(対象環境)

  • OpenSSH(Ubuntu / Debian / RHEL 系など一般的なLinuxサーバのSSH実装)
  • クライアントもOpenSSH(macOS / Linux / WSL / Windows 10以降)

SSH鍵認証とパスワード認証は何が違うのか?

結論: パスワード認証は「知っている秘密」を毎回サーバへ送って照合する。鍵認証は「持っている秘密鍵」をネットワークに出さずに所有を証明する。

両者は「本人をどう確かめるか」の方式が根本的に異なる。

観点 パスワード認証 鍵認証(公開鍵認証)
秘密の正体 パスワード(記憶) 秘密鍵(ファイル)
秘密の流れ 暗号化された経路でサーバへ送る ネットワークに 出さない
サーバ側が持つもの パスワードのハッシュ 公開鍵(authorized_keys
突破の主な経路 推測・総当たり・使い回し・フィッシング 秘密鍵ファイルの盗難

パスワードは「頭の中の文字列」、秘密鍵は「手元のファイル」。守るべき対象の性質が違うので、対策の考え方も変わる。

なぜ鍵認証の方が安全なのか?

結論: 秘密鍵がネットワークを流れないため盗聴で奪えず、鍵長が事実上総当たり不能で、サーバ側が漏洩しても秘密鍵は復元できないため。

鍵認証の安全性は主に3つの構造から生まれる。

1. 秘密がネットワークを流れない

パスワード認証では、暗号化されているとはいえパスワードそのものがサーバへ届く。鍵認証では秘密鍵はクライアントに留まり、送られるのは 署名(秘密鍵で作った証明)だけ。秘密鍵自体は経路上に存在しない。

2. 総当たりが事実上不可能

人間が覚えられるパスワードは桁数・複雑さに限界があり、総当たり・辞書攻撃の標的になる。一方 Ed25519 や 2048bit 以上の RSA 鍵は、鍵空間が天文学的で総当たりは現実的でない。

3. サーバ漏洩に強い

サーバが保持するのは 公開鍵 だけ。公開鍵から秘密鍵を逆算することはできないため、authorized_keys が流出しても他人がログインできるようにはならない。パスワードのハッシュ流出(オフライン解析の起点)とは前提が違う。

「鍵認証は安全」は 秘密鍵を守れている前提 が成り立つ場合の話。秘密鍵ファイルそのものを盗まれれば突破される。守る対象がパスワードから秘密鍵ファイルに移っただけ、という視点を忘れない。

公開鍵と秘密鍵はどう機能するのか?

結論: クライアントが秘密鍵で署名し、サーバが対応する公開鍵で検証する。秘密鍵を渡さずに「秘密鍵を持っている」ことを証明できる。

鍵認証は 公開鍵暗号 に基づくチャレンジ・レスポンスで成立する。流れは概ね次の通り。

  1. クライアントが「この公開鍵で認証したい」とサーバへ伝える
  2. サーバは authorized_keys に該当する公開鍵があるか確認する
  3. クライアントはセッション固有のデータに 秘密鍵で署名 して返す
  4. サーバは 公開鍵で署名を検証 する。一致すれば本人と判断する

ポイントは、署名はセッションごとに異なるデータに対して作られるため、過去の通信を盗聴・再生しても次の認証には使えないこと。秘密鍵そのものは一度もネットワークに出ない。

公開鍵 = 配ってよい錠前、秘密鍵 = 手元に隠す鍵、というイメージ。錠前(公開鍵)はサーバに何個でも置けるが、それを開けられるのは対応する鍵(秘密鍵)を持つ本人だけ。

鍵ペアをどう作成して設置するのか?

結論: ssh-keygen -t ed25519 で鍵ペアを作り、ssh-copy-id で公開鍵をサーバの authorized_keys に設置する。

1. 鍵ペアを作成する

$ ssh-keygen -t ed25519 -C "you@example.com"
  • -t ed25519:現在の推奨アルゴリズム(高速で安全。古い環境向けには -t rsa -b 4096
  • -C:コメント(どの鍵か後で識別するための目印)
  • 生成物:秘密鍵 ~/.ssh/id_ed25519 と 公開鍵 ~/.ssh/id_ed25519.pub

途中で パスフレーズ を求められる。これは秘密鍵ファイル自体を暗号化する追加の鍵で、設定を強く推奨する(後述)。

2. 公開鍵をサーバへ設置する

$ ssh-copy-id user@server

ssh-copy-id は公開鍵をサーバの ~/.ssh/authorized_keys に安全に追記し、権限も適切に設定する。手動で行う場合は公開鍵(.pub の方)の中身を authorized_keys に1行追記する。

設置するのは 公開鍵(.pub だけ。秘密鍵(id_ed25519)をサーバへコピーしてはいけない。秘密鍵は手元のクライアントから出さないのが大原則。

3. 接続を確認する

$ ssh user@server

パスワードを聞かれずに(またはパスフレーズだけで)ログインできれば成功。

パスワード認証は無効化すべきか?

結論: 鍵認証が確実に動くことを確認した上で、本番サーバはパスワード認証を無効化するのが定番。総当たりの入口を物理的に塞げる。

鍵認証を有効にしても、パスワード認証が生きていれば総当たり攻撃の入口は残る。/etc/ssh/sshd_config で無効化する。

# /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no

設定後、SSHサービスを再起動する。

$ sudo systemctl restart ssh      # Debian / Ubuntu 系
# RHEL 系はサービス名が sshd
$ sudo systemctl restart sshd

秘密鍵を安全に扱うには?

結論: パスフレーズを設定し、~/.ssh と秘密鍵のパーミッションを絞り、ssh-agent で入力負担を減らす。

鍵認証の安全性は秘密鍵を守れている前提に立つ。最低限、次を守る。

パスフレーズを設定する

秘密鍵にパスフレーズを掛けておけば、ファイルを盗まれても即座には使えない。ssh-keygen 実行時に設定するのが最も簡単。

パーミッションを絞る

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_ed25519
$ chmod 600 ~/.ssh/authorized_keys

OpenSSH は秘密鍵や ~/.ssh の権限が緩いと、安全のため認証を拒否する。権限エラーで弾かれる定番ポイント。

ssh-agent で入力を減らす

$ eval "$(ssh-agent -s)"
$ ssh-add ~/.ssh/id_ed25519

ssh-agent にパスフレーズ解除済みの鍵を預けておくと、セッション中はパスフレーズの再入力が不要になる。安全性(パスフレーズあり)と利便性を両立できる。

やってはいけないこと:

  • 秘密鍵をメールやチャット、クラウドストレージで共有する
  • 秘密鍵を複数人で使い回す(誰の操作か追跡できなくなる)
  • パスフレーズなしの秘密鍵を持ち運ぶノートPCに置きっぱなしにする

まとめ:鍵認証への移行チェックリスト

鍵認証は「秘密をネットワークに出さない」という構造そのものが安全性の源泉である。移行は次の順で進めると事故りにくい。

  • ssh-keygen -t ed25519パスフレーズ付き の鍵を作る
  • ssh-copy-id で公開鍵を設置し、別セッション で鍵ログインを確認する
  • ~/.ssh と秘密鍵の パーミッションを 700 / 600 に絞る
  • 鍵ログインが確実に動いてから PasswordAuthentication no にする

次に読むと理解が深まる記事: