如果不使用系统中的证书,则无法将curl中的公钥固定 [英] Public key pinning in curl does not work without using certificates from the system

查看:73
本文介绍了如果不使用系统中的证书,则无法将curl中的公钥固定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将libcurl与公钥固定一起使用,以便在下载文件时验证服务器的真实性.

I am trying to use libcurl with public-key pinning in order to verify a server's authenticity when downloading a file.

Curl被编译,因此它不使用系统上的任何证书,而仅依赖于它从用户那里收到的证书:

Curl is compiled so that it doesn't use any certificates on the system, but only relies on certificates it receives from the user:

./configure --without-ca-bundle --without-ca-path --without-ca-fallback && make

首先,如此处:

$ openssl s_client -servername www.example.com -connect www.example.com:443 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
verify return:1
depth=0 C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, OU = Technology, CN = www.example.org
verify return:1
DONE
$ openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem
$ openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem -out www.example.com.pubkey.der
$ openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64
xmvvalwaPni4IBbhPzFPPMX6JbHlKqua257FmJsWWto=

然后我在libcurl中设置公钥的哈希值和其他相关选项:

Then I set the public key's hash and other related options in libcurl:

curl_easy_setopt(conn, CURLOPT_PINNEDPUBLICKEY, "sha256//xmvvalwaPni4IBbhPzFPPMX6JbHlKqua257FmJsWWto=");
curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(conn, CURLOPT_URL, "https://example.com/index.html");
curl_easy_setopt(conn, CURLOPT_VERBOSE, 1);
curl_code = curl_easy_perform(conn);
if (curl_code != CURLE_OK)
{
    printf("%s\n", curl_easy_strerror(curl_code));
}

下载失败,并显示以下错误:

The download fails with an error:

* SSL certificate problem: unable to get local issuer certificate
...
Peer certificate cannot be authenticated with given CA certificates

好吧,似乎curl正在寻找一些证书,所以我重新编译它以使其包含默认证书:

Well, it seems curl is looking for some certificates, so I recompile it in order for it to include the default certificates:

./configure && make

现在,下载将可以进行:

Now, the download will work:

* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
...
*  SSL certificate verify ok.
*    public key hash: sha256//xmvvalwaPni4IBbhPzFPPMX6JbHlKqua257FmJsWWto=
...

在CURLOPT_PINNEDPUBLICKEY文档中,对其进行了解释:

In the CURLOPT_PINNEDPUBLICKEY documentation, it is explained:

When negotiating a TLS or SSL connection, the server sends a certificate
indicating its identity. A public key is extracted from this certificate
and if it does not exactly match the public key provided to this option,
curl will abort the connection before sending or receiving any data. 

因此,我的印象是curl只需要将用户的公钥与从服务器证书中提取的公钥进行比较即可.

So my impression was that curl only needs the public key from the user, in order to compare it with the public key extracted from the server's certificate.

我在这里想念什么?

推荐答案

问题是将 CURLOPT_SSL_VERIFYPEER 设置为1会启用CA固定.Curl接受同时设置CA固定和公共密钥固定的功能,并且由于在公共密钥固定之前尝试了CA固定,因此CA固定失败,并且永远也无法进行公共密钥固定.

The problem is that CURLOPT_SSL_VERIFYPEER being set to 1 enables CA pinning. Curl accepts setting both CA pinning and public-key pinning at the same time, and because CA pinning is tried before public key pinning, the CA pinning fails and it never gets to do the public key pinning.

解决方案是在进行公钥固定时明确禁用CA固定:

The solution is to explicitly disable CA pinning when doing public key pinning:

curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);

这需要明确完成,因为 CURLOPT_SSL_VERIFYPEER 的默认值为1.

This needs to be done explicitly because the default value for CURLOPT_SSL_VERIFYPEER is 1.

注意:通常应避免将 CURLOPT_SSL_VERIFYPEER 设置为0,但是在这种情况下,因为已经完成了公钥固定,所以这是安全的.

NOTE: setting CURLOPT_SSL_VERIFYPEER to 0 should generally be avoided, but in this case it is safe because public-key pinning is being done.

有关更多详细信息,另请参见此卷曲问题.

For more details also see this curl issue.

这篇关于如果不使用系统中的证书,则无法将curl中的公钥固定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆