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