【おうどんの基礎講座】公開鍵と秘密鍵ってなに? SSH鍵はどっちを渡す? 作り方・authorized_keysへの登録・指紋の確認方法

【おうどんの基礎講座】公開鍵と秘密鍵ってなに? SSH鍵はどっちを渡す? 作り方・authorized_keysへの登録・指紋の確認方法

こんにちは、おうどんです🍜

新人さん「サーバーに鍵でログインできるように、鍵を作って送っておきました!」

おうどん「お、えらい。どっちを送ったの?」

新人さん「両方です。念のため、秘密鍵も」

おうどん「……念のため、の使い方が逆」

(会話は説明用の架空の場面です)

うどん屋さんで言うと、常連さんの登録に来て、自分の筆跡見本と一緒に、自分の右手も置いて帰ったようなものです。

大将「右手はけっこうです」

……そりゃそうです。

SSH(ネットワーク越しにサーバーへ安全にログインするための仕組み)で鍵を使うとき、必ず出てくるのが公開鍵と秘密鍵。
名前は聞いたことがあるけど、どっちを誰に渡すのか、なぜ鍵でログインできるのかは、意外とあいまいなままになりがちです。

今回は基礎講座として、公開鍵と秘密鍵の役割を、Git for Windows に入っている ssh-keygen を実際に動かしながら整理します。

最初に、初心者向けのチェックリストです。

  • 相手(サーバー)に渡すのは、末尾が .pub のファイル(公開鍵)だけ
  • .pub が付いていないほう(秘密鍵)は、誰にも送らない。チャットにも貼らない
  • 同じ鍵かどうかは、ssh-keygen -l -f ファイル名 の指紋で確かめる

前回の応用編「SSHでRSA鍵なのに接続できない原因と対処」は、この記事の知識を前提にしています。実践編としてあわせてどうぞ。

目次

公開鍵は「筆跡見本」、秘密鍵は「自分の手」

先に結論を言うと、秘密鍵はサインを書くための手、公開鍵はそのサインが本物か照らし合わせるための見本です。

まず用語です。

  • 鍵ペア:公開鍵と秘密鍵の2つで1組。片方だけ作ることはなく、必ずセットで生まれる
  • 秘密鍵:自分だけが持つほう。これを使って署名(「本人です」という証拠)を作る
  • 公開鍵:相手に渡すほう。署名が、対になる秘密鍵で作られたものかを確かめるのに使う
  • 署名:秘密鍵を使って、あるデータに対して作る「本人が書いた」証拠。紙のサインと同じ発想

ssh のマニュアルには、公開鍵認証の考え方が次のように書かれています。

  • 各ユーザーが、認証のための公開鍵と秘密鍵のペアを作る
  • サーバーは公開鍵を知っていて、秘密鍵はユーザーだけが知っている
  • クライアントは、秘密鍵を持っていることを証明する
  • ログインを許す公開鍵の一覧は、サーバー側の ~/.ssh/authorized_keys に書く

新人さん「じゃあ、秘密鍵を見せれば一番早く証明できますね」

おうどん「それは、サインの代わりに右手を切って提出するやつ」

……証明はできても、二度とサインできません。

見せるのは手ではなく、その手で書いたサイン。ここが公開鍵認証のいちばん大事なところです。

大将「常連さん、お名前を書いてください。見本と照らし合わせますので」

おうどん「(さらさら)」

大将「はい、本人ですね。手は見せなくて大丈夫です」

……手を見せずに本人だと分かる。これが鍵ペアのいいところなんです。

どっちを渡す? 「.pub」が付いているほうだけ

迷ったら、ファイル名の最後に .pub(public=公開)が付いているほうだけを渡す、と覚えておけば間違えません。

今回の検証環境(Git for Windows の OpenSSH_9.7p1、bash 5.2.26)で鍵ペアを作ってみます。

ssh -V
ssh-keygen -q -N "" -C udon-key -f ./udon_key
ls -1
OpenSSH_9.7p1, OpenSSL 3.2.1 30 Jan 2024
udon_key
udon_key.pub

(1行目が ssh -V、2〜3行目が ls -1 の結果です。ssh-keygen は -q で静かにしているので何も表示しません)

オプションの意味はこうです(ssh-keygen のマニュアルより)。

オプション意味
-f鍵のファイル名。公開鍵は同じ名前に .pub を付けたファイルになる
-Cコメント(どの鍵か見分けるためのメモ)
-Nパスフレーズ。"" は「なし」(今回は検証用なのでなし)
-q静かモード
-t鍵の種類。今回は付けていない

新人さん「-N "" って、パスフレーズが空っぽってことですか」

おうどん「検証用の鍵だからね。本番の鍵で真似しない」

……空っぽの金庫は、金庫の形をした箱です。

-t を付けなかったので、何の鍵ができたか見てみます。

cat udon_key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMtrLHW1uJUlZ7aGl7bW/114Lf7zFbewY66Hn/Rads+ udon-key

(鍵の中身は作るたびに変わります)

公開鍵ファイルは1行で、スペース区切りの3つの部分でできています。

部分中身
ssh-ed25519鍵の種類
AAAAC3Nza...鍵の本体(Base64 という、データを英数字と記号で表す書き方)
udon-keyコメント(-C で付けたメモ)

今回の検証環境では、-t なしで Ed25519 の鍵ができました。ssh-keygen のマニュアル(OpenBSD 版の最新)にも、引数なしで実行すると Ed25519 の鍵を作る、と書かれています。古い版では既定が違うことがあるので、種類を決めたいときは -t ed25519 のように明示しましょう。

新人さん「Ed25519 って、なんだか型番みたいですね」

おうどん「うどんで言えば、麺の種類の名前」

新人さん「じゃあ RSA は?」

おうどん「……昔からある太麺、くらいにしておこう」

……雑なたとえは、ここで止めておきます。鍵の種類の違いは後半の上級者向けで少しだけ触れます。

次に、秘密鍵のほうの最初と最後の行を見ます。

head -n 1 udon_key
tail -n 1 udon_key
-----BEGIN OPENSSH PRIVATE KEY-----
-----END OPENSSH PRIVATE KEY-----

PRIVATE KEY(秘密鍵)と、自分で名乗っています。
送る前にファイルを開いてこの行が見えたら、それは送ってはいけないほうです。

新人さん「ファイルが自分で『秘密です』って書いてあるの、親切ですね」

おうどん「封筒に『極秘』って大きく書いてあるのと同じでね」

……親切だけど、見つかったら一番目立つ。だから置き場所と権限が大事なんです(後半で触れます)。

鍵でログインできる仕組み:サインを見せて、手は見せない

ひとことで済ませると怒られそうなので、大将のお店で説明します。
サーバーはお題を出し、クライアントはそのお題に秘密鍵でサインして返す。サーバーは公開鍵(見本)で照らし合わせる。これだけです。

SSH の公開鍵認証を定めた RFC 4252(RFC はインターネットの技術の決まりごとを書いた文書)の7章によると、

  • クライアントは、ユーザー名・公開鍵・署名などを入れた認証のリクエストを送る
  • 署名は、秘密鍵を持っていることを示すためのもの
  • サーバーは、その公開鍵がそのユーザーの認証に使ってよいものか、署名が正しいかを確かめ、両方満たせば成功にする

と書かれています。送られるものとして挙がっているのは、公開鍵と署名です。秘密鍵そのものは、リストに入っていません。

ログインそのものは今回の検証環境では試せないので、同じ「秘密鍵で署名して、公開鍵で確かめる」流れを、ssh-keygen のファイル署名機能(-Y sign と -Y verify)で体験してみます。

(-Y sign はファイルに署名する機能で、SSH のログインそのものではありません。秘密鍵で署名し、公開鍵で確かめる、という考え方が同じなので、体験用に使っています)

まず、注文書に秘密鍵でサインします。

printf 'うどん3玉、注文します\n' > order.txt
ssh-keygen -Y sign -f udon_key -n file order.txt
Signing file order.txt
Write signature to order.txt.sig

-n file は、署名の用途(名前空間)を表すラベルです。ssh-keygen のマニュアルによると、別の用途に署名が使い回されるのを防ぐためのものです。

新人さん「名前空間って、宇宙の話ですか」

おうどん「伝票の『用途』欄。出前用か、店内用か」

……宇宙までは、出前していません。

次に、確かめる側の準備。「この人の見本はこれ」という一覧(allowed_signers)を作ります。中身は「名前 + 公開鍵」です。

echo "oudon@example $(cut -d' ' -f1,2 udon_key.pub)" > allowed_signers
cat allowed_signers
oudon@example ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMtrLHW1uJUlZ7aGl7bW/114Lf7zFbewY66Hn/Rads+

公開鍵で確かめます。

ssh-keygen -Y verify -f allowed_signers -I oudon@example -n file -s order.txt.sig < order.txt
Good "file" signature for oudon@example with ED25519 key SHA256:HLBgYeWydciiUrIsrKn1WntRLQvt2mj4GXEMUj2fY2E

(終了コードは 0)

Good、本物です。

では、注文書を書き換えてみます。3玉を30玉に。

printf 'うどん30玉、注文します\n' > order_fake.txt
ssh-keygen -Y verify -f allowed_signers -I oudon@example -n file -s order.txt.sig < order_fake.txt
Signature verification failed: incorrect signature
Could not verify signature.

(終了コードは 255。ここまでのコマンドは、今回の検証環境で bash スクリプトの中から順に実行し、標準出力と標準エラーをまとめて記録しました)

1文字(0)を足しただけで、サインが合わなくなりました。

新人さん「30玉なら、大将も喜ぶと思ったんですけど」

大将「喜ぶ前に、お代を払う人が見つからない」

……サインの付いていない30玉は、誰も払ってくれません。

新人さん「じゃあ、サインごと30玉用に書き直せば?」

おうどん「それができるのは、秘密鍵を持っている人だけ」

……だから、秘密鍵は自分の手から離しちゃいけないんです。

🔰 ここまで読めば今日から困らない

  • 鍵ペアは、公開鍵(.pub、相手に渡す見本)と秘密鍵(自分だけの手)の2つで1組
  • サーバーに渡すのは .pub だけ。中身が -----BEGIN OPENSSH PRIVATE KEY----- で始まるファイルは送らない
  • ログインのとき、秘密鍵そのものは送られない。秘密鍵で作った署名を、サーバーが公開鍵で確かめる
  • 鍵の種類を決めたいときは ssh-keygen -t ed25519 -C "メモ" のように -t を明示する

新人さん「4行なら覚えられます。秘密鍵のファイルにメモしておきますね」

おうどん「メモの置き場所に、一番大事な金庫を選ばない」

……開けるたびに中身が見えて危ないです。

大将「その4行、見本帳の表紙に貼っておきますね」

新人さん「大将のほうが、先に覚えそう」

……お客さんより詳しいうどん屋。

ここから先は中級者向け。読み飛ばしてもOKです。

サーバーに登録する:authorized_keysの書き方と権限

公開鍵は、サーバーのログインしたいユーザーの ~/.ssh/authorized_keys に1行ずつ書きます。大将の「常連さんの見本帳」です。

sshd のマニュアルによると、

  • AuthorizedKeysFile を指定していなければ、既定は ~/.ssh/authorized_keys(と ~/.ssh/authorized_keys2)
  • 1行に1つの鍵。空行と # で始まる行はコメントとして無視される
  • 1行は、オプション・鍵の種類・Base64 の鍵本体・コメントをスペースで区切ったもの(オプションは省略できる)
  • コメントは何にも使われない(どの鍵か見分ける目印になるだけ)

.pub の1行をそのまま追記すれば、形式どおりになります。

サーバーにすでにパスワードなどでログインできる状態なら、手元から次のように登録できます(opsuser と 192.0.2.10 は説明用の例です)。

cat ~/.ssh/id_ed25519.pub | ssh opsuser@192.0.2.10 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

(未実行の例です。今回の検証環境には接続先のサーバーがないため、実際の登録は試していません)

ポイントは >>(追記)。> にすると、ファイルが上書きされて、ほかの人や別の端末の鍵が消えます。

新人さん「> と >>、1文字しか違わないのに」

おうどん「見本帳に1枚足すのと、見本帳を燃やして1枚だけ置くのの違い」

……常連さんが全員、初めましてになります。

権限もよくハマるところです。sshd のマニュアルには、authorized_keys は本人だけが読み書きでき、ほかの人からはアクセスできない権限がすすめられていること、そして このファイル・~/.ssh ディレクトリ・ホームディレクトリのどれかがほかのユーザーから書き込める状態だと、StrictModes が no でない限り sshd はこのファイルを使わない、と書かれています。

対象例理由
~/.sshchmod 700 ~/.sshほかのユーザーが書き込めないようにする
~/.ssh/authorized_keyschmod 600 ~/.ssh/authorized_keys本人だけ読み書き
ホームディレクトリほかのユーザーが書き込めないこと書き込めると authorized_keys が使われない

(上の chmod は、マニュアルの条件を満たす設定の一例です)

新人さん「鍵を登録したのに、パスワードを聞かれます」

おうどん「見本帳の棚に、誰でも書き込めるようになってない?」

……他人が見本を差し替えられる棚の見本は、大将も信用しません。

手元の秘密鍵にも同じ考え方があります。ssh のマニュアルには、~/.ssh/id_ed25519 などの秘密鍵ファイルは本人だけが読めるようにすべきで、ほかの人がアクセスできる状態だと ssh はその秘密鍵ファイルを単に無視する、と書かれています。

指紋で「同じ鍵か」を確かめる

鍵の本体は長いので、目で見比べるのは大変です。そこで使うのが指紋(フィンガープリント。鍵の中身から計算した短い要約)です。

ssh-keygen -l -f udon_key.pub
ssh-keygen -l -f udon_key
256 SHA256:HLBgYeWydciiUrIsrKn1WntRLQvt2mj4GXEMUj2fY2E udon-key (ED25519)
256 SHA256:HLBgYeWydciiUrIsrKn1WntRLQvt2mj4GXEMUj2fY2E udon-key (ED25519)

(1行目が公開鍵、2行目が秘密鍵のファイルを指定した結果です)

公開鍵のファイルを指定しても、秘密鍵のファイルを指定しても、同じ指紋が出ました。同じペアだからです。
並びは、鍵の大きさ(ビット数)・指紋・コメント・鍵の種類です。

使いどころは、たとえばこんなときです。

  • サーバーの authorized_keys に並んだ鍵のうち、どれが自分の鍵か調べる(今回の検証では、公開鍵を2行並べたファイルに ssh-keygen -l -f を使うと、1行ずつ指紋が出ました)
  • 手元に id_ed25519 が何本もあって、どれを登録したか分からなくなった

新人さん「指紋が同じなら、同じ鍵。じゃあ、うどんの指紋も……」

おうどん「麺には指紋がない。粉のロット番号ならある」

……ロット番号で常連さんは見分けられません。

指紋の表し方は、既定が SHA256(ssh-keygen のマニュアルより)。古いシステムや資料では MD5 の形(コロン区切り)で書かれていることがあるので、そのときは -E md5 で合わせます。

ssh-keygen -l -E md5 -f udon_key.pub
256 MD5:c0:d5:47:4e:11:a7:a6:40:00:21:7e:92:68:bd:f3:2b udon-key (ED25519)

同じ鍵でも、表し方が違うと見た目はまるで別物です。
見比べるときは、SHA256 同士、MD5 同士で。

新人さん「SHA256 と MD5 で一致しないから、別の鍵だと思ってました」

おうどん「同じ人の、身長を cm と尺で測って『違う人だ』って言ってるやつ」

……単位をそろえてから、別人かどうかを決めましょう。

秘密鍵にパスフレーズを付ける・変える

パスフレーズは、秘密鍵ファイルそのものにかける鍵です。ファイルが盗まれても、パスフレーズが分からなければ使えないようにするためのものです。

ここまでの検証用の鍵はパスフレーズなし(-N "")でした。コピーした鍵にパスフレーズを付けてみます(-P は今のパスフレーズ、-N は新しいパスフレーズ)。

cp udon_key pp_key
ssh-keygen -p -P "" -N "kitsune-udon" -f pp_key
Key has comment 'udon-key'
Your identification has been saved with the new passphrase.

間違ったパスフレーズで、秘密鍵から公開鍵を取り出そうとすると(-y は秘密鍵を読んで公開鍵を表示するオプション)、

ssh-keygen -y -P "tanuki-soba" -f pp_key
Load key "pp_key": incorrect passphrase supplied to decrypt private key

(終了コードは 255)

断られました。正しいパスフレーズなら、公開鍵が出てきます。

ssh-keygen -y -P "kitsune-udon" -f pp_key
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMtrLHW1uJUlZ7aGl7bW/114Lf7zFbewY66Hn/Rads+ udon-key

新人さん「きつねとたぬき、間違えただけなのに」

pp_key「おあげが入っていないので、開けられません」

……うどんとそばの違いまで厳しい。

注意点が2つあります。

  • 上の例はパスフレーズをコマンドに直接書いていますが、これは検証のためです。実際の作業では ssh-keygen -p -f ~/.ssh/id_ed25519 とだけ打って、聞かれたときに入力しましょう(コマンドに書くと、履歴に残ることがあります)
  • ssh-keygen のマニュアルには、忘れたパスフレーズを取り戻す方法はない、と書かれています。忘れたら、新しい鍵を作り、公開鍵を登録し直すことになります

新人さん「じゃあ、パスフレーズは公開鍵のファイルにメモしておけば……」

おうどん「公開鍵は、配って歩くほうだよ」

……メモが全サーバーに配られます。

毎回入力するのが面倒なら、ssh-agent(秘密鍵を覚えておいてくれる常駐プログラム)を使う方法があります。ssh のマニュアルにも、公開鍵認証のいちばん便利な使い方は認証エージェントを使うことかもしれない、とあります。

よくある勘違いチェックリスト

最後に、中級者がやりがちな勘違いを並べておきます。

よくある勘違い実際
鍵ペアは片方を失くしても作り直せる公開鍵は秘密鍵から取り出せる(ssh-keygen -y)。秘密鍵は公開鍵からは作れない。秘密鍵を失くしたら作り直し
ログインのとき秘密鍵がサーバーに送られるRFC 4252 で送るとされているのは、公開鍵と署名など。秘密鍵そのものは入っていない
authorized_keys のコメントで鍵を区別しているsshd はコメントを何にも使わない。区別したいなら指紋で
鍵を登録したのにパスワードを聞かれる=鍵が壊れたまず ~/.ssh・authorized_keys・ホームの権限を疑う
指紋が違う=別の鍵SHA256 と MD5 の表し方の違いかも。そろえてから比べる
1つの秘密鍵をみんなで共有すればラクどの人・どの端末の鍵か区別できなくなり、1人やめるときも全員の鍵を替えることになる。1人(1端末)1ペアにして、公開鍵を必要なサーバーに登録する

新人さん「6つ全部やったことがあります」

おうどん「全部やった人は、もう中級者だよ」

……失敗の数だけ、見本帳はきれいになります。

大将「お客さん、見本帳に同じ名前が12人いるんですが」

おうどん「全部、別の端末の私です」

……コメントに端末名を書いておくと、大将も助かります。

ここから先は上級者向け。読み飛ばしてもOKです。

秘密鍵ファイルの中には、公開鍵も入っている

パスフレーズの章で、ちょっと気になることがありました。
パスフレーズ付きの秘密鍵でも、指紋は出るのか。.pub を消して、秘密鍵だけで試してみます。

rm -f pp_key.pub
ssh-keygen -l -f pp_key
256 SHA256:HLBgYeWydciiUrIsrKn1WntRLQvt2mj4GXEMUj2fY2E no comment (ED25519)

(pp_key.pub は、検証のために udon_key.pub をコピーして置いていたものです。それを消してから実行しました)

パスフレーズを聞かれずに、指紋が出ました。しかも、コメントは no comment。

理由は、OpenSSH の秘密鍵ファイルの形式を書いた PROTOCOL.key にあります。この形式は、

  • 先頭の目印(openssh-key-v1)、暗号の方式、鍵から暗号の鍵を作る方式(KDF)とその設定
  • 鍵の数
  • 公開鍵(暗号化されていない)
  • 暗号化された秘密鍵の一覧(秘密鍵とコメントの組)

の順に並んでいます。公開鍵は暗号化されずに入っていて、コメントは秘密鍵と一緒に暗号化される側にいる。だから、パスフレーズなしで指紋は計算できても、コメントは読めなかったわけです。

pp_key「顔写真は表に貼ってあります。名前は金庫の中です」

大将「名札は、表に付けておいてほしかった」

……「no comment」が、記者会見みたいになっている。

秘密鍵ファイルからは、公開鍵を取り出すこともできます(ssh-keygen -y)。今回の検証では、パスフレーズなしの 3072 ビットの RSA 鍵でも取り出せました。ただし、パスフレーズの章で見たとおり、パスフレーズ付きの鍵では -y は正しいパスフレーズを求めました。-l とは扱いが違うので、指紋を見たいだけなら -l が手軽です。

ssh-keygen -q -t rsa -b 3072 -N "" -C rsa-key -f ./rsa_key
ssh-keygen -y -f rsa_key | cut -c1-48
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDJbnkI7SUd

(-y の出力は1行が長いので、cut で先頭48文字だけ表示しています)

逆向き(公開鍵だけで署名する)は、もちろんできません。公開鍵 udon_key.pub と注文書だけを入れたフォルダで試しました。

ssh-keygen -Y sign -f udon_key.pub -n file order.txt
No private key found for public key "udon_key.pub"

(ssh-agent を使わない状態で実行。終了コードは 255 でした)

ssh-keygen のマニュアルでは、-Y sign の -f には秘密鍵か、秘密鍵の半分が ssh-agent にある公開鍵を指定する、とされています。なお、今回の検証では、同じフォルダに秘密鍵 udon_key も置いてある状態で -f udon_key.pub を指定すると、署名ができました。中でどう秘密鍵を探しているかは確かめていないので、ここでは「公開鍵だけでは署名できなかった」という結果にとどめます。

新人さん「見本だけ持っていっても、サインは書けないんですね」

おうどん「なぞり書きで通るなら、見本帳の意味がない」

……なぞり書きでも、本人の手じゃないと通りません。

署名は「そのセッション専用」:RFC 4252の中身

もう一歩だけ、ログインの中身に入ります。
サーバーへのサインは、その接続ごとのお題に対して書く。だから、サインはその接続に結びつく、という作りです。

RFC 4252 の7章では、署名の対象は次のものだと決められています。

  • セッション識別子(その接続ごとに決まる値)
  • 認証のリクエストの中身(ユーザー名、サービス名、publickey という方式名、公開鍵の方式名、公開鍵など)

セッション識別子は接続ごとに決まるので、署名もその接続に結びつきます。

悪い人「昨日のサイン、写真に撮っておきました」

大将「それは昨日のお題へのサインですね。今日のお題は違います」

……合言葉が毎日変わる店で、昨日の合言葉は通じません。

もう1つ、RFC 4252 には署名なしの問い合わせも書かれています。クライアントは、署名の欄を空にして「この公開鍵なら受け付けてもらえますか」と先に聞ける。サーバーは、受け付けるなら SSH_MSG_USERAUTH_PK_OK、だめなら SSH_MSG_USERAUTH_FAILURE で返します。RFC には、パスフレーズの入力や署名の計算という手間をかける前に、鍵が使えるか確かめられる、という目的も書かれています。問い合わせを飛ばして、いきなり署名を送ってもかまいません。

おうどん「大将、この見本、見本帳に載ってます?」

大将「載ってますよ。じゃあ、サインをどうぞ」

……載っていない人に、わざわざ書かせない。お互いにやさしい手順です。

そして、サーバー側の判定は2つです。

  1. その公開鍵が、そのユーザーの認証に使ってよい鍵か(OpenSSH の sshd なら、主に authorized_keys に載っているか)
  2. 署名が正しいか

両方満たせば、この方式は成功。RFC には、サーバーがさらに別の認証を求めてもよい、とも書かれています(多要素認証のように)。

ここで、さっきの「他人の鍵でサインした注文書」の検証結果を見てください。今回の検証では、別の鍵ペア other_key で同じ内容の注文書に署名し、2つの方法で確かめました。

ssh-keygen -Y verify -f allowed_signers -I oudon@example -n file -s order2.txt.sig < order2.txt
ssh-keygen -Y check-novalidate -n file -s order2.txt.sig < order2.txt
Could not verify signature.
Good "file" signature with ED25519 key SHA256:gZzmzJffo2mGwMEamsYjZdbkphylu72N7kGk6AW+Td4

(1行目が1つ目のコマンド(終了コード 255)、2行目が2つ目のコマンド(終了コード 0)の結果です)

check-novalidate は、ssh-keygen のマニュアルによると、署名の形が正しいかだけを確かめ、署名した人が許可されているかは確かめないモードです。
つまり、署名そのものは正しい(Good)けれど、見本帳(allowed_signers)に載っていない人のサインだった。

他人「サインは、ちゃんと書けてますよね?」

大将「上手です。でも、見本帳に載っていない方です」

……字がきれいでも、常連さんではない。

SSH のログインも同じ構造で、サーバーは「署名が正しいか」と「その鍵が許可されているか」の両方を見ます。authorized_keys は、その「許可されているか」の部分を担う見本帳なんです。

ついでに、名前空間(-n)を変えて確かめた結果も載せておきます。

ssh-keygen -Y verify -f allowed_signers -I oudon@example -n email -s order.txt.sig < order.txt
Couldn't verify signature: namespace does not match
Could not verify signature.

(終了コードは 255)

file 用に書いたサインは、email 用としては通りません。用途ごとにお題の欄を分けておく、という仕組みです。

Ed25519とRSA:大きさの違い

最後に、鍵の種類の話を少しだけ。
今回の検証環境で、Ed25519 の鍵と、3072 ビットの RSA の鍵を並べてみました。

awk '{print $1, length($2)}' udon_key.pub rsa_key.pub
wc -c udon_key rsa_key
ssh-ed25519 68
ssh-rsa 544
 399 udon_key
2590 rsa_key
2989 total

(1〜2行目が公開鍵の本体(Base64 部分)の文字数、3〜5行目が秘密鍵ファイルのバイト数です)

公開鍵の本体は、Ed25519 が 68 文字、RSA(3072 ビット)が 544 文字。8倍くらい違います。
authorized_keys に並べたとき、チャットで共有したとき、短いほうが見やすいのは確かです。

RSA「長いのは、歴史の重みです」

Ed25519「短いのは、ただの効率です」

……どっちも正しいことを言っているのに、なぜかケンカに聞こえる。

どちらを選ぶかは、接続先が対応しているかで決まることもあります。古い機器が Ed25519 に対応していないなら RSA を使う、という判断もありえます。
迷ったら、まず接続先の対応を確認し、対応していれば -t ed25519 を明示して作る、が手堅い順番です。

新人さん「じゃあ両方作って、両方登録しておけば……」

おうどん「見本帳に、同じ人の見本が2枚。管理する鍵が2本に増える」

……使わない鍵は、見本帳から外すところまでが鍵の管理です。

まとめ:見本は配る、手は離さない

冒頭の新人さんは、秘密鍵も念のため送っていました。

新人さん「送っちゃった秘密鍵、どうしましょう」

おうどん「その鍵ペアはもう使わない。新しく作って、新しい公開鍵を登録し直して、古い公開鍵は authorized_keys から外す」

新人さん「右手、生え変わるんですね」

おうどん「鍵はね。本物の右手は大事にして」

……鍵の世界は、手を作り直せるのが救いです。

今回のポイントを並べると、

  • 鍵ペアは、公開鍵(.pub)と秘密鍵の2つで1組。渡すのは .pub だけ
  • ログインでは、秘密鍵で書いた署名を、サーバーが公開鍵で確かめる。秘密鍵そのものは送らない
  • サインは、その接続のお題(セッション識別子)に対して書くので、その接続に結びつく
  • サーバーは「署名が正しいか」と「その鍵が authorized_keys に載っているか」の両方を見る
  • authorized_keys は >> で追記。~/.ssh・authorized_keys・ホームの権限がゆるいと使われない
  • 同じ鍵かは指紋で確かめる。SHA256 と MD5 は表し方が違うだけ
  • 秘密鍵ファイルには公開鍵も暗号化されずに入っている。だからパスフレーズ付きでも指紋は出る。公開鍵だけでは署名できない
  • パスフレーズは忘れたら取り戻せない

新人さん「8行は、さすがに右手に書ききれません」

おうどん「書かなくていい。右手は鍵を守るので忙しい」

……右手、今日いちばんの働き者です。

公開鍵は見本として配り、秘密鍵は自分の手として離さない。

まずは自分のパソコンで ssh-keygen -l -f ~/.ssh/id_ed25519.pub(RSA なら id_rsa.pub)を1回だけ打って、自分の鍵の指紋を眺めてみてください。
自分の筆跡を知っておくと、見本帳の前で迷わずにすみます🍜

参考資料

  • ssh(1) — 公開鍵認証の考え方(ユーザーが鍵ペアを作る、サーバーは公開鍵を知り秘密鍵はユーザーだけが知る、クライアントは秘密鍵を持っていることを証明する)、authorized_keys、秘密鍵ファイルの権限と他人がアクセスできると無視されること、認証エージェント
  • sshd(8) — authorized_keys の既定の場所と1行の形式、コメントは使われないこと、推奨の権限、ファイル・~/.ssh・ホームが他人から書き込めると StrictModes で使われないこと
  • ssh-keygen(1) — 引数なしで Ed25519 を作ること、公開鍵は同じ名前に .pub を付けたファイル、-C・-f・-N・-p・-y・-l・-E(既定は SHA256)、-Y sign・-Y verify・-Y check-novalidate・-n、忘れたパスフレーズは取り戻せないこと(OpenBSD 版の最新のマニュアル)
  • RFC 4252:The Secure Shell (SSH) Authentication Protocol — 7章の公開鍵認証(送る項目、署名の対象にセッション識別子が入ること、署名なしの問い合わせと SSH_MSG_USERAUTH_PK_OK、サーバーの判定)
  • PROTOCOL.key(OpenSSH portable) — OpenSSH の秘密鍵ファイルの形式。公開鍵が暗号化されずに入り、秘密鍵とコメントが暗号化されること

確認日:2026-10-12。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

おうどん|癒しと創作をたのしむ雑食クリエイター
写経アプリやクレイセラピー、優しい和風デザインがすき。
ZARDと刀剣と文字に癒されて、今はアプリ作ってます。

コメント

コメントする

目次