You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否仅通过公钥检测SSH服务器是否接受对应私钥?

仅通过SSH公钥检测服务器是否信任对应私钥的实现方法

是的,完全可以仅通过公钥判断远程SSH服务器是否接受对应的私钥,无需持有私钥本身。这利用了SSH公钥认证的试探阶段——服务器会先验证客户端提供的公钥是否在授权列表中,只有公钥被信任时,才会要求客户端用对应私钥完成签名验证。

原理说明

从你提供的ssh -vvv输出就能看到关键流程:

debug1: Offering public key: /Users/opera_user/.ssh/id_rsa RSA SHA256:bZ2lxtUybH426ogDCGzZ3/HzbYaIsZ3rC69jgXBa3Ig
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 60
debug1: Server accepts key: /Users/opera_user/.ssh/id_rsa RSA SHA256:bZ2lxtUybH426ogDCGzZ3/HzbYaIsZ3rC69jgXBa3Ig

这里的type 50是客户端发送的公钥试探包,包含公钥信息;服务器返回的type 60表示"公钥已被信任,请继续签名验证"——这就足以证明服务器信任该公钥对应的私钥,不需要完成后续签名步骤。

程序化实现方式

1. 用OpenSSH客户端命令快速检测

直接调用ssh命令,限定仅尝试公钥认证且不要求输入密码/签名:

ssh -o PubkeyAuthentication=yes -o PreferredAuthentications=publickey -o BatchMode=yes -o ConnectTimeout=5 user@server -i /path/to/public_key_file
  • 若服务器信任该公钥,命令会返回Permission denied (publickey)(因无钥匙完成签名);
  • 若公钥不被信任,会返回Permission denied并附带其他认证方式(如password),或直接跳过公钥认证。

2. 用SSH库手动处理协议包(以Python的paramiko为例)

通过库直接构造公钥试探包,解析服务器响应:

import paramiko

def check_public_key_trusted(hostname, username, public_key_path):
    # 加载公钥文件
    with open(public_key_path, 'r') as f:
        pub_key_content = f.read().strip()
        # 从公钥字符串解析出密钥对象
        key_type, key_data, _ = pub_key_content.split()
        if key_type == 'ssh-rsa':
            pub_key = paramiko.RSAKey(data=paramiko.util.base64_decode(key_data))
        elif key_type == 'ecdsa-sha2-nistp256':
            pub_key = paramiko.ECDSAKey(data=paramiko.util.base64_decode(key_data))
        else:
            raise ValueError(f"Unsupported key type: {key_type}")

    transport = None
    try:
        transport = paramiko.Transport((hostname, 22))
        transport.start_client()
        # 触发认证流程,先尝试无密码认证(仅为进入认证阶段)
        try:
            transport.auth_none(username)
        except paramiko.SSHException:
            pass
        # 发送公钥试探
        transport.auth_publickey(username, pub_key)
    except paramiko.SSHException as e:
        # 抛出"signature required"说明公钥被信任,等待签名;其他异常则是公钥不被认可
        return "signature required" in str(e)
    finally:
        if transport:
            transport.close()

当服务器信任公钥时,auth_publickey会抛出含"signature required"的异常,代表服务器已认可该公钥;若公钥不被信任,则会抛出"publickey authentication failed"类异常。

注意事项

  • 扫描前确认符合服务器管理规范,避免触发IDS告警;
  • 设置短连接超时,提升批量扫描效率;
  • 控制并发数,避免对目标服务器造成压力。

内容的提问来源于stack exchange,提问作者anon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:17:13