x509-parser

repository·master·Indexed 42 days ago

https://github.com/rusticata/x509-parser

A high-performance, zero-copy X.509 v3 (RFC 5280) parser implemented in pure Rust using the nom framework. It supports DER and PEM formats and provides tools for parsing certificates, Certificate Revocation Lists (CRL), and Certification Signing Requests (CSR). Version 0.19.0-beta.1 requires Rustc 1.85 or greater. Optional features include structural validation via the 'validate' feature and cryptographic signature verification via 'verify' (ring), 'verify-aws' (aws-lc-rs), or 'verify-aws-fips'.

Tokens
15.3K
Snippets
39
Records
67
Agent score
54%

What's inside x509-parser

  1. Generate RSA-PSS test certificates using OpenSSL

    master

    You can generate self-signed X.509 certificates using RSA-PSS padding for testing purposes with OpenSSL. The following commands generate DER-encoded certificates using SHA-256, SHA-384, and SHA-512 respectively.

    Key flags used:

    • -sigopt rsa_padding_mode:pss: Specifies RSA-PSS padding.
    • -sigopt rsa_pss_saltlen:-1: Sets the salt length to the maximum possible.
    • -outform der: Ensures the output is in DER format.
    # Generate SHA-256 certificate
    openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha256 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha256.der -batch
    
    # Generate SHA-384 certificate
    openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha384 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha384.der -batch
    
    # Generate SHA-512 certificate
    openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha512 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha512.der -batch
  2. Upgrade from 0.18 to 0.19

    master
    Version 0.19 introduces major breaking changes, including dependency updates, changes to the global parsing API, and modifications to struct fields and methods. Key dependency changes include updating nom to 8.0 and asn1-rs to 0.8, and the removal of the der-parser dependency and re-export.
  3. How the X509CertificateVisitor works

    master

    The X509CertificateVisitor trait implements the Visitor pattern to allow traversing the components of an X509Certificate without manual field access.

    Key Behaviors:

    • Generic vs. Specific Extension Visiting: The visitor provides a generic visit_extension method for any X509Extension. It also provides specific methods for standard extensions (e.g., visit_extension_aki for AuthorityKeyIdentifier).
    • Conditional Execution: A specific extension method is only called if the extension's OID is correct and the content is successfully parsed into the expected type.
    • Redundancy: A specific method can be called multiple times if the extension appears multiple times in the certificate. Implementations should be aware that they might visit the same extension multiple times.
    • Error Handling: If an extension is malformed or cannot be parsed, visit_extension_parse_error is invoked.
    use x509_parser::prelude::*;
    use x509_parser::visitor::X509CertificateVisitor;
    
    #[derive(Debug, Default)]
    struct MyVisitor {
        issuer: String,
        is_ca: bool,
    }
    
    impl X509CertificateVisitor for MyVisitor {
        fn visit_issuer(&mut self, name: &X509Name<'_>) {
            self.issuer = name.to_string();
        }
    
        fn visit_extension_basic_constraints(&mut self, bc: &BasicConstraints) {
            self.is_ca = bc.ca;
        }
    }
    
    // Usage:
    // let mut visitor = MyVisitor::default();
    // x509.walk(&mut visitor);
  4. Enable cryptographic signature verification with the `verify` feature

    master

    The verify feature adds support for cryptographic signature verification using the ring crate. It provides the X509Certificate::verify_signature() method.

    To verify if a certificate was signed by an issuer, you can use the issuer's public key:

    #[cfg(any(feature = "verify", feature = "verify-aws", feature = "verify-aws-fips"))]
    use x509_parser::certificate::X509Certificate;
    
    #[cfg(any(feature = "verify", feature = "verify-aws", feature = "verify-aws-fips"))]
    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()
    }
  5. How to use the CertificateRevocationListVisitor pattern

    master

    The CertificateRevocationListVisitor trait allows you to traverse a CertificateRevocationList (CRL) by implementing specific callback methods. This is useful for extracting specific data (like revoked certificate serial numbers) or inspecting extensions without manually navigating the entire tree structure.

    Key Behaviors

    • Extension Dispatch: The visitor provides both generic methods (e.g., visit_extension) and specific methods for recognized extensions (e.g., visit_extension_aki). A specific method is only called if the extension OID matches and the content is successfully parsed.
    • Redundancy: Some methods are redundant by design (e.g., visit_revoked_certificates vs visit_revoked_certificate). If you implement a trait that provides multiple visitor methods, be aware that the same extension might be visited multiple times.
    • Execution: Use the .walk(&mut visitor) method on a CertificateRevocationList instance to begin traversal.
    use asn1_rs::num_bigint::BigUint;
    use x509_parser::prelude::*;
    use x509_parser::visitor::CertificateRevocationListVisitor;
    
    #[derive(Debug, Default)]
    struct RevokedCertsVisitor {
        certificates: Vec<BigUint>,
    }
    
    impl CertificateRevocationListVisitor for RevokedCertsVisitor {
        fn visit_revoked_certificate(&mut self, certificate: &RevokedCertificate<'_>) {
            self.certificates.push(certificate.user_certificate.clone());
        }
    }
  6. Iterate over multiple PEM blocks with PemIterator

    master

    When a file contains multiple PEM blocks (like a certificate chain), use Pem::iter_from_buffer or Pem::iter_from_reader to get a PemIterator.

    This iterator skips any text outside of valid -----BEGIN ...----- and -----END ...----- blocks. Each call to next() returns a Result<Pem, PEMError>. The iterator terminates when no more blocks are found or when PEMError::MissingHeader is encountered.

  7. Enable cryptographic signature verification with `verify` features

    master

    To enable cryptographic signature verification, you must enable one of the following features:

    • verify: Uses the ring crate for signature verification. Adds the X509Certificate::verify_signature() method.
    • verify-aws: Uses the aws-lc-rs crate for signature verification. Adds the X509Certificate::verify_signature() method.
    • verify-aws-fips: Uses the FIPS-approved crypto module of aws-lc-rs. Requires CMake, Go, and an executable temporary directory on the host system.

    Note: If both verify and verify-aws (or verify-aws-fips) are enabled, aws-lc-rs will be used for verification, but ring will still be included as a dependency.

  8. How X509Certificate and TbsCertificate work together

    master

    An X509Certificate is a wrapper around a TbsCertificate (To-Be-Signed certificate) and the signature data.

    • X509Certificate: Contains the tbs_certificate, the signature_algorithm, and the signature_value. It provides a zero-copy view of the entire signed certificate.
    • TbsCertificate: Contains the core identity and validity information defined in RFC5280, including the version, serial number, issuer, validity period, subject, and extensions.

    Because X509Certificate implements Deref<Target = TbsCertificate>, you can call TbsCertificate methods (like .subject() or .issuer()) directly on an X509Certificate instance.

  9. Understand the DistributionPointName structure

    master

    The DistributionPointName is a CHOICE type used to identify the location of a CRL. It can take one of two forms:

    1. FullName(Vec<GeneralName>): A list of GeneralName objects (typically URIs).
    2. NameRelativeToCRLIssuer(RelativeDistinguishedName): A distinguished name relative to the CRL issuer.

    This type uses implicit tagging in its ASN.1 definition.

  10. Enable structural validation with the `validate` feature

    master
    The validate feature adds methods to run validation functions on the certificate structure and values using the Validate trait. Note that this feature does not perform cryptographic parameter validation; use the verify features for that.