我正在使用libssh2
使网络程序更安全。
我希望我的程序以尽可能类似于OpenSSH客户端ssh(1)的方式进行身份验证。 OpenSSH客户端只会询问服务器实际接受的密钥的密码短语。
据我了解this link,ssh客户端发送使用公钥的请求,如果接受,则可以使用密码解锁私钥。
libssh2提供了一个函数libssh2_userauth_publickey_fromfile
,它接受私钥和公钥文件名以及密码。使用此函数非常简单,但这意味着我必须获取私钥的密码,即使服务器首先没有接受公钥。对于拥有大量不同密钥的用户来说,这显然是个问题(我的程序当前遍历〜/ .ssh目录中的密钥文件)。
我已经尝试阅读libssh2
函数的手册页,如果没有更详细的ssh协议知识,大多数函数看起来都太简短了。实际上some of them甚至还没有写过。
有人能告诉我如何只提示使用libssh2
ssh服务器实际接受的密钥的密码短语吗?
答案 0 :(得分:3)
在RTFM并进行一些测试之后,我发现libssh2_userauth_publickey_fromfile
将返回不同的错误代码,具体取决于服务器是否接受密钥,或密码短语是否错误。
所以,这是一个非常低效的解决方案(因为它调用libssh2_userauth_publickey_fromfile
,因此协议的所有密钥交换部分至少两次)。
int nAttempts = 3; // number of attempts the user gets at entering the passphrase
// Try authenticating with an empty passphrase
int err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,"");
if (err == 0)
{
fprintf(stderr, "You shouldn't use keys with an empty passphrase!\n");
}
else if (err == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED)
{
// if we get here it means the public key was initially accepted
// but the private key has a non-empty passphrase
char p[BUFSIZ];
for (int i = 0; i < nAttempts; ++i)
{
get_passphrase(p); // assume this gets the passphrase
err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,p);
if (err != LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) break;
}
}
if (err != 0)
{
fprintf(stderr, "Authentication using key %s failed!\n", priv);
}
为了完整性,get_passphrase
函数使用this question解决方案来提示用户输入密码。