【发布时间】:2017-07-06 05:27:31
【问题描述】:
我正在做一个项目,我在 C++ 中使用 libssh2 将端口转发到 MySQL。我已经让它用于用户名/密码身份验证,但我现在想使用公钥/私钥身份验证。 libssh2 的文档很差,所以我很难弄清楚我需要做什么。
我要做的是让一个 Android 应用程序将数据发布到我的 C++ 应用程序,其中 C++ 将获得 SSH 详细信息以及身份验证密钥,并创建 SSH 隧道。 C++ 正在获取密钥,然后我正在执行以下操作来进行公钥身份验证。
else if (this->getAuthMethod() == SupportedAuthMethods::AUTH_PUBLICKEY)
{
string test = this->getSSHPrivateKey();
boost::replace_all(test, "\n", "");
unsigned char * key = (unsigned char *)test.c_str();
size_t sizeofkey = strlen((char*)key);
cout << key << endl;
stringstream logstream;
logstream << "Using public key authentication for SSH Host: " << this->getSSHHostnameOrIPAddress();
this->bitsLibrary->writeToLog(logstream.str(), "SSHTunnelForwarder", "authenticateSSHServer");
if (chosenAuthMethod & SupportedAuthMethods::AUTH_PUBLICKEY)
{
//int result = 0;
int result = libssh2_userauth_publickey(this->session, this->getUsername().c_str(), key, sizeofkey, SSHTunnelForwarder::publicKeyAuthComplete, 0);
if (result != 0)
{
char * error = NULL;
int len = 0;
int errbuf = 0;
libssh2_session_last_error(this->session, &error, &len, errbuf);
this->bitsLibrary->writeToLog(std::string(error), "SSHTunnelForwarder", "auth");
JSONResponseGenerator jsonResponse;
jsonResponse.generateJSONResponse(API_AUTH_FAILURE, "InvalidPublicKey");
return jsonResponse.getJSONString();
}
}
}
我在某处读到它不应该有新行,这就是为什么我将 \n 替换为空白字符,但不管有没有这个都没有区别。
非常基本的文档提到libssh2_userauth_publickey 的参数之一是如下回调:
int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract);
但是我在任何地方都找不到关于这个回调是什么或它应该包含什么的任何信息。在我对 libssh2_userauth_publickey 的函数调用中,我传入了SSHTunnelForwarder::publicKeyAuthComplete,目前这个函数只有以下内容:
int SSHTunnelForwarder::publicKeyAuthComplete(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract)
{
cout << "In SSH Auth Callback" << endl;
return 0;
}
上面的这个方法没有被调用,虽然我预计这甚至不接近正确。
当我在上面运行我的代码时,libssh2_userauth_publickey 的结果是 19,而从 get_last_message() 方法返回的错误是 invalid public key。我知道公钥文件很好,因为我可以在 Android 上的 SSH 应用程序中使用它,并且可以成功地通过我的服务器进行身份验证。
更新 1
我已经取得了一些进展,我发现有一个函数叫做:
libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session, const char *username, size_t username_len, const char *publickeyfiledata, size_t publickeyfiledata_len, const char *privatekeyfiledata, size_t privatekeyfiledata_len, const char *passphrase);
我拥有的 libssh2 版本来自 NuGet 包管理器,发现其中的最新版本实际上很旧,所以我在 Visual Studio 中从 GitHub 构建了最新的 1.7.0 版本,并将我的项目重新链接到这个新版本版本。
我现在已经用这个版本替换了原来使用的 publickey auth 函数,所以我的代码现在看起来像这样:
int result = libssh2_userauth_publickey_frommemory(this->session, username.c_str(), username.length(), nullptr, 0, test.c_str(), sizeofkey, nullptr);
这个函数让我有点困惑,它需要公钥和私钥,因为我所知道的关于 SSH 的一切(当然不是很多)公钥都保留在服务器上,并且想要登录的用户只能访问到私钥。
我发现其他人在问这个问题,并且已经完成了一个补丁以允许公钥的空指针,所以我为公钥传递了 nullptr,为公钥长度传递了 0。我还为证书密码设置了一个 nullptr,因为它尚未设置。
当我现在运行此代码时,我现在得到错误 -18,即 invalid username/public key combination。不过,我知道我使用的用户名和私钥文件是正确的,因为我可以在 Android 上的 SSH 客户端应用程序中使用它来连接到我的 SSH 服务器。
【问题讨论】:
标签: c++ ssh private-key public-key libssh2