Skip to content

Instantly share code, notes, and snippets.

@9072997
Last active January 19, 2021 14:19
Show Gist options
  • Save 9072997/b49e0014eb35f081532010bd086d4085 to your computer and use it in GitHub Desktop.
Save 9072997/b49e0014eb35f081532010bd086d4085 to your computer and use it in GitHub Desktop.
ServerCertVerifier for rustls that will accept only a fixed certificate chain
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)));
}
}
}
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