sftp(ssh)で「send_pubkey_test: no mutual signature algorithm」エラーの原因

saratogax
記事内に商品プロモーションを含む場合があります

リモートサーバへ sftp で接続しようとしたら以下のエラーが発生。

send_pubkey_test: no mutual signature algorithm

相手に渡した公開鍵の問題か、相手側のサーバ(sshd や authorized_keys など)の問題かと思い、あれこれ試したのですが解決せず。

大した話ではないのですが、ちょっとハマったので備忘録として原因と対応方法を残しておきます。

エラーの詳細

冒頭のエラーメッセージは、以下の sftp コマンドのログモードの出力結果の中から見つけたもの。

$ sftp -vvv -P 22 -i [private_key] USER@HOST

鍵認証のハズなのに、パスフレーズではなくパスワードが問われたので、おかしいなって思ったのが最初でした。

キーペアを作成する際、Mac 上から以下のコマンドを実行して作成しました。

先に結論に触れておくと、このエラーで問題になっているのは「RSA という鍵」ではなく「ssh-rsa という署名アルゴリズム(RSA を SHA-1 でハッシュする古い方式)」です。OpenSSH 8.8(2021年)でこの SHA-1 署名がデフォルト無効になりました。公式リリースノートも「there is no need to replace ssh-rsa keys」と明記していて、RSA の鍵そのものは今も有効です。だから、このあと出てくる「鍵を作り直す」対応では直りません。

$ ssh-keygen -t rsa -C test -f test_id_rsa

ただ、相手サーバの要求は RSA(2048)ということで、よくよく鍵を調べてみたら生成した鍵が RSA(3072)となっていました。

$ ssh-keygen -l -f test_id_rsa

3072 SHA256:xxxxxxxxxx test (RSA)

これの問題かなっと思って、RSA(2048)で作り直したけど結果は同じ。

$ ssh-keygen -t rsa -b 2048 -C test -f test_id_rsa

エラーの原因

相手側のサーバのログ(auth.log や secure.log など)を見てもらいたいところですが、なかなか確認してもらえなかったところ、以下の情報をキャッチ。

これは、Bitbucket のサポートページの一部に記載されていたものです。

It is important to note that by default Bitbucket offers support for ECDSA and ED25519 algorithm. Keys generated with these algorithms are not affected by RSA deprecation.

Bitbucket はデフォルトで ECDSA および ED25519 アルゴリズムのサポートを提供していることに注意することが重要です。これらのアルゴリズムで生成されたキーは、RSA の非推奨の影響を受けません。

これの解決策について以下の記載もありました。

This workaround should only be taken if it is impossible to regenerate SSH keys with ECDSA and ED25519 algorithms. If you can generate new ECDSA and ED25519 based keys, please proceed to the Resolution using ECDSA and ED25519 algorithms right below.

In order to re-enable ssh-rsa support, inserting the following line into the affected SSH client’s config file can re-enable this algorithm:

この回避策は、ECDSA および ED25519 アルゴリズムで SSH キーを再生成できない場合にのみ実行してください。新しい ECDSA および ED25519 ベースのキーを生成できる場合は、すぐ下の ECDSA および ED25519 アルゴリズムを使用した解決策に進んでください。 ssh-rsa サポートを再度有効にするには、影響を受ける SSH クライアントの構成ファイルに次の行を挿入すると、このアルゴリズムを再度有効にできます。

なるほど、ssh クライアント側の問題ということなんですね。

整理すると、新しめの OpenSSH クライアント(8.8 以降)が ssh-rsa(RSA+SHA-1)署名をデフォルトで送らなくなったのが原因です。本来はサーバが rsa-sha2-256 / rsa-sha2-512(同じ RSA 鍵で、ハッシュを SHA-2 にした署名)に対応していれば自動でそちらが使われます。今回のサーバはその新しい署名に対応しておらず、ssh-rsa しか受け付けなかったため、両者の署名アルゴリズムが噛み合わず「no mutual signature algorithm(相互に使える署名アルゴリズムがない)」になった、というわけです。

試したサーバが AmazonLinux2023 で、比較的新しいものになります。

# cat /etc/os-release

NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PLATFORM_ID="platform:al2023"
PRETTY_NAME="Amazon Linux 2023"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
HOME_URL="https://aws.amazon.com/linux/"
BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
SUPPORT_END="2028-03-01"

今回はコマンドベースでしたので、署名アルゴリズムを明示するオプションを指定して実行しました。ssh-rsa を受け付けるサーバ相手の、あくまで応急処置です。

PubkeyAcceptedKeyTypes は OpenSSH 8.5 で PubkeyAcceptedAlgorithms改名されました。公式が「以前の名前は、鍵のアルゴリズムを制御するかのように誤解を招く。実際には署名アルゴリズムを指定するもの」と説明しています。旧名もエイリアスとして残っているのでどちらでも通りますが、意味を正しく表しているのは PubkeyAcceptedAlgorithms のほうです。

$ sftp -o PubkeyAcceptedKeyTypes=ssh-rsa -P 22 -i [private_key] USER@HOST

これで無事に接続ができました。

ssh クライアントが原因とは思ってもなかったので、これは大反省です・・・。

まとめ

確かに公開鍵認証は ecdsa や ed25519 も広く使われるようになっていますが、今回のエラーの主因はそこではありません。RSA 鍵のままでも、クライアントとサーバが rsa-sha2-256 / rsa-sha2-512 に対応していれば問題なくつながります。引っかかったのは、サーバが古い ssh-rsa(SHA-1)署名しか受け付けなかったからでした。

今回はリモートサーバの設定ではなく、こちらのクライアント側の問題でしたが、もしリモートサーバ側でキータイプが制限されていたらどうなっていたのか。

結果的には、以下のような権限エラーになっていたのかなと想像できます。

Permission denied (publickey).

最後に、ヒントとなった Bitbucket のページを紹介して締めくくりを。

参考(出典)

ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました