Last active
January 19, 2021 14:19
-
-
Save 9072997/b49e0014eb35f081532010bd086d4085 to your computer and use it in GitHub Desktop.
ServerCertVerifier for rustls that will accept only a fixed certificate chain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use blake2::{Blake2b, Digest}; | |
pub struct CertHash<'a>(pub &'a str); | |
impl rustls::ServerCertVerifier for CertHash<'_> { | |
fn verify_server_cert( | |
&self, | |
_roots: &rustls::RootCertStore, | |
presented_certs: &[rustls::Certificate], | |
_dns_name: webpki::DNSNameRef<'_>, | |
_ocsp_response: &[u8], | |
) -> Result<rustls::ServerCertVerified, rustls::TLSError> { | |
let mut hasher = Blake2b::new(); | |
for cert in presented_certs { | |
hasher.update(cert.as_ref()); | |
} | |
let hash = hasher.finalize(); | |
let hash_str = base64::encode(hash); | |
if hash_str == self.0 { | |
return Ok(rustls::ServerCertVerified::assertion()); | |
} else { | |
let err_str = format!("Certificate hash {} does not match pinned hash", hash_str); | |
return Err(rustls::TLSError::General(String::from(err_str))); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::sync::Arc; | |
mod cert_pin; | |
fn main() -> Result<(), ureq::Error> { | |
// create TLS config using cert_pin | |
let mut tls_config = rustls::ClientConfig::new(); | |
tls_config | |
.dangerous() | |
.set_certificate_verifier(Arc::new(cert_pin::CertHash("+XMhemTq5LkUAK9siKwgb75Wp8N59L3YLn1X1pfB9hDS8QN5k4PKe/iFAbWo4KjauI0vdvjNW27MOAJnGRNBag=="))); | |
// just an example request using rustls with our tls_config | |
let agent = ureq::builder() | |
.tls_config(Arc::new(tls_config).clone()) | |
.build(); | |
let req = agent.get("https://jsonplaceholder.typicode.com/todos/1"); | |
let resp: serde_json::Value = req.call()?.into_json()?; | |
println!("{}", resp["title"]); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment