OpenSSHでPEM形式のed25519鍵を使う
二つの秘密鍵形式
OpenSSHの秘密鍵には二種類の形式があります。
- OpenSSL PEM形式[1] (旧形式)
- OpenSSH独自形式 (新形式)
しかしed25519鍵については歴史的経緯[2]により常にOpenSSH形式が使われ、PEM形式は使えませんでした。
この為OpenSSLでPEM形式のed25519鍵を生成してもOpenSSHでは長い間使えなかったのですが、2023-12-19に出たOpenSSH 9.6ではRelease Notesに
* ssh(1), sshd(8), ssh-add(1), ssh-keygen(1): add support for
reading ED25519 private keys in PEM PKCS8 format. Previously
only the OpenSSH private key format was supported.
と有るようにPEM形式のed25519秘密鍵の読み込みに対応しました。
今回はこのPEM形式ed25519秘密鍵の読み込みを試してみます。
テスト環境
今回のテストは以下の環境で行いました。
OS: FreeBSD 13.2-RELEASE
OpenSSL: OS付属(1.1.1t)
OS付属のOpenSSHが 9.3 だった為、PEM形式のed25519鍵が扱えません。
なので、2024-06-06時点で最新のOpenSSH 9.7p1をビルドして試します。
今回はJAISTのミラーサーバーからopenssh-9.7p1.tar.gz
を入手しました。
sue@hiyo% fetch http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/openssh-9.7p1.tar.gz
openssh-9.7p1.tar.gz 1805 kB 3119 kBps 01s
sue@hiyo% ls -l openssh-9.7p1.tar.gz
-rw-r--r-- 1 sue yac 1848766 Mar 11 19:19 openssh-9.7p1.tar.gz
入手した openssh-9.7p1.tar.gz
を展開して、ビルドします。
sue@hiyo% tar xf openssh-9.7p1.tar.gz
sue@hiyo% cd openssh-9.7p1
sue@hiyo% ./configure && make
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
~略~
sue@hiyo% ./ssh -V
OpenSSH_9.7p1, OpenSSL 1.1.1t-freebsd 7 Feb 2023
無事?にビルド出来ました。
PEM形式のed25519秘密鍵の生成
openssl
コマンドで、ed25519秘密鍵を生成します。
sue@hiyo% openssl genpkey -algorithm ed25519 -aes256 -out ed25519.pem
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
sue@hiyo% ls -l ed25519.pem
-rw------- 1 sue yac 290 Jun 6 05:28 ed25519.pem
生成された秘密鍵の内容を確認します。
sue@hiyo% cat ed25519.pem
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAiX4qpoSTUwnwICCAAw
DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEED8l6dB/KGe/dujI2/26E6QEQCxB
K1RfjhHkoKQKBxZDJJQx9onZV20wim2l/hQvGVfDZhFtnNPC53bXDZ28x5+FrRjZ
tr04tYiOz3P/znQG0ZQ=
-----END ENCRYPTED PRIVATE KEY-----
1行目が -----BEGIN ENCRYPTED PRIVATE KEY-----
となっており、OpenSSH形式の秘密鍵では無い事が確認出来ました。
この秘密鍵を使ってSSHログインする為には対応する公開鍵が必要になります。
そこでssh-keygen
コマンドを使って秘密鍵から公開鍵を取り出してみましょう。
sue@hiyo% ./ssh-keygen -y -f ed25519.pem
Enter passphrase:
Load key "ed25519.pem": invalid format
……なぜかエラーが出てうまくいきません。
念の為、ssh
コマンドで秘密鍵が読めるか試してみますが、やはりエラーになります。
sue@hiyo% ./ssh -i ed25519.pem localhost
Enter passphrase for key 'ed25519.pem':
Load key "ed25519.pem": invalid format
(sue@localhost) Password for sue@hiyo.iwmt.org:
エラーの原因と対処
エラーの原因を調べます。まず、configure
の出力で気になる部分が無いかを確認してみます。
sue@hiyo% ./configure && make
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
~略~
checking for EVP_PKEY_get_raw_private_key... yes
checking whether OpenSSL has ED25519 support... no
checking whether to enable PKCS11... yes
~略~
なぜかOpenSSLがed25519に対応していないと判定されています。
詳細を調べる為、config.log
を確認します。
~略~
configure:19224: checking whether OpenSSL has ED25519 support
configure:19245: cc -o conftest -g -O2 -pipe -Wunknown-warning-option -Qunused-arguments -Wall -Wextra -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-parameter -Wno-unused-result -Wmisleading-indentation -Wbitwise-instead-of-logical -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -ftrapv -mretpoline -fno-builtin-memset -fstack-protector-strong -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,retpolineplt -fstack-protector-strong conftest.c -lcrypto -lutil >&5
conftest.c:293:23: error: too few arguments to function call, expected 4, have 3
buf, sizeof(buf)) == NULL);
^
/usr/include/openssl/evp.h:1362:11: note: 'EVP_PKEY_new_raw_private_key' declared here
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
^
1 error generated.
~略~
OpenSSLのed25519サポート判定の部分で、関数の引数の数が違う為コンパイルに失敗し、ed25519に対応していないと判定されているようです。
どうやらconfigure
スクリプトにバグが有り、OpenSSH 9.7p1のリリース後に修正されたようです。
configure
を使うのはポータブル版OpenSSHのみなので、未確認ですがOpenBSDでは問題無く使えると思われます。
GitHubのHEADでは修正済みですが、今回はこの修正をOpenSSH 9.7p1のソースに適用する事によって対応してみます。
configure.ac
をvi
で開き、3187行目のEVP_PKEY_new_raw_private_key
の引数にNULL
を追加します。
memset(buf, 0, sizeof(buf));
exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519,
buf, sizeof(buf)) == NULL);
]])],
memset(buf, 0, sizeof(buf));
exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
buf, sizeof(buf)) == NULL);
]])],
autoreconf
でconfigure.ac
からconfigure
を生成し直して、再度ビルドします。
sue@hiyo% autoreconf
sue@hiyo% ./configure && make
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
~略~
checking for EVP_PKEY_get_raw_private_key... yes
checking whether OpenSSL has ED25519 support... yes
checking whether to enable PKCS11... yes
~略~
OpenSSLがed25519に対応していると、正しく判定されるようになりました。
PEM形式のed25519鍵によるログインテスト
今度こそPEM形式のed25519鍵が扱えるようになったので、実際にログインしてみます。
まずはPEM形式のed25519秘密鍵から、OpenSSH形式の公開鍵を生成します。
秘密鍵の形式は自動判別される為、ssh-keygen
コマンドのオプションはOpenSSH形式の秘密鍵を扱う時と同じです。
sue@hiyo% ./ssh-keygen -y -f ed25519.pem | tee ed25519.pem.pub
Enter passphrase:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE3HgnDc+VfLP25llaY6PHEfIGW5k414MN3SD+fm6MHp
sue@hiyo% ls -l ed25519.pem.pub
-rw-r--r-- 1 sue yac 81 Jun 6 06:32 ed25519.pem.pub
PEM形式のed25519秘密鍵が読めて、OpenSSH形式の公開鍵が作成されました。
公開鍵をログイン先のサーバーの~/.ssh/authorized_keys
に追加します。
今回はテストで自分自身に追加してみます。
sue@hiyo% cat ed25519.pem.pub >> ~/.ssh/authorized_keys
公開鍵を登録したので、実際にPEM形式のed25519秘密鍵を使ってログインしてみます。
ssh
コマンドで利用する時も秘密鍵の形式は自動判別されるので、OpenSSH形式の時とオプションは同じになります。
sue@hiyo% ./ssh -i ed25519.pem -o IdentitiesOnly=yes localhost
Enter passphrase for key 'ed25519.pem':
Last login: Thu Jun 6 05:22:32 2024 from localhost
FreeBSD 13.2-RELEASE-p4 GENERIC
Welcome to FreeBSD!
Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories: https://www.FreeBSD.org/security/
FreeBSD Handbook: https://www.FreeBSD.org/handbook/
FreeBSD FAQ: https://www.FreeBSD.org/faq/
Questions List: https://www.FreeBSD.org/lists/questions/
FreeBSD Forums: https://forums.FreeBSD.org/
Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with: pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.
Show the version of FreeBSD installed: freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages: man man
FreeBSD directory layout: man hier
To change this login announcement, see motd(5).
sue@hiyo%
無事ログイン出来ました。
注意点
OpenSSH 9.6で対応したのは、PEM形式ed25519秘密鍵の読み込みのみです。
PEM形式での書き出しには対応していません。
ssh-keygen
でed25519鍵を生成する時に-m pem
や-m pkcs8
を指定してもOpenSSH形式の秘密鍵が生成されます。
またssh-keygen -p
でパスフレーズを付け直す時に-m pem
や-m pkcs8
を指定してもOpenSSH形式の秘密鍵に変換されてしまいます。
PEM形式の公開鍵の読み込みには対応していません。
ssh-keygen -i
で読み込もうとしてもエラーになります。
sue@hiyo% openssl pkey -in ed25519.pem -pubout -out ed25519.pem.pub
Enter pass phrase for ed25519.pem:
sue@hiyo% cat ed25519.pem.pub
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEATceCcNz5V8s/bmWVpjo8cR8gZbmTjXgw3dIP5+bowek=
-----END PUBLIC KEY-----
sue@hiyo% ./ssh-keygen -i -f ed25519.pem.pub -m pkcs8
do_convert_from_pkcs8: unsupported pubkey type 1087
まとめ
- OpenSSH 9.6よりPEM形式のed25519秘密鍵が使えるようになりました。
- 利用する時には鍵の形式は自動判別される為、オプションは特に指定する必要は有りません。
- ポータブル版OpenSSH 9.6p1, 9.7p1では
configure
スクリプトにバグが有って使えません。このバグは9.8p1以降では修正されています。
Discussion