首页 > 解决方案 > 为什么 curl 无法使用受密码保护的密钥?

问题描述

当我在客户端密钥上有密码时,Curl SSL 连接失败

我正在尝试发出 https POST 请求,客户端使用适当的证书和私钥向远程系统进行身份验证

在下面的代码中,如果 'pathToAuthKey' 指的是非密码保护的密钥,则一切正常。没有错误。没有警告。连接已建立,一切正常。

如果“pathToAuthKey”指的是相同的密钥但受密码保护,并且我通过“authKeyPwd”字符串提供密码,我会从 Curl 得到以下响应;-

* About to connect() to 10.10.4.71 port 443 (#1)
*   Trying 10.10.4.71...
* Connected to 10.10.4.71 (10.10.4.71) port 443 (#1)
* unable to load client key: -8178 (SEC_ERROR_BAD_KEY)
* NSS error -8178 (SEC_ERROR_BAD_KEY)
* Peer's public key is invalid.
* Closing connection 1

从本质上讲,Curl 似乎要么忽略了我给它的密码,要么它无法使用指定的密码解密密钥,原因不明。我给 Curl 的密码字符串就是这样;只是原始密码,所以是“abcde”,而不是像“pass:abcde”这样的东西(尽管我尝试了各种组合)

如果我使用命令行,我会得到相同的错误响应(尽管我不确定我在这里是否正确指定了密码);-

curl -k -v --cert ./.ssh/authCert.pem --key --pass abcde ./.ssh/authKey.pem https://10.10.4.71/

...或者 (?)...

curl -k -v --cert ./.ssh/authCert.pem --key ./.ssh/authKey.pem:abcde https://10.10.4.71/

密钥和证书采用 PEM 格式。我在某处读到他们应该包含与 Curl 一起使用的“包”信息。我试过有无 - 没有区别。我还尝试了以下代码的许多变体(以不同的顺序做事,尝试其他选项等),但没有运气

我从带有----BEGIN ENCRYPTED PRIVATE KEY-----标题的关键 PEM 格式开始,但在某个地方读到 Curl 不喜欢这样,所以将其更改为-----BEGIN RSA PRIVATE KEY-----. 我已经尝试了带有和不带有 and 信息的密钥 PEM 文件Proc-TypeDEK-Info尽管我看不到 SSL 如何在没有此信息的情况下解码密钥,除非它只是尝试所有组合直到它成功),即 -

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,FD47E79520E2C2A1E3B5D9B769C713A9

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .......etc.....
-----END RSA PRIVATE KEY-----

我尝试将密钥与证书文件结合起来。

证书是自签名的(尽管我看不出这会如何影响(缺少)密码成功)

最后一件事 - 我已经看到了CURLOPT_KEYPASSWD名为CURLOPT_SSLKEYPASSWD. 两种我都试过了,Curl好像都接受了,但是不知道有没有区别(官方文档没有提到后一种形式)

这是在 Centos 6 机器上。卷曲版...

curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.36 zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp 
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets

任何帮助将不胜感激

这是我的 C 代码;-

curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl"); // Identify ourselves

// Set up timeout handler
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, curlTimeoutCallback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &transferStartTime);

// Set up the response handler
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlResponseCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

// Create HTTP request data
char postData[MAX_JSON_POST_LEN] = {"My POST data"};
int postLen = strlen(postData);

// Construct URL to send request to
char url[] = {"https://10.10.4.71/"};
curl_easy_setopt(curl, CURLOPT_URL, url);

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); // ###

curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, pathToAuthCert);

curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLKEY, pathToAuthKey);

if (*authKeyPwd)
{
    curl_easy_setopt(curl, CURLOPT_KEYPASSWD, authKeyPwd);
}

// Try and simplify things for now by disabling verification of the remote system
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

// Send request
clock_gettime(CLOCK_MONOTONIC, &transferStartTime);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postLen);

CURLcode curlResp = curl_easy_perform(curl);

标签: csslcurlhttpslibcurl

解决方案


推荐阅读