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