Skip to content

Instantly share code, notes, and snippets.

@exoego
Created September 30, 2025 04:40
Show Gist options
  • Save exoego/9801c216c2fdf08ab070cf8e2774c1ee to your computer and use it in GitHub Desktop.
Save exoego/9801c216c2fdf08ab070cf8e2774c1ee to your computer and use it in GitHub Desktop.
Create reqwest::client with custom certification from PKCS12 (.p12)
[dependencies]
rustls = { version = "^0.23", features = ["ring", "logging", "std", "tls12", ] }
rustls-platform-verifier = "0.6"
rustls-pki-types = "1"reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
p12-keystore = "0.2"
anyhow = "^1"
use std::fs;
use std::path::PathBuf;
use reqwest::ClientBuilder;
use rustls::ClientConfig;
use rustls_pki_types::CertificateDer;
use rustls_pki_types::PrivateKeyDer;
use rustls_platform_verifier::BuilderVerifierExt;
pub fn build_reqwest_client_with_p12(
p12_path: &PathBuf,
p12_password: &str,
) -> anyhow::Result<reqwest::Client> {
let p12_data = fs::read(p12_path)?;
let key_store = p12_keystore::KeyStore::from_pkcs12(&p12_data, p12_password)?;
let (client_key, client_cert_chain) = if let Some((_, pkc)) = key_store.private_key_chain() {
let client_key = PrivateKeyDer::try_from(pkc.key()).unwrap();
let client_cert_chain = pkc
.chain()
.iter()
.map(|cert| CertificateDer::from(cert.as_der()).into_owned())
.collect::<Vec<_>>();
if client_cert_chain.is_empty() {
return Err(anyhow::anyhow!("missing client cert chain"));
}
(client_key.clone_key(), client_cert_chain)
} else {
return Err(anyhow::anyhow!("missing private key chain"));
};
let tls_config = ClientConfig::builder()
.with_platform_verifier()?
.with_client_auth_cert(client_cert_chain, client_key)?;
let client_builder = ClientBuilder::new().use_preconfigured_tls(tls_config);
match client_builder.build() {
Ok(c) => anyhow::Ok(c),
Err(e) => anyhow::bail!(e),
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment