1--- 2c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 3SPDX-License-Identifier: curl 4Title: CURLOPT_PROXY_PINNEDPUBLICKEY 5Section: 3 6Source: libcurl 7See-also: 8 - CURLOPT_PINNEDPUBLICKEY (3) 9 - CURLOPT_PROXY_CAINFO (3) 10 - CURLOPT_PROXY_CAPATH (3) 11 - CURLOPT_PROXY_SSL_VERIFYHOST (3) 12 - CURLOPT_PROXY_SSL_VERIFYPEER (3) 13Protocol: 14 - TLS 15TLS-backend: 16 - OpenSSL 17 - GnuTLS 18 - mbedTLS 19 - wolfSSL 20--- 21 22# NAME 23 24CURLOPT_PROXY_PINNEDPUBLICKEY - pinned public key for https proxy 25 26# SYNOPSIS 27 28~~~c 29#include <curl/curl.h> 30 31CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, 32 char *pinnedpubkey); 33~~~ 34 35# DESCRIPTION 36 37Pass a pointer to a null-terminated string as parameter. The string can be the 38filename of your pinned public key. The file format expected is "PEM" or 39"DER". The string can also be any number of base64 encoded sha256 hashes 40preceded by "sha256//" and separated by ";" 41 42When negotiating a TLS or SSL connection, the https proxy sends a certificate 43indicating its identity. A public key is extracted from this certificate and 44if it does not exactly match the public key provided to this option, libcurl 45aborts the connection before sending or receiving any data. 46 47On mismatch, *CURLE_SSL_PINNEDPUBKEYNOTMATCH* is returned. 48 49The application does not have to keep the string around after setting this 50option. 51 52# DEFAULT 53 54NULL 55 56# EXAMPLE 57 58~~~c 59int main(void) 60{ 61 CURL *curl = curl_easy_init(); 62 if(curl) { 63 curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); 64 curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443"); 65 curl_easy_setopt(curl, CURLOPT_PROXY_PINNEDPUBLICKEY, 66 "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjA" 67 "a3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74" 68 "Gxa2eg7fRbEgoChTociMee9wno="); 69 70 /* Perform the request */ 71 curl_easy_perform(curl); 72 } 73} 74~~~ 75 76# PUBLIC KEY EXTRACTION 77 78If you do not have the https proxy server's public key file you can extract it 79from the https proxy server's certificate. 80~~~c 81# retrieve the server's certificate if you do not already have it 82# 83# be sure to examine the certificate to see if it is what you expected 84# 85# Windows-specific: 86# - Use NUL instead of /dev/null. 87# - OpenSSL may wait for input instead of disconnecting. Hit enter. 88# - If you do not have sed, then just copy the certificate into a file: 89# Lines from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----. 90# 91openssl s_client -servername www.example.com -connect www.example.com:443 \ 92 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem 93 94# extract public key in pem format from certificate 95openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem 96 97# convert public key from pem to der 98openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem \ 99 -out www.example.com.pubkey.der 100 101# sha256 hash and base64 encode der to string for use 102openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64 103~~~ 104The public key in PEM format contains a header, base64 data and a 105footer: 106~~~c 107-----BEGIN PUBLIC KEY----- 108[BASE 64 DATA] 109-----END PUBLIC KEY----- 110~~~ 111 112# AVAILABILITY 113 114PEM/DER support: 115 116 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL 117 118sha256 support: 119 120 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL 121 122Other SSL backends not supported. 123 124# RETURN VALUE 125 126Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or 127CURLE_OUT_OF_MEMORY if there was insufficient heap space. 128