reqwest icon indicating copy to clipboard operation
reqwest copied to clipboard

Add public key pinning

Open rumpelsepp opened this issue 7 years ago • 10 comments

Support for public key pinning is missing. curl has PINNEDPUBLICKEY.

rumpelsepp avatar May 23 '18 11:05 rumpelsepp

Some more reference material: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

There’s an OpenSSL example in there. If given a pointer or two I’d be happy to try implement this.

stephanbuys avatar Jul 13 '19 05:07 stephanbuys

Currently reqwest also does not work if a certificate store is not available on the system, even if the correct certificate has been added with .add_root_certificate() (or a public key is pinned). Running without a certificate store should probably also be supported as pinning methods get added.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Hyper(Error(Connect, Custom { kind: Other, error: Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 337047686, library: "SSL routines", function: "tls_process_server_certificate", reason: "certificate verify failed", file: "ssl/statem/statem_clnt.c", line: 1921 }]))) }, X509VerifyResult { code: 20, error: "unable to get local issuer certificate" }) })), "https://example.com/")', src/libcore/result.rs:1084:5

remram44 avatar Aug 26 '19 02:08 remram44

any activity on this? I have the same prolem...

goodidea-kp avatar Dec 22 '20 15:12 goodidea-kp

Doesn't #1150 fix this? using add_root_certificate and tls_built_in_root_certs should create the desired behavior unless I misunderstood what the issue is about.

zumoshi avatar May 29 '21 07:05 zumoshi

Hi, any news here?

yuvalmarciano avatar Aug 08 '24 08:08 yuvalmarciano

Doesn't #1150 fix this? using add_root_certificate and tls_built_in_root_certs should create the desired behavior unless I misunderstood what the issue is about.

No, add_root_certificate is much more strict because it only allows adding a root certificate. I just tried to put only the leaf certificate there, and the connection got rejected.

Furthermore, I would like to supply the sha256 of the leaf certificate instead of providing the full certificate (chain)

Tienisto avatar Aug 14 '24 15:08 Tienisto

What would be needed for this issue to be moved from label B-rfc (Blocked Request for comments. More discussion would help move this along.) to E-*?

lucacastelnuovo avatar Oct 08 '25 12:10 lucacastelnuovo

It'd need more of a specced out design. Likely someone else motivated to consider how exactly it would work, and then to implemented it. Some things to consider:

  • What does the method and arguments look like?
  • Does it work with all TLS backends?

seanmonstar avatar Oct 08 '25 13:10 seanmonstar

Looking more closely at curl's implementation, I see it supports both file paths and hash strings. For the first version of the implementation, I'd focus on supporting only the hash string format (not PEM/DER files):

.pin_public_key(hash: &str)
let hash1 = "7ad9c14e9ab5eb5c52c9e5bf9d7e0b839194e4b564e0bd6744b727ab71ec84ef";
let hash2 = "498fd358cb0297e0dab6da9b2dab310534f64bee164fac22030199dba75fae51";

let client = reqwest::Client::builder()
    .pin_public_key(hash1)
    .pin_public_key(hash2)
    .build()?;

The hash format would be:

  • Raw hex-encoded SHA256 hash of the public key (64 characters)
  • No "sha256//" prefix, no base64 encoding, no semicolon separators, just repeated calls if more hashes need to be allowed
  • Hash format validation happens at build time, returning an error for invalid input

The behaviour would be:

  • Normal validation still occurs, pinning would be an additional security check on top of the standard validation
  • If at least one pin is specified, the connection fails unless the server's public key matches at least one of the pinned hashes

I would love to help implement this but my rust level is very beginner.

lucacastelnuovo avatar Oct 10 '25 08:10 lucacastelnuovo

Hello, I made a quick proof of concept with a custom verifier here : https://github.com/nicolaspernoud/certificate-pinning-poc-rs ; The API proposed by @lucacastelnuovo could be easier... but what if we want to add extra CAs as well, etc.

nicolaspernoud avatar Nov 14 '25 10:11 nicolaspernoud