A X.509 v3 (RFC5280) parser, implemented with the nom parser combinator framework.
It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken to ensure security and safety of this crate, including design (recursion limit, defensive programming), tests, and fuzzing. It also aims to be panic-free.
The code is available on Github and is part of the Rusticata project.
Certificates are usually encoded in two main formats: PEM (usually the most common format) or
DER. A PEM-encoded certificate is a container, storing a DER object. See the
pem module for more documentation.
To decode a DER-encoded certificate, the main parsing method is
X509Certificate::parse_der (from the DerParser trait)
which builds a X509Certificate object.
The parse_der trait takes an Input
object, which can be built from the input bytes. This helps tracking offsets (in case of
error).
For convenience,
the [X509Certificate::from_der] method (part of the FromDer trait)
does the same directly on the input bytes, but it can loose the precise error location.
An alternative method is to use X509CertificateParser,
which allows specifying parsing options (for example, not automatically parsing option contents).
Similar methods are provided for other X.509 objects:
X509Certificatefor X.509 CertificatesCertificateRevocationListfor X.509 v2 Certificate Revocation List (CRL)X509CertificationRequestfor Certification Signing Request (CSR)
The returned objects for parsers follow the definitions of the RFC. This means that accessing
fields is done by accessing struct members recursively. Some helper functions are provided, for
example X509Certificate::issuer() returns the
same as accessing <object>.tbs_certificate.issuer.
For PEM-encoded certificates, use the pem module.
This crate also provides visitor traits: X509CertificateVisitor, CertificateRevocationListVisitor.
See the visitor module.
Parsing a certificate in DER format:
use x509_parser::prelude::*;
static IGCA_DER: &[u8] = include_bytes!("../assets/IGC_A.der");
let input = Input::from(IGCA_DER);
let res = X509Certificate::parse_der(input);
match res {
Ok((rem, cert)) => {
assert!(rem.is_empty());
//
assert_eq!(cert.version(), X509Version::V3);
},
_ => panic!("x509 parsing failed: {:?}", res),
}To parse a CRL and print information about revoked certificates:
let input = Input::from(DER);
let res = CertificateRevocationList::parse_der(input);
match res {
Ok((_rem, crl)) => {
for revoked in crl.iter_revoked_certificates() {
println!("Revoked certificate serial: {}", revoked.raw_serial_as_string());
println!(" Reason: {}", revoked.reason_code().unwrap_or_default().1);
}
},
_ => panic!("CRL parsing failed: {:?}", res),
}See also examples/print-cert.rs.
- The
verifyandverify-awsfeatures add support for (cryptographic) signature verification, based onringoraws-lcrespectively. It adds theX509Certificate::verify_signature()method toX509Certificate.
/// Cryptographic signature verification: returns true if certificate was signed by issuer
#[cfg(any(feature = "verify", feature = "verify-aws"))]
pub fn check_signature(cert: &X509Certificate<'_>, issuer: &X509Certificate<'_>) -> bool {
let issuer_public_key = issuer.public_key();
cert
.verify_signature(Some(issuer_public_key))
.is_ok()
}-
The
verify-awsfeature offers the same support for signature verification, but based onaws-lc-rsinstead ofring. -
Note: if both
verifyandverify-awsfeatures are enabled (which happens when using--all-features), the verification will useaws-lc-rs. It also has the side-effect of having a dependency onring, even if it is not used. -
The
validatefeature adds methods to run more validation functions on the certificate structure and values using theValidatetrait. It does not validate any cryptographic parameter (seeverifyabove).
x509-parser requires Rustc version 1.85 or greater
This projects tries to maintain compatibility with older versions of the rust compiler for the following durations:
masterbranch: 12 months minimum- older releases: about 24 months
However, due to dependencies and the fact that some crate writers tend to require very recent versions of the compiler, this can prove to be difficult. These numbers are given as best-effort.
We do not consider MSRV changes to be breaking for the purposes of semver.
We try to make no change to MSRV in stable branches and in security patches, with the exception of a dependency that must be updated for security and requires a new MSRV.
See CHANGELOG.md and UPGRADING.md for instructions for upgrading major versions.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.