☰
curl `--pubkey` 选项详解:为 SFTP/SCP 显式指定 SSH 公钥文件
2026/10/15 4:06:03 网站建设 项目流程

curl--pubkey选项详解:为 SFTP/SCP 显式指定 SSH 公钥文件

【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl

导读

--pubkey是 curl 命令行工具中用于 SFTP、SCP 协议的 SSH 公钥认证选项,它允许你显式指定存放 SSH 公钥的文件路径,与--key(私钥文件)搭配组成一套完整的公钥认证方案。读完本文,你将掌握--pubkey的语法、默认行为(公钥自动提取机制)、与--key/--pass等选项的配合方式,以及 curl 底层在 libssh2/libssh 两个 SSH 后端中如何使用该公钥文件完成认证的完整调用链。

--pubkey基本用法

选项元信息

该选项定义于 docs/cmdline-opts/pubkey.md,其 front matter 中记录了完整的选项属性:

属性值
Long 名称--pubkey
参数<key>(公钥文件名)
适用协议SFTP、SCP
帮助文本SSH Public key filename
分类sftp、scp、ssh、auth
引入版本7.16.2
Multisingle(选项只能出现一次)

官方示例为:

curl --pubkey file.pub sftp://example.com/

命令行基本用法

--pubkey需要一个公钥文件名作为参数,典型用法是与--key一起使用:

# 显式指定私钥与公钥文件进行 SFTP 上传 curl --key ~/.ssh/id_ed25519 --pubkey ~/.ssh/id_ed25519.pub \ -u username: sftp://example.com/path/to/file # SCP 下载场景 curl --key ./client_key --pubkey ./client_key.pub \ -u username: scp://example.com/remote/path/file

参数解析在 src/tool_getparam.c 中完成,随后存储到配置结构体config->pubkey字段(见 src/tool_cfgable.h)。

关键行为:公钥的自动提取

文档明确指出:curl 会尝试自动从私钥文件中提取公钥,因此通常不需要显式传递--pubkey。

这一行为在源码 lib/vssh/vssh.c 中有明确实现注释:

"Unless the user explicitly specifies a public key file, let the SSH library extract the public key from the private key file. This is done by passing sshc->pub_key = NULL."

即:只有当用户显式指定公钥文件时,sshc->pub_key才会被设置为该文件路径;否则保持为 NULL,交由底层 SSH 库从私钥中自行推导公钥。

提取的前提条件

自动提取存在一个硬性前提(文档原文):该功能要求 libcurl 在编译时链接的 libssh2 版本为 1.2.8 或更高,且该 libssh2 自身必须链接了 OpenSSL。该能力自 curl 7.39.0 起提供。

也就是说:

  • libssh2 >= 1.2.8 且链接 OpenSSL:公钥可以从私钥文件自动推导,--pubkey通常可以省略;
  • libssh2 更老版本或未链接 OpenSSL:必须显式给出--pubkey公钥文件,否则公钥认证可能失败。

与其他 SSH 选项的配合

--pubkey通常与以下选项搭配使用,构成完整的 SSH 认证参数集:

选项作用文档
--key <key>指定私钥文件名。未指定时 curl 依次尝试~/.ssh/id_rsa、~/.ssh/id_dsa、./id_rsa、./id_dsakey.md
--pass <phrase>私钥口令(passphrase)pass.md
--pubkey <key>指定公钥文件名(本文主题)pubkey.md
--user <user:password>指定 SSH 用户名(认证时以该用户身份进行)user.md

注意--key同时适用于 TLS 与 SSH(SCP/SFTP),而--pubkey仅适用于 SSH 场景。

私钥的默认查找路径

与--pubkey配对的私钥默认查找逻辑在 lib/vssh/vssh.c 中实现:当用户未通过--key/CURLOPT_SSH_PRIVATE_KEYFILE指定私钥时,curl 依次探测$HOME/.ssh/id_rsa、$HOME/.ssh/id_dsa,随后尝试当前目录下的id_rsa、id_dsa,全部不存在则以空字符串兜底。

libcurl 编程接口:CURLOPT_SSH_PUBLIC_KEYFILE

--pubkey在 libcurl 层面对应CURLOPT_SSH_PUBLIC_KEYFILE选项,其语义(见 lib/setopt.c 注释)为:

"Use this file instead of the $HOME/.ssh/id_dsa.pub file"

即用指定文件替代默认的$HOME/.ssh/id_dsa.pub。该选项在 lib/easyoptions.c 中被注册为字符串类型(CURLOT_STRING)。

命令行工具与 libcurl 的对接发生在 src/config2setopts.c:

/* SSH and SSL private key uses same command-line option */ MY_SETOPT_STR(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); MY_SETOPT_STR(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);

在 C 程序中对应的用法为:

#include <curl/curl.h> int main(void) { CURL *curl = curl_easy_init(); if(!curl) return 1; curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/path/file"); curl_easy_setopt(curl, CURLOPT_USERNAME, "username"); curl_easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "/home/user/.ssh/id_ed25519"); curl_easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "/home/user/.ssh/id_ed25519.pub"); curl_easy_perform(curl); curl_easy_cleanup(curl); return 0; }

源码级原理:公钥认证的底层调用链

密钥文件的准备阶段

Curl_ssh_setup_pkey()(lib/vssh/vssh.c)是整个认证准备的核心函数:

  1. 检查ssh_auth_types中是否启用了CURLSSH_AUTH_PUBLICKEY公钥认证方式;
  2. 解析私钥:优先使用CURLOPT_SSH_PRIVATE_KEYFILE指定文件,否则按上文默认路径探测;
  3. 解析公钥:读取CURLOPT_SSH_PUBLIC_KEYFILE(即--pubkey的值);若为空字符串则视同 NULL,交由 SSH 库自动提取;
  4. 设置口令passphrase(来自--pass或CURLOPT_KEYPASSWD);
  5. 通过infof()输出调试信息,例如SSH: public key file 'xxx',可在-v详细模式下观察到。

libssh2 后端的认证调用

在 libssh2 后端(lib/vssh/libssh2.c),认证最终由libssh2_userauth_publickey_fromfile_ex()完成,该调用同时传入用户名、公钥文件路径、私钥文件路径与口令:

rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, user, curlx_uztoui(strlen(user)), sshc->pub_key, sshc->priv_key, sshc->passphrase);

其中sshc->pub_key为 NULL 时,libssh2 会尝试从私钥中提取公钥——这正是文档所述"自动提取"机制的落地处。返回LIBSSH2_ERROR_EAGAIN时表示需重试(非阻塞场景)。

libssh 后端的对应实现

若 curl 以 libssh 为 SSH 后端,认证流程位于 lib/vssh/libssh.c,其主机公钥校验部分使用ssh_get_server_publickey()获取服务器公钥,再与 known hosts 中的条目比对。

测试用例佐证

仓库测试数据中可看到--pubkey的实际使用样例(这些测试依赖本地 SSH 测试服务器,路径中的%LOGDIR、%HOSTIP等为测试框架变量):

  • tests/data/test1446:SFTP 结合--remote-time,同时指定--key与--pubkey;
  • tests/data/test1583:SFTP 目录与空文件操作,两次请求均使用--key/--pubkey;
  • tests/data/test1725:SCP 主机密钥错误场景,配合--hostpubmd5与--pubkey验证失败路径。

这些测试证明:显式提供公钥文件(如curl_client_key.pub)与私钥文件配对,是 SFTP/SCP 功能回归测试的标准配置方式。

使用建议与注意事项

  1. 优先省略--pubkey:在满足 libssh2 >= 1.2.8 + OpenSSL 的构建条件下,直接省略该选项让 curl 自动提取公钥更省事;
  2. 显式指定的场景:公钥与私钥分离存储、公钥位于非标准路径、或使用的 libssh2 不支持自动提取时,必须显式传--pubkey;
  3. 文件格式:公钥文件应为 OpenSSH 格式(如ssh-ed25519 AAAA...、ssh-rsa AAAA...),即通常ssh-keygen生成的.pub文件;
  4. 权限问题:认证失败时可用-v查看SSH: public key file '...'与SSH: private key file '...'调试输出,确认 curl 实际读取的密钥路径是否正确;
  5. 选项唯一性:--pubkey为 single 类型,命令行中只能出现一次。

【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询