@@ -253,6 +253,99 @@ const req = https.request(options, (res) => {
253
253
});
254
254
```
255
255
256
+ Example pinning on certificate fingerprint, or the public key (similar to
257
+ ` pin-sha256 ` ):
258
+
259
+ ``` js
260
+ const tls = require (' tls' );
261
+ const https = require (' https' );
262
+ const crypto = require (' crypto' );
263
+
264
+ function sha256 (s ) {
265
+ return crypto .createHash (' sha256' ).update (s).digest (' base64' );
266
+ }
267
+ const options = {
268
+ hostname: ' github.com' ,
269
+ port: 443 ,
270
+ path: ' /' ,
271
+ method: ' GET' ,
272
+ checkServerIdentity : function (host , cert ) {
273
+ // Make sure the certificate is issued to the host we are connected to
274
+ const err = tls .checkServerIdentity (host, cert);
275
+ if (err) {
276
+ return err;
277
+ }
278
+
279
+ // Pin the public key, similar to HPKP pin-sha25 pinning
280
+ const pubkey256 = ' pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=' ;
281
+ if (sha256 (cert .pubkey ) !== pubkey256) {
282
+ const msg = ' Certificate verification error: ' +
283
+ ` The public key of '${ cert .subject .CN } ' ` +
284
+ ' does not match our pinned fingerprint' ;
285
+ return new Error (msg);
286
+ }
287
+
288
+ // Pin the exact certificate, rather then the pub key
289
+ const cert256 = ' 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' +
290
+ ' D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16' ;
291
+ if (cert .fingerprint256 !== cert256) {
292
+ const msg = ' Certificate verification error: ' +
293
+ ` The certificate of '${ cert .subject .CN } ' ` +
294
+ ' does not match our pinned fingerprint' ;
295
+ return new Error (msg);
296
+ }
297
+
298
+ // This loop is informational only.
299
+ // Print the certificate and public key fingerprints of all certs in the
300
+ // chain. Its common to pin the public key of the issuer on the public
301
+ // internet, while pinning the public key of the service in sensitive
302
+ // environments.
303
+ do {
304
+ console .log (' Subject Common Name:' , cert .subject .CN );
305
+ console .log (' Certificate SHA256 fingerprint:' , cert .fingerprint256 );
306
+
307
+ hash = crypto .createHash (' sha256' );
308
+ console .log (' Public key ping-sha256:' , sha256 (cert .pubkey ));
309
+
310
+ lastprint256 = cert .fingerprint256 ;
311
+ cert = cert .issuerCertificate ;
312
+ } while (cert .fingerprint256 !== lastprint256);
313
+
314
+ },
315
+ };
316
+
317
+ options .agent = new https.Agent (options);
318
+ const req = https .request (options, (res ) => {
319
+ console .log (' All OK. Server matched our pinned cert or public key' );
320
+ console .log (' statusCode:' , res .statusCode );
321
+ // Print the HPKP values
322
+ console .log (' headers:' , res .headers [' public-key-pins' ]);
323
+
324
+ res .on (' data' , (d ) => {});
325
+ });
326
+
327
+ req .on (' error' , (e ) => {
328
+ console .error (e .message );
329
+ });
330
+ req .end ();
331
+
332
+ ```
333
+ Outputs for example:
334
+ ``` text
335
+ Subject Common Name: github.com
336
+ Certificate SHA256 fingerprint: 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16
337
+ Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=
338
+ Subject Common Name: DigiCert SHA2 Extended Validation Server CA
339
+ Certificate SHA256 fingerprint: 40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A
340
+ Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=
341
+ Subject Common Name: DigiCert High Assurance EV Root CA
342
+ Certificate SHA256 fingerprint: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
343
+ Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=
344
+ All OK. Server matched our pinned cert or public key
345
+ statusCode: 200
346
+ headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
347
+ ```
348
+
256
349
[ `Agent` ] : #https_class_https_agent
257
350
[ `URL` ] : url.html#url_the_whatwg_url_api
258
351
[ `http.Agent` ] : http.html#http_class_http_agent
0 commit comments