SSH 公開鍵認証の仕組み|何と何を照らし合わせているのか
ssh 公開 鍵 認証 仕組みを調べる人がつまずくのは、手順そのものではありません。鍵を作って公開鍵を相手に登録すれば入れる、という手順は覚えられます。わからないまま残るのは、接続の瞬間に何と何が照らし合わされているのか、そして秘密鍵が送られないのなら何を根拠に本人だと判断しているのか、という部分です。この記事では、交換されているものを順に追いながら、鍵の種類が入れ替わってきた経緯と、実際に詰まる箇所までを並べます。
パスワードで入る場合と、鍵で入る場合の違い
パスワード認証は、あらかじめ決めた文字列を接続のたびに相手へ渡し、相手が保存している値と一致するかを見る方式です。SSHの通信自体は暗号化されているため、パスワードが平文のまま回線を流れるわけではありません。それでも構造上の弱点が2つ残ります。
1つは、正解の文字列が相手側にも存在することです。相手のサーバが持っている情報が漏れた場合、そこから元のパスワードへ迫られる可能性があります。もう1つは、試行の回数に制限がなければ機械的に総当たりできることです。インターネットに口を開けたサーバのログには、辞書に載っている利用者名とパスワードの組み合わせで入ろうとする試行が、放置しておくだけで大量に記録されます。
公開鍵認証は、この2つを構造で外します。相手側に置くのは公開鍵だけで、そこから秘密鍵を求めることが計算量の面で困難です。そして接続のたびに渡すものは固定の文字列ではなく、そのときだけ有効な署名です。試行を繰り返しても、正解に近づくという性質がありません。パスワードを廃してこの方式だけを許す設定にすると、総当たりの試行そのものが成立しなくなります。
鍵のペアが持っている2つの性質
公開鍵と秘密鍵は、同じ計算の中から一緒に生まれる2つの値です。数学的な関係で結ばれていて、片方から片方を導けない向きがあります。この非対称性から、2つの使い道が出てきます。
- 公開鍵で包んだものは、対応する秘密鍵でしか開けない。暗号化の用途
- 秘密鍵で作った署名は、対応する公開鍵で検証できる。認証の用途
SSHの公開鍵認証で使っているのは2つ目のほうです。サーバはクライアントから受け取った署名を公開鍵で検証し、検証が通ればその秘密鍵を持っている相手だと判断します。1つ目の暗号化の性質は、通信そのものの秘匿には別の仕組みが使われるため、認証の場面では出てきません。
署名で確かめられるのは、あくまで「対応する秘密鍵を持っている」という一点だけです。その鍵を持っているのが本来の持ち主なのか、鍵のファイルを持ち出した第三者なのかは、この仕組みでは区別できません。パスフレーズを付ける意味はここにあり、ファイルを手に入れただけでは署名を作れない状態を1枚重ねています。
この区別を押さえていないと、「公開鍵で暗号化して送っているのだろう」という誤った像ができます。実際に送られているのは署名であり、署名の元になっているデータには、その接続に固有の値が含まれています。だから同じ署名を録っておいて次の接続で使い回すことができません。
接続のときに交換されているものを順に追う
実際の流れは次の順に進みます。
1つ目に、暗号の方式をどれにするかを双方で決め、鍵交換の手順を踏んで、この接続だけで使う共通の鍵を作ります。この時点では、まだ利用者が誰かという話は始まっていません。ここで作った共通の鍵で、以降のやり取りは暗号化されます。
2つ目に、サーバが自分のホスト鍵で署名を返し、クライアントは手元の known_hosts に記録された公開鍵と照らし合わせます。初回の接続で指紋を確認するかと尋ねられるのはこの段階です。相手が入れ替わっていないかを先に確かめる工程で、利用者の認証とは向きが逆になります。
3つ目に、クライアントが「この公開鍵で入りたい」と鍵を指定して問い合わせます。サーバは受け取った公開鍵が authorized_keys に載っているかを調べ、載っていれば署名を要求します。載っていなければ次の鍵を試すか、認証方法を切り替えます。
4つ目に、クライアントが秘密鍵を使って署名を作ります。署名の対象には、この接続を識別する値と、利用者名と、使う公開鍵の情報が含まれます。秘密鍵にパスフレーズが付いている場合、この署名を作る手前で解錠が必要になります。
5つ目に、サーバが受け取った署名を公開鍵で検証します。通れば認証が成立し、シェルが起動します。
この順番から読み取れることが1つあります。鍵が合わないときのエラーが「公開鍵が見つからない」ではなく単なる認証の失敗として返ってくるのは、3つ目と5つ目のどちらで落ちたのかを外から区別させない設計になっているためです。
秘密鍵が送られない、が意味すること
この方式の要点を1文で言い表している説明があります。
公開鍵認証のポイントは、パスワード認証とは違って、認証に必要な秘密情報(この場合は秘密鍵)そのものはネットワーク上に送出されないという点です。また認証に使われる署名は一時的なものであり、再利用はできないため、署名そのものを盗んでも意味がありません。 出典: clouddirect.jp.fujitsu.com
送出されないという性質から、運用上の結論が2つ出てきます。第1に、接続先のサーバが乗っ取られていても、そこから秘密鍵は取れません。公開鍵しか置いていないためです。第2に、逆に守るべき対象は手元の端末に絞られます。秘密鍵のファイルが読み取られれば、その鍵で入れる先すべてに入られます。
だから対策の置き場所もはっきりします。サーバ側で頑張ることではなく、手元の秘密鍵にパスフレーズを付けること、端末ごとに鍵を分けること、鍵を配布や共有の対象にしないことです。鍵のファイルを複数人で共有すると、誰が入ったのかをログから区別できなくなり、1人が離任したときに全員の鍵を作り直す作業が発生します。
鍵の種類が入れ替わってきた経緯
同じ公開鍵認証でも、中で使う計算の種類は入れ替わってきました。古い手順書がそのまま使えない理由はここにあります。
| 変更 | 導入されたバージョン |
|---|---|
| RSA/SHA-256とSHA-512の署名に対応 | OpenSSH 7.2 |
| SHA-1を使うRSA署名を既定で無効化 | OpenSSH 8.8(2021年9月26日) |
| ssh-keygenが既定でEd25519の鍵を作る | OpenSSH 9.5 |
| DSAの対応を完全に削除 | OpenSSH 10.0(2025年4月9日) |
SHA-1を使うRSA署名が無効になった変更は、RSAの鍵そのものを捨てる話ではありません。同じRSAの鍵で、より新しい署名の方式を使えるためです。既定で無効になったのは古い署名の方式だけです。それでも、長く更新されていない接続先へ入れなくなる場合があり、その場合は接続元の設定で古い方式を明示的に許す形になります。
現在のmacOSに入っているものを見ると、macOS 27ではOpenSSH 10.3p1が使われています。鍵の種類を指定せずに ssh-keygen を実行すると、Ed25519の鍵ができます。Ed25519の公開鍵は短く、authorized_keys に貼ったときに1行に収まるため、扱いやすさの面でも扱う側の負担が小さくなっています。
鍵を作って置くまでの手順
作る側と置く側で、やることが分かれます。
ssh-keygen -t ed25519 -C "macbook-2026"
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
1行目で鍵のペアができます。パスフレーズを尋ねられるので、空にせず設定します。コメントには、どの端末の鍵かがわかる文字列を入れておきます。サーバ側の authorized_keys を数年後に見たときに、どれが今も使われている鍵なのかを判別する手がかりになります。
2行目で公開鍵を接続先へ登録します。この作業は、パスワード認証がまだ有効なうちに済ませる必要があります。鍵の登録を終えてから、サーバ側でパスワード認証を無効にする、という順序になります。順序を逆にすると自分が入れなくなります。
新しく環境を用意する場面では、この一連を初日にまとめてやることになります。
こないだ新しく開発環境セットアップしてて「サーバーにSSH接続できるようにするので公開鍵お願いします」と言われました。 出典: zenn.dev
このやり取りで渡すのは、末尾が .pub のファイルの中身だけです。秘密鍵のほうを渡すよう求められた場合、その手順そのものが誤っています。
入れないときに疑う箇所は決まっている
設定を見直す前に、権限を確認したほうが早く終わります。sshdは、鍵の置き場所の権限が緩いときに、その鍵を無視します。第三者が書き込める場所に置かれた authorized_keys は信用できないという判断です。
- ホームディレクトリは、本人以外が書き込めない状態にする
~/.sshディレクトリは本人だけがアクセスできる権限にする~/.ssh/authorized_keysは本人だけが読み書きできる権限にする- 手元の秘密鍵も同様に、本人だけが読める権限にする
次に疑うのは、そもそも公開鍵を正しい利用者のホームディレクトリに置けているかです。rootで作業しているときに、接続に使う利用者ではなくrootの側へ登録してしまう取り違えが起きます。サーバ側のログを見れば、どの利用者名で来てどこを探したかが記録されています。
理解を進めるうえでの落とし穴について、次のような書き出しをしている記録があります。
SSH って公開鍵認証とパスワード認証があって、通信は共通鍵で秘匿化して~みたいな感じのあっさりとした理解が現状ですが、実際に SSH を叩いたり、公開鍵の中身をみたりしてみると、rs とか ed25519 とかよくわからないものがいっぱい。 出典: qiita.com
概念の層と、ファイルの中身の層と、設定ファイルの層が混ざると、この状態になります。順番としては、交換されているものを先に押さえ、次に鍵の種類を1つに決め、最後に設定ファイルの書き方へ進むと、迷いが減ります。
鍵が増えたあとに決めることが本題になる
仕組みを理解したあとで実務に残るのは、鍵の本数が増えたときの管理です。接続先が5つを超えると、どの鍵がどこに登録されているのかが手元からは見えなくなります。鍵の一覧はサーバ側に分散して置かれていて、手元にはファイルだけがあるためです。
決めておくと崩れにくいのは3つです。端末ごとに鍵を1本にすること、鍵のコメントに端末名を入れること、そして接続先の設定を1つのファイルに集めることです。この3つが揃っていれば、端末を買い替えたときに外す鍵と足す鍵がすぐ決まります。
ターミナルと設定ファイルとフォルダを別々の窓で開いていると、この確認のたびに窓を移る操作が入ります。手元で扱うものを1つの窓に集めておく考え方はできることに整理されていて、他のファイル管理の道具との違いは他のファイル管理との比較で確認できます。出先の端末から接続の状態を確かめる場面についてはiPhone・iPadから続きをにまとめられています。
次に手を付ける順番としては、まず手元の秘密鍵にパスフレーズが付いているかを確かめ、次に端末ごとに鍵が分かれているかを確かめ、それが済んでから設定ファイルの整理へ進むのが無理のない形です。導入にかかる費用の目安は料金にあり、判断に迷う点はよくある質問に並んでいます。
よくある質問
公開鍵認証はパスワード認証より安全と言えるのはなぜですか?
正解になる秘密情報が相手側に存在せず、回線にも流れないためです。サーバに置くのは公開鍵だけで、そこから秘密鍵を求めることは計算量の面で困難です。接続のたびに渡すのは固定の文字列ではなくその場限りの署名なので、盗んでも次の接続には使えず、総当たりで正解に近づく性質もありません。
秘密鍵を送っていないのに、どうやって本人だと判断しているのですか?
クライアントが秘密鍵で署名を作り、サーバがその署名を公開鍵で検証しています。署名の対象にはその接続を識別する値が含まれるため、同じ署名を別の接続で使い回せません。検証が通ることが、対応する秘密鍵を持っている証拠になります。送られているのは署名であって、鍵そのものではありません。
鍵を作るときの種類は何を選べばよいですか?
指定せずに作れば問題ありません。OpenSSH 9.5以降、ssh-keygenは既定でEd25519の鍵を作ります。macOS 27にはOpenSSH 10.3p1が入っています。公開鍵が短く1行に収まるため扱いやすく、接続先が相当古いものでない限り、古い手順書に従ってRSAで作り直す必要はありません。
鍵を登録したのに入れません。最初に何を見ればよいですか?
権限を確認してください。sshdはホームディレクトリやauthorized_keysの権限が緩いと、その鍵を無視します。本人以外が書き込める状態になっていないかを見ます。次に、公開鍵を接続に使う利用者のホームディレクトリに置けているかを確認します。rootで作業していて置き場所を取り違える例が多いです。