使用SSH客户端导出同一个id_ecdsa_256私钥,每次内容都不一样的原因

在 Xshell 或其他 SSH 客户端中,每次导出相同的 ECDSA 私钥(id_ecdsa_256),但其文件内容不同,通常是因为 PEM 格式的加密方式和随机化 影响了最终的存储结果。具体而言,有以下几个关键原因。

1. PEM 格式中的加密随机性

如果你的私钥是加密存储的(即在导出时选择了密码保护),那么PEM 格式(通常是 OpenSSL 兼容的)会使用 PBKDF2 或 bcrypt 进行密钥派生,并为每次导出生成 随机盐值。由于加密盐值不同,即使私钥的核心内容相同,最终的加密数据会有所不同。

可以检查你的私钥文件头部,例如:

-----BEGIN ENCRYPTED PRIVATE KEY-----

如果看到 ENCRYPTED,则意味着该私钥是加密存储的,每次导出的加密数据可能不同。

2. ASN.1 序列化中的随机性

即使你的私钥未加密,它仍然可能以 ASN.1(Abstract Syntax Notation One)编码的 DER(Distinguished Encoding Rules)格式存储:

  • ASN.1 的 DER 编码可能会有不同的填充方式,导致即使内容相同,字节级表示不同。
  • 在某些情况下,ECDSA 私钥的元数据(如生成时间)可能会导致数据的微小变化。

3. 不同的软件导出方式

不同的 SSH 客户端或 OpenSSL 版本可能会使用不同的方式序列化私钥:

  • Xshell 可能在导出时重新编码了私钥,使其格式不同,但实际上仍然是同一个密钥。
  • 使用 OpenSSH 或 OpenSSL 重新导出同一私钥,也可能会生成不同的文件内容,但仍然对应相同的公钥。

4. Base64 编码的多样性

如果你的私钥是以 PEM 格式(Base64 编码)存储,则:

  • 行长(Line Wrapping) 可能不同,即 Base64 编码的换行方式可以有所变化。
  • PEM 头部或尾部的额外信息 可能发生改变,但不影响核心私钥内容。

5. 验证是否是相同私钥

你可以使用以下方法验证你的私钥是否实际上是相同的:

5.1 查看公钥是否一致

ssh-keygen -y -f id_ecdsa_256

如果你每次导出的私钥 生成的公钥相同,则可以确认它们是相同的私钥,只是存储格式不同。

5.2 查看私钥指纹

ssh-keygen -lf id_ecdsa_256

这个命令会计算私钥的指纹,若指纹相同,则说明私钥内容本质上是一样的。

5.3 比较 DER 格式

你可以将 PEM 格式转换为 DER 格式并比较:

openssl ec -in id_ecdsa_256 -outform DER -out id_ecdsa_256.der

md5sum id_ecdsa_256.der

如果 MD5 哈希值相同,说明私钥实际上是一样的。

How to Fix the Error “The Selected User Key is Not Registered on the Remote Host. Please Try Again” When Using XShell with SSH Private Key to Log into a Remote Linux Host

I’m working with a remote Linux host running Ubuntu 24.

Following an online tutorial, I was able to successfully SSH into the remote host using a private key file from Git Bash with the following command:

$ ssh [email protected] -i .ssh/id_rsa

However, when I try using the same command and private key file in XShell, I get the error: “The selected user key is not registered on the remote host. Please try again.”

Upon checking the SSH log file /var/log/auth.log, I found the following message:

userauth_pubkey: signature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

This indicates that the SSH service on the remote host rejected the SSH-RSA public key signature algorithm during authentication, likely because it has been disabled in the remote host’s configuration.

The reason it worked in Git Bash but not in XShell is likely because Git Bash uses a newer version of the OpenSSH client that supports alternative signature algorithms (like rsa-sha2-256 or rsa-sha2-512). On the other hand, XShell may still rely on the ssh-rsa signature algorithm due to its default configuration or older client version, which results in the authentication failure.

Starting from OpenSSH 8.8, the ssh-rsa algorithm is considered insecure, and some server configurations (like Ubuntu 24) disable it by default. In this case, the PubkeyAcceptedAlgorithms configuration on the remote host may have disabled ssh-rsa, only accepting more secure algorithms such as rsa-sha2-256 or rsa-sha2-512.

To check my remote Linux host’s OpenSSH version, I ran:

$ sshd -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024

It turned out to be OpenSSH 9.6.

This version of OpenSSH supports more secure public/private key pairs generated with the ECDSA (Elliptic Curve Digital Signature Algorithm). To fix the issue with XShell, I decided to regenerate a new key pair using the ECDSA algorithm. XShell provides a “New User Key Generation Wizard” under the “Tools (T)” menu to do this.

Alternative Solution: Allow ssh-rsa Algorithm (if the remote host allows it)

If you have control over the remote host, you can allow the ssh-rsa algorithm by modifying the SSH configuration file /etc/ssh/sshd_config on the remote host. Here’s how you can do it:

1 Open the SSH configuration file:

sudo vim /etc/ssh/sshd_config

2 Find and add (or modify) the following line to allow ssh-rsa:

PubkeyAcceptedAlgorithms +ssh-rsa

3 Restart the SSH service:

sudo systemctl restart ssh

If you’re using CentOS, restart sshd instead:

sudo systemctl restart sshd

Other Causes for the Error “The Selected User Key is Not Registered on the Remote Host” or “Server Refused the User Key”

1 Incorrect directory or file permissions: Ensure that the permissions for the .ssh directory and the authorized_keys file are set correctly:

chmod 700 .ssh
chmod 600 .ssh/authorized_keys

Also, ensure that authorized_keys is owned by the correct user:

chown ubuntu:ubuntu .ssh/authorized_keys

2 Incorrect key: Make sure the authorized_keys file on the server contains the public key (usually ending with .pub), not the private key.

3 SSH key authentication not enabled: The configuration file /etc/ssh/sshd_config should have the following line and it should not be commented out:

PubkeyAuthentication yes

4 Username and key mismatch: If the key is in /home/debian/.ssh/ (for the debian user), but you’re trying to log in as ubuntu, authentication will fail.

5 Root login is disabled: If /etc/ssh/sshd_config has PermitRootLogin no, you won’t be able to log in as root.

6 SELinux is enabled: Run getenforce to check the status of SELinux. The status should be Permissive, not Enforcing. Temporarily disable SELinux with:

setenforce 0

To permanently disable SELinux, edit the /etc/sysconfig/selinux file and change SELINUX=enforcing to SELINUX=disabled.

7 Incorrect authorized_keys filename: If the line in /etc/ssh/sshd_config is:

# AuthorizedKeysFile .ssh/authorized_keys

but your .ssh directory contains a file named authorized_key, you should rename it to authorized_keys.

XShell使用私钥文件ssh登录远程Linux主机报错“所选的用户秘钥未在远程主机上注册,请再试一次”的解决方法

我的远程Linux主机的操作系统是Ubuntu 24。

按照网上的教程,我在Git Bash上使用私钥文件成功ssh登录远程Linux主机,命令如下所示:

$ ssh [email protected] -i .ssh/id_rsa

但是使用同样的命令和私钥文件,却无法在XShell上ssh登录远程Linux主机,报错“所选的用户秘钥未在远程主机上注册。请再试一次”。

查看ssh的日志文件/var/log/auth.log,我发现如下信息:

userauth_pubkey: signature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

这表明远程主机的 SSH 服务在进行公钥认证时,发现客户端使用的公钥签名算法是 ssh-rsa,但是在远程主机的配置中,ssh-rsa算法被禁用了,因此认证失败。

在Git Bash 中使用私钥可以登录成功,可能是因为 Git Bash 使用的是较新的 OpenSSH 客户端版本,并能够使用备用的签名算法(如 rsa-sha2-256 或 rsa-sha2-512)。但是在 XShell 中,可能由于其默认配置或旧版本的客户端,它仍然依赖于 ssh-rsa 签名算法进行身份验证,导致认证失败。

从 OpenSSH 8.8 开始,ssh-rsa 算法被视为不再安全,部分服务器配置(例如Ubuntu 24)默认禁用了该算法。在远程主机的 SSH 服务中,可能已经通过 PubkeyAcceptedAlgorithms 配置来禁用 ssh-rsa 算法,而只接受更安全的算法,例如 rsa-sha2-256 或 rsa-sha2-512。 查看我的远程Linux主机的OpenSSH版本:

$ sshd -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024

发现是OpenSSH 9.6版本。

OpenSSH 9.6版本支持更安全的ECDSA(Elliptic Curve Digital Signature Algorithm) 算法生成的公钥和私钥。因此我解决XShell问题的方法是,使用ECDSA算法重新生成一对公钥和私钥,可以使用XShell的“工具(T)”->“新建用户秘钥生成向导”来做到:

另一个解决方案是,允许 ssh-rsa 算法(如果远程主机允许)。如果你有对远程主机的控制权,可以通过修改远程主机的 SSH 配置文件 /etc/ssh/sshd_config 来允许 ssh-rsa 算法。打开 /etc/ssh/sshd_config 文件:

sudo vim /etc/ssh/sshd_config

查找并添加(或修改)以下行,允许 ssh-rsa 算法:

PubkeyAcceptedAlgorithms +ssh-rsa

重启 SSH 服务:

sudo systemctl restart ssh

# 如果你的系统是CentOS

sudo systemctl restart sshd

其他会引起“所选的用户秘钥未在远程主机上注册。请再试一次”或“服务器拒绝了用户密钥”问题的原因还有:

1 没有正确设置目录和文件的权限:

chmod 700 .ssh

chmod 600 .ssh/authorized_keys

并且authorized_keys文件要归属于用户组,例如:

chown ubuntu:ubuntu .ssh/uthorized_keys

2 密钥错误:服务器上的 authorized_keys 保存的应是公钥(一般以.pub作为文件后缀名),而不是私钥。

3 未开启密钥验证:/etc/ssh/sshd_config这个配置文件中应有 PubkeyAuthentication yes 这一行,且没有被注释掉

4 用户名和密钥不匹配:假设密钥是放在 /home/debian/.ssh/ 下(即用户是 debian),但是登录的用户名却使用ubuntu

5 root用户名被禁止登陆:假设etc/ssh/sshd_config 配置了 PermitRootLogin no,却用 root 账户来登录

6 开启了SELinux:使用getenforce命令查看SELinux的状态,状态应该是Permissive,不能是 Enforcing。临时关闭SELinux:

setenforce 0

永久关闭SELinux的方法是:编辑/etc/sysconfig/selinux配置文件,把其中的 SELINUX=enforcing 替换为 SELINUX=disabled

7 SSH 配置文件/etc/ssh/sshd_config中有这么一行:

# AuthorizedKeysFile      .ssh/authorized_keys

而你的.ssh目录下的对应文件的名字却是authorized_key,应该是authorized_keys。