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