OpenSSH 鍵をアップグレードする【2020-01-11 改訂】
【2020-01-11 改訂】
2020-05-27 に OpenSSH 8.3 がリリースされた。
この中で “Future deprecation notice” として
と書かれていてた1。 といっても,これはサーバ側の設定の話だそうでクライアントには関係ないそうだ(フィードバック感謝)。
もし2048ビット以下の古い RSA 鍵を使ってるなら替えどきかな。 で,どうせ鍵を新調するのなら楕円曲線暗号(Elliptic Curve Cryptography; ECC)で構成するのがいいよね。
ちうわけで,ECC 鍵を作って登録するところまでやってみる。 ちゃんとメモっておかないと忘れるので(笑)
前提条件【2021-01-09 変更】
今回は Ubuntu 環境下での作業とし鍵管理を GnuPG で行うものとする。 Ubuntu での設定方法は以下を参考にどうぞ。
Windows 環境の場合は以下の拙文を参考にどうぞ。
ちなみに,今回は鍵の生成を OpenSSH で行っているが GnuPG でも生成できる。 詳しくは以下を参照のこと。
OpenSSH 鍵の生成
OpenSSH 鍵を生成するには ssh-keygen
コマンドを使う。
たとえばこんな感じ。
$ ssh-keygen -t ecdsa -b 256 -C "alice@example.com"
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/username/.ssh/id_ecdsa
Your public key has been saved in /home/username/.ssh/id_ecdsa.pub
The key fingerprint is:
SHA256:DtXgQm9rz7Dc5M5yWu/CNVo341o1rcfN9UCyYu+SZU4 alice@example.com
The key's randomart image is:
+---[ECDSA 256]---+
| . . |
| . o o |
| . = . . . |
| + . + .|
| . S + . ..+|
| = X oE +*=|
| +.*X.+oo*|
| .+Bo.... |
| .+o+=. |
+----[SHA256]-----+
これで作成された id_ecdsa
および id_ecdsa.pub
ファイルが鍵ファイルである。
ちなみに id_ecdsa
ファイルには秘密鍵, id_ecdsa.pub
ファイルには公開鍵が格納されている。
-t
オプションで鍵種別を, -b
で鍵長(ビット数)をセットする。
鍵種別と鍵長の組み合わせと,それぞれに対するセキュリティ強度(ビット数)は以下の通り2。
鍵種別 | 鍵長 | 強度 | 楕円曲線名 |
---|---|---|---|
dsa |
80 | — | |
ecdsa / ecdsa-sk |
256 | 128 | nistp256 |
384 | 192 | nistp384 |
|
521 | 256 | nistp521 |
|
ed25519 / ed25519-sk |
— | 128 | ed25519 |
rsa |
3072 | 128 | — |
7680 | 192 | ||
15360 | 256 |
この組み合わせの(dsa
以外の)いずれかであれば2031年以降も問題なく使える。
なお ecdsa-sk
および ed25519-sk
は暗号デバイスに登録する際に使うらしい(今回は割愛する)。
余談だが楕円曲線 ed25519
に対応する電子署名アルゴリズムは EdDSA と呼ばれ RFC 8032 で規定されている3。
なんで鍵種別を eddsa
としなかったのかは知らない。
紛らわしかったのかな?
楕円曲線と鍵長
(「そろそろ GnuPG でも ECC を標準で使うのがいいんじゃないかな」より抜粋)
ここでちょっと横道に逸れて鍵長の話をしておく。
たとえば RSA の(平文 $M$ から暗号文 $C$ への)暗号化は以下の式で表される。
$(e, n)$ のセットが公開鍵で, $n$ のサイズが鍵長に相当する。 実際の計算はともかく,感覚としては分かりやすいよね。
ECC の場合は暗号化の前に,まずベースとなる楕円曲線の(素数 $q$ で決められる)素体(prime fields)を決めなければならない4。 これは以下の式で表される。
この素体上の有理点の数(位数)を $\#E$ とした時の $\#E$ のサイズが鍵長に相当する。 $(a,b,q)$ といったパラメータを眺めただけでは鍵長が分からないというのが面倒臭い感じである5。
そこで ECC の場合は楕円曲線を表すパラメータのセットが標準化されている。
OpenSSH の場合は nistp256
, nistp384
, nistp521
, ed25519
といった楕円曲線名に対応している。
つまり楕円曲線名から楕円曲線の種類を特定し,そこから鍵長も分かる,というわけだ。
OpenSSH 鍵の登録(クライアント側)
本題に戻る。
作成した OpenSSH 鍵ファイル id_ecdsa
および id_ecdsa.pub
を登録しよう。
クライアント側は ssh-add
コマンドを使って秘密鍵ファイル id_ecdsa
の内容を GnuPG の鍵束に永続的に登録できる。
$ ssh-add ./id_ecdsa
Enter passphrase for ./id_ecdsa:
Identity added: ./id_ecdsa (alice@example.com)
この時 ssh-add
コマンドによるパスフレーズ入力とは別に GnuPG の pinentry によるパスフレーズの設定が行われる(確認を含めて2回入力する必要あり)。
Pinentry で設定するパスフレーズは id_ecdsa
ファイルに対するものとは管理が異なるので注意。
というか GnuPG の鍵束に登録したら id_ecdsa
ファイルは不要になる。
OpenSSH 秘密鍵が登録できたかどうかは ~/.gnupg/sshcontrol
ファイルで確認できる。
ちゃんと登録できていれば以下のような内容が追記される。
# ECDSA key added on: 2020-06-01 14:05:35
# Fingerprints: MD5:e4:5b:66:a6:03:9a:a4:0e:f2:1b:a5:04:72:93:f3:f0
# SHA256:DtXgQm9rz7Dc5M5yWu/CNVo341o1rcfN9UCyYu+SZU4
A5353D587000D820669B0BD55A0B4AD6897458DB 0
また ssh-add -L
コマンドでも登録した鍵を確認できる。
鍵の実体は ~/.gnupg/private-keys-v1.d/
ディレクトリにある。
上述の鍵の場合は
A5353D587000D820669B0BD55A0B4AD6897458DB.key
というファイル名で格納されているはずである。
OpenSSH 鍵の登録(サーバ側)
ログイン先のサーバに公開鍵ファイル id_ecdsa.pub
の中身を登録する。
つっても,どうにかして id_ecdsa.pub
ファイルをサーバにアップロードして
$ cat ./id_ecdsa.pub >> ~/.ssh/authorized_keys
と authorized_keys
ファイルに追記すればよい。
追記ではなく内容を書き換えるなら
$ cat ./id_ecdsa.pub > ~/.ssh/authorized_keys
でもよい。 書き換えるなら以前のファイルのバックアップはとってね。 パーミッションの設定も忘れずに。
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
老婆心ながら,新しい鍵でログインできることを確認するまでは接続中のセッションは切らないこと。 設定を間違えてログイン不能になったら悲惨だからねぇ。
【2021-12-13 追記】 ssh-copy-id を使う方法
フィードバックで教えてもらったが(感謝!) ssh-copy-id
コマンド(中身は shell スクリプト)を使うともっと簡単に登録できるそうだ。
$ ssh-copy-id -h
Usage: /usr/bin/ssh-copy-id [-h|-?|-f|-n] [-i [identity_file]] [-p port] [-F alternative ssh_config file] [[-o <ssh -o options>] ...] [user@]hostname
-f: force mode -- copy keys without trying to check if they are already installed
-n: dry run -- no keys are actually copied
-h|-?: print this help
ふむむ。
-n
オプションで dry run できるのか。
ありがたい。
-i
オプションで公開鍵ファイルを指定するが,標準入力からも受け付けるようなので,パイプで繋いで
$ ssh-add -L | ssh-copy-id -n alice@hostname
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
=-=-=-=-=-=-=-=
Would have added the following key(s):
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFfjejx/Saej929myfZoBQAKgusPi2iiOxdZZfpCLxh5 (none)
=-=-=-=-=-=-=-=
てな感じにできる(実際に登録する際は -n
オプションを外してね)。
あるいは GnuPG で作った認証鍵であれば
$ gpg --export-ssh-key alice | ssh-copy-id -n alice@hostname
などとすることもできる(実際に登録する際は -n
オプションを外してね)。
サーバ側に既に ~/.ssh/authorized_keys
ファイルがある場合は(公開鍵認証でログインした上で)ちゃんと追記してくれるし,パーミッションの心配も要らないようだ。
教えていただいて本当にありがとう 🙇
各種 Git リポジトリ・サービスに公開鍵を登録する
GitHub ではリポジトリのアクセスに OpenSSH 認証が使える。 OpenSSH 認証に使う公開鍵は設定の “SSH and GPG keys” で登録する(複数登録可能)。
Bitbucket や GitLab などの各種 git リポジトリ・サービスでも同様に OpenSSH 公開鍵を登録できる。
よしゃあ! これで作業完了。
ブックマーク
参考図書
- 暗号化 プライバシーを救った反乱者たち
- スティーブン・レビー (著), 斉藤 隆央 (翻訳)
- 紀伊國屋書店 2002-02-16
- 単行本
- 4314009071 (ASIN), 9784314009072 (EAN), 4314009071 (ISBN)
- 評価
20世紀末,暗号技術の世界で何があったのか。知りたかったらこちらを読むべし!
- 暗号技術入門 第3版 秘密の国のアリス
- 結城 浩 (著)
- SBクリエイティブ 2015-08-25 (Release 2015-09-17)
- Kindle版
- B015643CPE (ASIN)
- 評価
SHA-3 や Bitcoin/Blockchain など新しい知見や技術要素を大幅追加。暗号技術を使うだけならこれ1冊でとりあえず無問題。
-
実は同様の問題は GnuPG でも指摘されていて,半年前にリリースされた 2.2.18 で対応済みである(GnuPG 2.2.18 リリース: さようなら SHA-1) ↩︎
-
フィードバックで教えていただいたが, OpenSSH は FIPS 186-3 以降の DSA に対応していないそうで,1024ビットの鍵長しか選択できないらしい。なので,最近の OpenSSH のデフォルト設定では DSA を無効にしているそうな。情報感謝です。あと
ecdsa-sk
では鍵長の指定はできない(無視される)ようだ。256ビット(nistp256
)固定ってことかな? ↩︎ -
ed25519
(edwards25519) は Curve25519 と双有理同値な楕円曲線で,鍵長も Curve25519 と同じく256ビット(セキュリティ強度128ビット)と見積もられている。ちなみに Curve25519 は ECDH 用の楕円曲線およびそのライブラリで,公有(public domain)のソフトウェアとして公開されている。また EdDSA は FIPS 186-5 に組み込まれる予定になっていて,そうなれば正式に NIST 標準となる。 ↩︎ -
素体ではなく「標数2の体(binary fields)」を使う場合もあるが,ここでは割愛する。 ↩︎
-
楕円曲線と楕円曲線暗号については結城浩さんの『暗号技術入門 第3版』の付録に比較的分かりやすい解説が載っている。同じく結城浩さんの『数学ガール ガロア理論』が何となく分かれば楕円曲線についても何となく分かると思う。大丈夫。私も何となくしか分かっていない(笑) ↩︎