无法使用libcurl访问需要客户端身份验证的站点

问题描述 投票:0回答:4

我使用下面的片段来设置客户端身份验证的证书和密钥。

  curl_easy_setopt(curl,CURLOPT_SSLCERT,"clientCert.pem");
  curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
  curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
  curl_easy_setopt(curl,CURLOPT_SSLKEY,"privateKey.pem");
  curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,"changeit");
  curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");

证书没有密码,我不知道为什么存在 SSLCERTPASSWD 选项,我只是提供了一个虚拟值。 当我在 Linux 上运行该程序时,我收到错误代码 58 和错误消息 无法设置私钥文件:“privateKey.pem”类型 PEM

但是在 Windows 上我得到 无法使用客户端证书(未找到密钥或密码短语错误?)

似乎提示证书和密钥不匹配,但我不知道怎么办。我已使用 openssl 命令从 p12 文件中提取了证书和密钥。 我用来提取密钥的命令是

openssl.exe pkcs12 -in client.p12 -nocerts -out privateKey.pem

用于提取证书的命令是

openssl.exe pkcs12 -in client.p12 -nokeys -out clientCert.pem

p12文件已成功在浏览器中访问客户端认证url。 在我开枪自杀之前请帮忙。

编辑: 这是私钥和证书相互对应的证明:

[debugbld@nagara ~/curlm]$ openssl x509 -noout -modulus -in clientCert.pem | openssl md5
d7207cf82b771251471672dd54c59927

[debugbld@nagara ~/curlm]$ openssl rsa -noout -modulus -in privateKey.pem | openssl md5
Enter pass phrase for privateKey.pem:
d7207cf82b771251471672dd54c59927

那为什么行不通呢?

authentication curl client
4个回答
3
投票

使用命令行curl,我使用也使用openssl从p12文件获取的.pem文件遇到了同样的错误,当在浏览器中导入时,p12也能够正常工作进行客户端身份验证。我想就像你描述的那样。

我的问题是由于 .pem 文件未按正确的顺序列出证书而引起的:似乎文件中的每个证书都必须后跟其颁发者证书。 我编辑了文件并更改了各部分的顺序,curl 很高兴

郑重声明,我的原始 .p12 文件是通过从 Firefox 备份证书获得的。

另请注意,就我而言,我没有收到输入密码的提示,而是得到了

curl: (58) unable to set private key file: 'alice.pem' type PEM

在密码提示之前


3
投票

我遇到了类似的问题,我发现问题与证书和私钥文件的文件权限有关。运行 PHP 的进程没有对这些文件的读取权限。

您可以尝试的一件事(这帮助我解决了这个问题)是运行以下代码:

$result=openssl_get_privatekey('file://path/to/private/key.pem','password');

并检查返回值是否不为 false 并且没有错误。我得到:

file_get_contents(/path/to/private/key.pem): failed to open stream: Permission denied

0
投票

感谢 Hugh 的帖子和 raugfer 的 openssl 提示。后者:既有帮助,也有误导性。 ;-)

实际上,我通过确保密钥文件的路径正确来解决问题。这就是为什么 openssl 提示具有误导性,尽管它帮助我检查我的 PEM 文件是否正常:

cURL 需要完整路径,但不带“file://”前缀。虽然 fopen 对相对路径感到满意,但 cURL 却不满意。因此,我打开密钥文件的所有测试都成功,而 cURL 则失败了。

顺便说一句:

curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");

不需要,因为密码仅用于解密私钥,PEM 是默认值。


0
投票

$result=openssl_get_privatekey('file://path/to/private/key.pem','密码');

unix 绝对路径的格式为 (file:///path/to/private/key.pem',....(三个斜杠)

Windows 的格式为 ('file://C:\path o\private\key.pem',....

© www.soinside.com 2019 - 2024. All rights reserved.