X509 Path Finder is a depth-first search certificate path validator for Rust.
X509 Path Finder rejects the notion of a single "certificate chain." Instead, it searches for the first match out of infinity. Once it finds a path it can validate, the search halts and the path is returned to the caller.
The complexity of the path search is constrained by three factors:
When evaluating a path candidate for validation, X509 Path Finder is implementation-agnostic. Once it finds a path that has terminated, it presents it to be validated by a backend authority. If the authority validates the path, the search halts.
Validators can be implemented with one method. To get users started, X509 Path Finder ships with an OpenSSL validator.
By default, you'll need to implement your own PathValidator.
text
[dependencies]
x509_path_finder = { version = "0.2"] }
Or, enable the openssl
feature for access to the provided OpenSSLPathValidator validator.
text
[dependencies]
x509_path_finder = { version = "0.2", features = ["openssl"] }
```` rust use x509pathfinder::api::CertificateStore; use x509pathfinder::provided::certificate::openssl::OpenSSLCertificateIterator; use x509pathfinder::provided::store::DefaultCertificateStore; use x509pathfinder::provided::validator::openssl::OpenSSLPathValidator; use x509pathfinder::report::CertificateOrigin; use x509pathfinder::{X509ClientType, X509PathFinder, X509PathFinderConfiguration}; use openssl::x509::store::X509StoreBuilder; use openssl::x509::verify::X509VerifyFlags; use openssl::x509::X509; use std::marker::PhantomData; use std::time::Duration;
async fn test() { // load certificates with OpenSSL let certificates = X509::stackfrompem(loadcertificate())?; let root = X509::fromder(load_root())?;
// create store, load in certificates
let store = DefaultCertificateStore::from_iter(certificates);
// create OpenSSL store
let mut builder = X509StoreBuilder::new()?;
builder.add_cert(root)?;
builder.set_flags(X509VerifyFlags::X509_STRICT)?;
// Instantiate validator with OpenSSL store
let validator = OpenSSLPathValidator::new(builder.build());
// Instantiate finder with store and validator
let mut finder = X509PathFinder::new(X509PathFinderConfiguration {
limit: Duration::default(),
client: X509ClientType::None(PhantomData::<OpenSSLCertificateIterator>),
store,
validator,
});
// Find a path, starting with first certificate
let report = finder.find(certificates[0].as_ref()).await?;
let path = report.path?.into_iter().collect::<Vec<X509>>();
assert_eq!(2, path.len());
// Find a path, starting with second certificate
let report = search.find(certificates[1].as_ref()).await?;
let path = report.path?.into_iter().collect::<Vec<X509>>();
assert_eq!(1, path.len());
}
````
The X509PathFinderConfiguration
struct has the following fields.
limit
: limit runtime of path search. Actual limit will be N * HTTP timeout. See Reqwest
docs for setting HTTP connection timeout.client
: Optional client to find additional certificates by parsing URLs from Authority Information Access extensionsstore
- CertificateStore
implementationvalidator
: PathValidator
implementationCall X509PathFinder::find
to start the search.
The returning Report
contains the following fields:
path
: on validate success, Option::Some
holds CertificatePath
iterator.origin
: on validate success, Option::Some
holds a list of CertificateOrigin
valuesduration
: duration of path search failures
: any validation failures reported by PathValidator
implementation are held in ValidateFailure
CertificatePath
is an iterator over a list of certificates.
CertificateOrigin
is an enum that describes the origin of each certificate. Can be one of:
Find
: the initial certificate when calling X509PathFinder::find
.Store
: certificate was found in the storeUrl
: certificate was downloaded from a URL (AIA)ValidateFailure
stores any validation failures. Validation failures can occur even though a valid certificate path was eventually found. ValidateFailure
contains the following fields:
path
: the CertificatePath
of where the validation error occurredreason
: human-readable reason for the failureX509 Path Finder can be extended with three traits:
Certificate
- model-agnostic representation of an X509 certificate. Implement this trait to add more certificates modelsCertificateStore
- certificate store API. Implement this trait to make stores with different persistence strategies PathValidator
- path validator API. Implement this trait to use different backend authorities to validate certificate paths.The following API implementations are provided with the X509 Path Finder crate:
Certificate
and PathValidator
X509PathFinderConfiguration::client
field