c - 为什么 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-Type
(DEK-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);
解决方案
推荐阅读
- javascript - 我的 Vuex 表单获得了第一个字段,但没有获得第二个字段,静默失败
- sql - 如何在 SQL 中应用带有问号符号的 liquibase 变更集
- oop - 如果正则表达式是方法,它们对应于哪个类?
- nginx - nginx 431 请求标头字段太大
- django - 我没有看到任何语法错误,但我不断收到 ModelForm has no model class specified
- python - 如何修复 TypeError:“类型”对象不可下标
- html - 我的图像从我的 div 列中流出。我如何修复它并使图像全尺寸变成 div
- postgresql - 如何将用户输入与模棱两可的城市名称相匹配?
- google-api - 在 File.get 中使用 * 作为文件 ID 来获取所有文件。导致错误
- javascript - 向下滚动时水平显示图像