我正在尝试为 libssh2 库中的 sftp_write 示例传递公钥(id_rsa.pub)。
const char *pubkey = "/home/username/.ssh/id_rsa.pub";
const char *privkey = NULL;
if(libssh2_userauth_publickey_fromfile(session, username,
pubkey, privkey,
password)) {
fprintf(stderr, "\tAuthentication by public key failed\n");
goto shutdown;
}
我尝试过 openssh 格式和标准 ssh 格式密钥,如下所示。
我收到以下两种格式的错误
标准 ssh 格式,
Athentication failed: cannot open the file -16
---- BEGIN SSH2 PUBLIC KEY ---- AAAAB3NzaC1yc2EAAAADAQABAAABAQCjnPF5vKg7NuUXkGbK0Nh5d3GjLNXHB+VozgVn5Ego DVSjwezr30YJm8gzGrk5aUAEJKbWSUczVj9vCrn7O54K1/VXOggC1a6pun3+Iqvuv0BINRj3 YuC+c9s803mYPSpzZpNPFf3Uj49lKrroUIdnEz3qo/Z9kFbpWfClJPlb7xjrZaZkSgolbxih 8gZ0w3iAuMR5nwnEGQnHkk751jxOtYopzT4w31gFmFYcq/LRbP4S2xJ0r8wl58J8Mm/U/yZx EhDARHx/mkqMILofAqFvsFSaaASUuFmB9uUJsgJ69s9FbgXnpGhyGoH0nyVsdM/oqwIXtJji IvbVBEomnCrX ---- END SSH2 PUBLIC KEY ----
开放SSH格式,认证失败
LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED \ LIBSSH2_ERROR_AUTHENTICATION_FAILED ,-18
"ssh-rsa" AAAAB3NzaC1yc2EAAAADAQABAAABAQCjnPF5vKg7NuUXkGbK0Nh5d3GjLNXHB+VozgVn5EgoDVSjwezr30YJm8gzGrk5aUAEJKbWSUczVj9vCrn7O54K1/VXOggC1a6pun3+Iqvuv0BINRj3YuC+c9s803mYPSpzZpNPFf3Uj49lKrroUIdnEz3qo/Z9kFbpWfClJPlb7xjrZaZkSgolbxih8gZ0w3iAuMR5nwnEGQnHkk751jxOtYopzT4w31gFmFYcq/LRbP4S2xJ0r8wl58J8Mm/U/yZxEhDARHx/mkqMILofAqFvsFSaaASUuFmB9uUJsgJ69s9FbgXnpGhyGoH0nyVsdM/oqwIXtJjiIvbVBEomnCrX
有人可以建议是否是公钥格式问题。
我在 Windows 上使用 Bitvise 服务器来测试 libssh2 客户端公钥身份验证。
答案1
看来您没有将私钥传递给 libssh2。
SSH pubkey 身份验证需要两台机器,服务器和客户端。客户端应生成私钥和公钥对,其中应在尝试进行 pubkey 身份验证之前使用任何可用的方法将公钥复制到服务器。私钥不应离开客户端。
当使用客户端连接到服务器时,应该使用私钥。仅使用公钥进行身份验证是行不通的,因为您只能加密协商数据包,而不能真正解密它们。阅读通过文档还指出私钥是必须的,而公钥在某些情况下可能设置为 NULL。
重现问题
我已经尝试重现该错误,但它似乎对我有用,下面我将描述我是如何做到的,以及关于您的问题的一些猜测:
- 创建一个目录并复制到示例文件
sftp_write.c
中libssh2。 - 在第 27 行更改
auth_pw
为。1
0
- 将 pubkey 和 privkey 更改为使用我自己的密钥,并添加了调试。
const char *pubkey = "/home/user/.ssh/id_rsa_PEM.pub";
const char *privkey = "/home/user/.ssh/id_rsa_PEM";
int liberr;
if(liberr = libssh2_userauth_publickey_fromfile(session, username,
pubkey, privkey,
password)) {
fprintf(stderr, "\tAuthentication by public key failed: %d\n", liberr);
goto shutdown;
}
- 改变了
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
到
#include <libssh2.h>
#include <libssh2_sftp.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
为了匹配我的设置。
- 使用Docker来编译镜像,运行
docker run -i --rm \
-w $(pwd) -v $(pwd):$(pwd) \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
-u $(id -u):$(id -u) \
datafr/libssh2:latest \
gcc -g -I /usr/include/ -L /usr/lib/ -l ssh2 sftp_write.c -o a.out
- 运行程序
./a.out 127.0.0.1 $USER
结果
运行此代码会导致错误 -19: LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED
。这是因为 docker 映像使用旧版本的 libssh2,需要旧的 PEM 密钥。这是通过创建一个新的密钥对来解决的
ssh-keygen -m PEM -t rsa -P "" -f id_rsa_PEM
并修改代码以使用新密钥。
再次运行代码会出现错误 -18: LIBSSH2_ERROR_AUTHENTICATION_FAILED
。通过将新的公钥添加id_rsa_PEM.pub
到服务器authorized_keys
文件中可以解决此问题。
之后,我们不再收到错误,输出如下所示:
$ ./a.out 127.0.0.1 $USER
Fingerprint: XXXXXXX
libssh2_sftp_init()!
libssh2_sftp_open()!
libssh2_sftp_open() is done, now send data!
all done
我可以确认创建了一个名为的文件,/tmp/TEST
其中包含我们的代码sftp_write.c
。
进一步猜测
我注意到LIBSSH2_ERROR_FILE
当文件不存在或权限错误时会出现错误 -16: ,因此我会要求您仔细检查您的文件权限。我将发布我自己的权限作为参考。
客户端~/.ssh/
目录:
$ ls -alh
total 28K
drwx------ 2 user user 4,0K Sep 28 15:37 .
drwxr-xr-x 32 user user 4,0K Sep 28 15:36 ..
-rw-rw-r-- 1 user user 2,7K Sep 28 15:36 config
-rw------- 1 user user 2,5K Sep 28 15:36 id_rsa_PEM
-rw-r--r-- 1 user user 574 Sep 28 15:36 id_rsa_PEM.pub
-rw------- 1 user user 6,3K Sep 28 15:36 known_hosts
服务器~/.ssh/
目录:
$ ls -alh
total 20K
drwx------ 2 user user 4,0K Sep 28 15:39 .
drwxr-xr-x 32 user user 4,0K Sep 28 15:39 ..
-rw------- 1 user user 3,4K Sep 28 15:39 authorized_keys