はじめに
背景
SSHで出てくる「公開鍵」という用語、初めて触れる人は戸惑うかも知れませんので、まとめることにしました。
手順的なもの含め、いろいろ ( 面倒なので ) 押し込めましたが、概要だけでも押さえておくと、混乱が少ないのではないかと思います。
TL;DR;
- みんながSSHで「公開鍵」と言ってるのは、大抵のケースで「認証鍵」のこと
※それ以外に「ホスト鍵」もある - 認証鍵は、サーバにログインするユーザを識別するための手続き(ユーザ認証)で使うデータ
- 認証鍵の実体は、公開鍵暗号の1種である電子署名における、秘密鍵と公開鍵の鍵ペア
- ユーザは秘密鍵・公開鍵(両方)を使ってログインを試み、サーバは公開鍵を使ってユーザを識別する
※サーバに公開鍵を予め登録する必要がある - ちょうど、銀行印による押印を行員がお届け済みの印影と照らし合わせて、本人確認をするようなもの
※電子署名は現実での「印鑑」に相当する技術
細かい話題は色々ありますが、取り敢えず上記イメージだけ押さえて、必要に応じてこの記事に書いてあるような情報を仕入れると良いのではないかと思います。
SSHについておさらい
鍵の話をする前に、「SSHってなに?」か、軽くおさらいです。
SSHは暗号技術によって、なりすまし・盗聴・データ改ざんから保護された、クライアント・サーバ間の通信を通じて、主に3通りの用途を実現する方式(プロトコル)やアプリを指します。
その時に、( Webのような ) 匿名のアクセスは許されず、ユーザ名を指定して「ユーザ認証」( 指定されたユーザ本人であることの確認 )を受ける必要があります。
さて、その3通りの用途は次のようなものです。
- 遠隔ログイン
ネットワークに接続された機器を、あたかも手元で操作しているかのようにCUIで遠隔操作する用途。( 昔のrlogin,telnet相当 )
- 遠隔コマンド実行
ネットワークに接続された機器上で、指定したアプリを遠隔実行する用途。( 昔のrsh相当 )
特に有名なものとしては、sftp/scp のファイル転送、rsync でのデータ同期、gitのリモートレポジトリ同期など、クライアント側のアプリと遠隔起動したアプリとでSSH通信を経由して、データを遣り取りするような形態でも使用します。
- 通信のトンネル
ネットワークで接続された機器との間に仮想的な通信トンネルを生成し、2つのネットワーク ( クライアント側・サーバ側 ) の間で通信を行う用途。
SSHクライアント・サーバが、それぞれのネットワークで通信の代理人として振る舞い、2つのネットワークの仲介を行います ( ネットワークが分離されていても通信が可能になります )。
様々な形態がありますが、1例として次の図のように、隔離されているWebサーバへアクセスするようなことも可能です。
SSHの公開鍵
2種類の鍵の用途
SSHは公開鍵暗号、中でも「鍵交換」「電子署名」の2種類、それから共通鍵を使う技術 ( 共通鍵暗号、HMACやAEAD ) を使った、SSL/TLSに類似のハイブリッド暗号技術です。
※公開鍵暗号の「暗号化」はほぼ使うことはありません。
通信の暗号化に用いる鍵はアプリが自動生成するため、ユーザが特に気にする必要はありませんが、電子署名の鍵は、用途に応じて2種類と知っておく必要があります。
いずれも ( 公開鍵暗号の1種なので ) 公開鍵・秘密鍵の鍵ペアで使います。
その2種類の用途は次の通りです。が、一般にみんなが言ってる「公開鍵」は大抵1番目の「認証鍵」のことを指します。
- 認証鍵
- 公開鍵認証でユーザを識別 ( ユーザ認証 ) するときに使う鍵
- 原則として、SSHでアクセスするユーザが自身で作って、自身で管理する
※アクセスを許可する管理者側で作ってユーザに配布する形態もありうる
- ホスト鍵
-
ホスト認証で、アクセス先のサーバを識別するときに使う鍵
※ホストベース認証 ( ユーザ認証の1種 ) に使うケースもあるが、マイナーなので割愛する - 各サーバが個別に持っている
※一般のユーザが作ることはない
-
ホスト認証で、アクセス先のサーバを識別するときに使う鍵
認証鍵
公開鍵認証のイメージ
2種類の鍵の用途に書いた通り、認証鍵は公開鍵認証というユーザ認証手続きで使用します。
電子署名の応用で、秘密鍵の所有者しか正しい署名が作れないことを利用し、署名の正しさを公開鍵で検証してもらうことで、確かに所有者であることを確認してもらいます。
これが本人確認になっているということです。
このような使い方ですから、秘密鍵は利用者本人以外に漏らしてはいけませんし、公開鍵は予めサーバに登録しておく必要があります。
電子署名は、ちょうど現実での印鑑を実現したような技術であり、その応用である公開鍵認証は、さながら銀行での手続き時に銀行印での押印を確認してもらうようなものと言えます。
※図だとユーザ側で使うのは秘密鍵だけに見えますが、実際は秘密鍵・公開鍵の両方を使います。
認証鍵の形式
さて、認証鍵はユーザ側で使うものですが、アプリによってそのファイル形式が違います。
細かく知っておく必要はありませんが、合っていない形式では使えませんので、自分のアプリに合う形式はどれかは、知っておく必要があります。
※とは言え、メジャーなWindows用クライアントであるTeraTerm、RLogin、MobaXtermの最近のバージョンは、以下に挙げる形式全てに対応しています。
その形式ですが、大きく次の3通りです。
- OpenSSH形式
- Linux,Mac等、UNIX系OSで標準で使われるOpenSSH ( sshコマンドなど ) で使われる形式です。
※OpenSSHは最近のWindowsでも使えます - "id_rsa" と "id_rsa.pub" のように、秘密鍵と公開鍵のファイルが分離しており、公開鍵の方は "秘密鍵ファイル名.pub" というファイル名になります。
- クライアント側は秘密鍵だけでも使えますが、基本的には2ファイルセットと考えてください。
- 秘密鍵には新旧の2形式がありますが、最近のアプリであれば特に違いを気にせず使えます。
- サーバの多くはOpenSSHであるため、サーバに登録する公開鍵も大抵この形式です。
- Linux,Mac等、UNIX系OSで標準で使われるOpenSSH ( sshコマンドなど ) で使われる形式です。
- PuTTY形式
- ssh.com(RFC4716)形式
- (OpenSSHでない)元祖のsshや、その後継であるTectiaで使用する形式です。
- OpenSSH形式と同様、秘密鍵と公開鍵のファイルが分離しています。
※公開鍵の方がRFC4716として規格になっています。 - 多くの人には縁のない形式ですが、間違えてこの形式で作らないよう、存在は知っておいた方が良いです。
いずれもテキスト形式であり、エディタで内容を見たり、コピペしたりできます。
それぞれ、次章で紹介するPuTTYgenで作成・変換した場合の例を挙げます。
あくまで例ですのでこれを覚える必要はありませんが、OpenSSH形式の公開鍵が1行のテキストであることについては重要ですので、覚えた方が良いと思います。
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAEEAiMqC2qjdnWEUp3Nf2eeHq4jQML/6jAq4sQmn3g7+Rr5r6eSU9W1u8qYzVdN2cqznA7Sst6xMODQeTD3KpyioQQ== FOR-TEST-ONLY
-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJBAIjKgtqo3Z1hFKdzX9nnh6uI0DC/+owKuLEJp94O/ka+a+nklPVt
bvKmM1XTdnKs5wO0rLesTDg0Hkw9yqcoqEECASUCQBYurW+RAVfKjbpKD4seoGEB
bd5kUiSMHfMx/4vLFHosepPszX6bLegMVvqAp20kVet4Wq2jLAXqeeczSvI5RkUC
IQDOI2PweNDPDKG79aE5xXjW2p9q4EifLZQ648cAd6a60wIhAKng9waailokYwms
w4mMKVOnrxKooB2Qz0kBZSavILwbAiALJIHxUqOA0EAX/3B/qc8uNVS5q0IyHiOw
J/zrRLzngQIhAJwa1Sipr5EahIVuUtFsCkzfRu6NHYLzxWWuQUYkY0URAiEAraOM
mNlmoCthPuY5EX4DkMibTUU3mKdT0qUGhl6Ywm0=
-----END RSA PRIVATE KEY-----
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAVQAAAAdz
c2gtcnNhAAAAASUAAABBAIjKgtqo3Z1hFKdzX9nnh6uI0DC/+owKuLEJp94O/ka+
a+nklPVtbvKmM1XTdnKs5wO0rLesTDg0Hkw9yqcoqEEAAAEwtdstPbXbLT0AAAAH
c3NoLXJzYQAAAEEAiMqC2qjdnWEUp3Nf2eeHq4jQML/6jAq4sQmn3g7+Rr5r6eSU
9W1u8qYzVdN2cqznA7Sst6xMODQeTD3KpyioQQAAAAElAAAAQBYurW+RAVfKjbpK
D4seoGEBbd5kUiSMHfMx/4vLFHosepPszX6bLegMVvqAp20kVet4Wq2jLAXqeecz
SvI5RkUAAAAhAK2jjJjZZqArYT7mORF+A5DIm01FN5inU9KlBoZemMJtAAAAIQDO
I2PweNDPDKG79aE5xXjW2p9q4EifLZQ648cAd6a60wAAACEAqeD3BpqKWiRjCazD
iYwpU6evEqigHZDPSQFlJq8gvBsAAAANRk9SLVRFU1QtT05MWQECAwQFBgcICQoL
DA0ODw==
-----END OPENSSH PRIVATE KEY-----
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: FOR-TEST-ONLY
Public-Lines: 2
AAAAB3NzaC1yc2EAAAABJQAAAEEAiMqC2qjdnWEUp3Nf2eeHq4jQML/6jAq4sQmn
3g7+Rr5r6eSU9W1u8qYzVdN2cqznA7Sst6xMODQeTD3KpyioQQ==
Private-Lines: 4
AAAAQBYurW+RAVfKjbpKD4seoGEBbd5kUiSMHfMx/4vLFHosepPszX6bLegMVvqA
p20kVet4Wq2jLAXqeeczSvI5RkUAAAAhAM4jY/B40M8Mobv1oTnFeNban2rgSJ8t
lDrjxwB3prrTAAAAIQCp4PcGmopaJGMJrMOJjClTp68SqKAdkM9JAWUmryC8GwAA
ACEAraOMmNlmoCthPuY5EX4DkMibTUU3mKdT0qUGhl6Ywm0=
Private-MAC: 09f35a0dc538bc6f4dc722f41024dd15f10f601d
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "FOR-TEST-ONLY"
AAAAB3NzaC1yc2EAAAABJQAAAEEAiMqC2qjdnWEUp3Nf2eeHq4jQML/6jAq4sQmn
3g7+Rr5r6eSU9W1u8qYzVdN2cqznA7Sst6xMODQeTD3KpyioQQ==
---- END SSH2 PUBLIC KEY ----
---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
Comment: "FOR-TEST-ONLY"
P2/56wAAAUwAAAA3aWYtbW9kbntzaWdue3JzYS1wa2NzMS1zaGExfSxlbmNyeXB0e3JzYS
1wa2NzMXYyLW9hZXB9fQAAAARub25lAAAA/QAAAPkAAAAGJQAAAf0WLq1vkQFXyo26Sg+L
HqBhAW3eZFIkjB3zMf+LyxR6LHqT7M1+my3oDFb6gKdtJFXreFqtoywF6nnnM0ryOUZFAA
ACAIjKgtqo3Z1hFKdzX9nnh6uI0DC/+owKuLEJp94O/ka+a+nklPVtbvKmM1XTdnKs5wO0
rLesTDg0Hkw9yqcoqEEAAAEAraOMmNlmoCthPuY5EX4DkMibTUU3mKdT0qUGhl6Ywm0AAA
EAqeD3BpqKWiRjCazDiYwpU6evEqigHZDPSQFlJq8gvBsAAAEAziNj8HjQzwyhu/WhOcV4
1tqfauBIny2UOuPHAHemutM=
---- END SSH2 ENCRYPTED PRIVATE KEY ----
認証鍵作成ツール
続いては、認証鍵を作成するためのツールについてです。
詳細な使い方は、様々なサイトや各種マニュアルで説明がありますので、ここでは代表的な手段についての紹介にとどめます。
-
ssh-keygen
コマンド - TeraTermの鍵生成メニュー
- PuTTYgen/MobaKeyGen
公開鍵の登録
折角作成した鍵も、サーバに公開鍵を登録しないと、使い物になりません。
※念のためですが秘密鍵は手元に置いておくものなので、サーバや管理者に送ったりはしないようにしましょう。
その方法については、サーバの管理者の案内する方式に従うのが筋です。例えばGitHubの場合、次のようにsettingsメニューから登録できるように、Webページ上でメニューが整備されています。
しかし、多くのサーバでは、パスワードでログインした上で、自分で鍵登録手続きを行うようになっており、Linux/UNIXでのCUIの基本的な操作ができることを要求されます。このことで敷居が高いと感じる人も少なくないようです。
※歴史的に、各種サービス共通で使うためにシステムで管理するパスワードと違って、鍵はSSH専用なので自己管理という扱いで来ている点が大きいと思われます。
手順については色々あるのですが、どういう状態にするかを意識した方が良いと思います。以下に、サーバがOpenSSHの場合(大抵はそうだと思いますが)の、デフォルト状態での登録方法について触れます。
- 登録の概要
- サーバ上で、ユーザ個々の鍵登録用のファイル ( authorized_keysファイルと呼ぶ ) に公開鍵データを登録します。
- authorized_keysファイルには複数の鍵データを登録することができます。
- マルチユーザシステムであるLinux/UNIXのセキュリティ管理上、他ユーザからファイルの内容が差し替えられる恐れがあると登録無効となります。
※Linux/UNIX上のファイルのパーミッションの話になります。
- 鍵登録の条件
- authorized_keysファイルの場所(パス)は、サーバ上のホームディレクトリ(個人用のデータディレクトリ)から見て
.ssh/authorized_keys
です。
※よく~/.ssh/authorized_keys
と表現します。 - authorized_keysファイルは1行が1公開鍵テキストデータ(OpenSSH形式公開鍵)です。
※公開鍵に加えて、鍵毎の設定も記述できるようになっていますが、取り敢えず考えなくても使えます。 - ホームディレクトリ、
.ssh
ディレクトリ、authorized_keysファイルともに、自ユーザ以外の書き込み(w)権が無効である必要があります。
※パーミッションについて、ディレクトリは 700(rwx------
)、ファイルは 600(rw-------
)が推奨です。 - 状況については、サーバにログインした上で、次のような
ls
,cat
といったコマンドで見ることができます。
※パーミッションは上で挙げた推奨とは違いますが、それでも無効にはならない状態と分かります。
- authorized_keysファイルの場所(パス)は、サーバ上のホームディレクトリ(個人用のデータディレクトリ)から見て
- 色々な手順
※以下、鍵を登録するための色々な手順をざっくり紹介します。- 共通事項
~/.ssh
ディレクトリがない場合はmkdir
コマンドで作成し、chmod
コマンドでパーミッションを調整します。
※既にあってもmkdir
コマンド自体に害はないので、何も考えずに実行する、でも困りません。 - 手順A: 公開鍵を転送してリネーム
クライアント上の公開鍵ファイルをscp等でサーバに転送し、サーバ上で~/.ssh/authorized_keys
にリネームします。
新規の場合はこれでもよいですが、別の鍵登録済みのauthorized_keysファイルがあった場合、そこの情報を消してしまうことになるので、注意が必要です。 - 手順B: エディタでファイルを編集
サーバ上で~/.ssh/authorized_keys
ファイルをエディタで編集し、公開鍵データのテキストを貼り付ける方法です。
エディタの操作に慣れていれば、この方法も良いと思います。 - 手順C: サーバ上のコマンドで鍵を追加
サーバ上でコマンドを実行して、ファイルに鍵データを追記する方法です。
予めコマンドを手元に用意して貼り付ければ済むため、紛れが少ないように思います。
※PuTTYgenでの公開鍵のコピペとも相性が良いです。PuTTYgenを使わない場合、メモ帳等で公開鍵ファイルを開いてテキストデータをコピペしましょう。
次のような実行イメージになります。
- 手順D: クライアントで
ssh-copy-id
コマンド
これは、Linux(WSL含む)やMacでOpenSSHクライアントを使う場合の方法です。
サーバ上で必要となる手順を一式自動で行ってくれるため、使える場合はお勧めです。
次のような実行イメージになります。
- 共通事項
ホスト鍵
ホスト鍵の概要
認証鍵がサーバでユーザを識別するものであるのに対し、ホスト鍵は「ホスト認証」においてクライアントがサーバを識別するために使うものです。
簡単に言うと、本物のサーバに接続できているかの判断材料になります。
ホスト鍵も認証鍵と同じ、電子署名の公開鍵・秘密鍵の鍵ペアであり、データとしては同じになります。
鍵ペアをサーバが持ち、公開鍵をクライアントで持つことでホスト認証を実現します。
認証鍵の公開鍵を登録するのがサーバ上の authorized_keysファイルであったのに対し、ホスト鍵はクライアント側の known_hostsファイルや類似のデータベースに登録します。
ホスト鍵の扱い
- known_hostsファイル
- OpenSSHのsshコマンド(他、scp等)を使う場合、クライアントの
~/.ssh/known_hosts
にホスト鍵を登録し、管理します。 - 以前は、サーバドメイン名やIPアドレスと公開鍵データをペアにした形式でした。
- 最近は、ドメイン名・IPアドレスをハッシュ化(難読化)した形式に移行しています。
- OpenSSH以外のアプリの場合、例えばWinSCPはレジストリ上で管理するなど、形式は様々です。
- 形式を知っていれば直接操作できる場合もありますが、基本は直接編集するものではないと考えてください。
- 実際に、github.comのホスト鍵のみ登録すると、次のようになります。
※known_hostsファイルに対して行番号が出ているのはcat -n
のためであり、ファイルの中にそのような番号はありません。
※ハッシュ化すると、ドメイン・IPアドレス毎にエントリが分かれるため、してない方に比べてエントリが増えているように見えます。
- OpenSSHのsshコマンド(他、scp等)を使う場合、クライアントの
- ホスト鍵の登録
- 細かく言うと、事前にホスト鍵(公開鍵)を入手してknown_hostsファイルに登録するのが最も厳格な運用です。
- しかし、利便性と折衷にした結果、初回接続時にサーバが提示した公開鍵を見て登録承認するのが一般的になっています。
- 素の公開鍵データでは比較が難しいため、大抵はハッシュ(フィンガープリント)で見ることになります。
※最近はASCIIアートにより、2次元にビジュアル化した表現も使われます。 - 以下は、OpenSSHのsshコマンド、あるいはTeraTermで初回接続を試みた時の状況です。
github.comの公開しているホスト鍵情報に合うため、本物のサーバと判断することができます。
※2023/3/24更新: 記事執筆時からgithubのホスト鍵が更新されていますので、ご自身の環境で確認する際はGitHub's SSH key fingerprintsをご覧下さい。画像は古い鍵のものです。
- ホスト鍵の自動チェック
- 一度known_hostsファイルにホスト鍵が登録されると、次回接続からは自動的にサーバが本物かどうかがチェックされます。
- もしホスト鍵が異なる場合、つまりサーバ側がホスト鍵を変えたか、あるいはニセのサーバに接続されている場合、クライアントが警告をあげるようになっています。
- サーバが鍵を変えたという話を把握しているなら、鍵の登録を削除する、上書きするといった対処が考えられます。
- しかしサーバが鍵を変えたという確信がないなら、接続を取りやめて管理者に確認をとるべきだと言えます。十分に注意しましょう。
- 以下、OpenSSHのsshコマンドや、TeraTermでホスト鍵の不一致を検出した状況です。
デフォルトでは、sshコマンドは即座に通信を打ち切ります。(メッセージとして鍵の登録削除の案内も出します)
その他の話題
ここでは、細かいところではあるものの、鍵を利用する上で気になるかもしれない点をざっくり説明します。
- 鍵のアルゴリズム
- 電子署名(公開鍵暗号の1種)には複数の方式があり、鍵のアルゴリズムとして使用することができます。
- 機能的には差がないので基本どれを利用しても構いませんが、古い環境で対応していないもの、新しい環境で廃止されたもの、暗号強度の違いなどがあります。
- 古くから対応しているのは RSA,DSA、その後 ECDSA、ed25519(EdDSA)と、現在4種類あります。
※かなり古い環境だと、後者2種類に対応していない可能性があります。
※逆にDSAは現在非推奨であり、新しい環境では使えなくなっています。 - ed25519以外は、鍵の強度を示す「鍵長」というパラメータがあります。
- 鍵の強度をアルゴリズム間で比較すると次のようになります。
現在は最低でもRSA 2048bit、できればそれより上の方式の鍵を使いましょう。
RSA/DSA 1024bit<今の最低限=RSA 2048bit<RSA 3072bit≒ECDSA 256bit≒ed25519<… - ECDSA,ed25519は、RSAと比較すると、より少ない鍵データ容量で同等の強度を実現できるというメリットがあります。
- パスフレーズによる鍵の保護
- 各形式の秘密鍵には、パスフレーズにより保護をかけた版もあります。
- PCからデータ流出する、PCが盗まれる等、秘密鍵が流出した際に悪用されるまでの時間稼ぎを意図した保護です。
- 各ツールで鍵を作成する際にパスフレーズを設定することができます。
※後からパスフレーズの再設定や解除を行うこともできます。 - 秘密鍵を使う際、設定したパスフレーズの入力が求められます。
※アプリによってはサーバ上のパスワードを入力するのと見分けがつきにくいことがありますので、注意が必要です。 - パスフレーズを設定した方がセキュリティ的には望ましいですが、利用シーンと合わせ、設定するかどうか判断しましょう。
- 鍵の使いまわし
- パスワードと違い、同じ公開鍵を各サーバに登録するデメリットがありません。
※プライバシー的な懸念がある ( 各所の利用者が同一であることがバレてほしくない ) 場合は別です。 - 逆に、同じ秘密鍵を複数のクライアント機器で共有するのはお勧めしません。
- サーバ上のユーザに対して、公開鍵は複数登録できるようになっているので、クライアント機器毎に鍵を作って機器外に秘密鍵を出さないようにしましょう。
- パスワードと違い、同じ公開鍵を各サーバに登録するデメリットがありません。
- authorized_keysファイルのパーミッション不備の検出
- 公開鍵の登録の章で、authorized_keysファイルのパーミッションの話をしましたが、分かっていてもここでトラブル人は非常に多いです。
- その場合、パスワード認証も有効にして、公開鍵認証失敗→パスワード認証成功とすれば、サーバからデバッグ情報として理由が通知されます。
- 詳細はTogetterまとめSSH鍵登録不備の通知に関する話をご覧ください。
終わりに
思いつくままに関連しそうな項目を挙げたので、把握するのが非常に大変なことに見えるかも知れませんが、概要だけでも十分です。SSHを使う場面になったときに混乱しないために活用していただければ幸いです。