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