webpki

repository·main·Indexed 19 days ago

https://github.com/briansmith/webpki

A high-performance, memory-safe Rust library for validating Web PKI (TLS/SSL) X.509 certificates. Optimized for resource-constrained environments like IoT, it utilizes zero-copy parsing and a heap-less allocation strategy. It provides tools for verifying TLS server and client certificates, DNS name validation, and digital signature verification using the ring crate.

Tokens
8.4K
Snippets
32
Records
43
Agent score
66%

What's inside webpki

  1. What is webpki?

    main

    webpki is a Rust-based library designed for validating Web PKI (TLS/SSL) certificates. It provides a full implementation of the client-side Web PKI suitable for a wide range of environments, including embedded (IoT) devices, mobile apps, desktop applications, and server infrastructure.

    Key technical characteristics:

    • Safety: Written in Rust to prevent buffer overflows, use-after-free, and data races.
    • Efficiency: Uses a zero-copy parsing strategy and never allocates memory on the heap. It maintains tight bounds on stack memory usage.
    • Small Footprint: Avoids superfluous PKIX features to keep object code size minimal, making it ideal for resource-constrained environments.
    • Dependencies: Uses ring for signature verification.
    • Influence: Strongly influenced by mozilla::pkix.
  2. Encode ASCII files to DER using ascii2der

    main

    To create or modify the binary DER files used in this project, first prepare an ASCII representation of the data and then encode it back to DER using the ascii2der tool from the google/der-ascii package.

    go get github.com/google/der-ascii/cmd/ascii2der
    ascii2der i <filename>.ascii -o <filename>
  3. Decode DER files to ASCII using der2ascii

    main

    The data files in this directory contain binary DER encodings of ASN.1 AlgorithmIdentifier values (excluding the outer SEQUENCE tag and length component). To convert these binary files into a human-readable ASCII format, use the der2ascii tool from the google/der-ascii package.

    go get github.com/google/der-ascii/cmd/der2ascii
    der2ascii -i <filename> -o <filename>.ascii
  4. Regenerate pathbuilding test data

    main

    To regenerate the JSON test data used for the pathbuilding suite, you must have Go installed. Use the bettertls command-line tool to export the tests into a JSON file.

    1. Install Go.
    2. Install the bettertls tool using go install.
    3. Run the export-tests command with the --suite pathbuilding flag and specify an output file using --out.
    GOBIN=$PWD go install github.com/Netflix/bettertls/test-suites/cmd/bettertls@latest
    ./bettertls export-tests --suite pathbuilding --out ./pathbuilding.tests.json
  5. What is a TrustAnchor and how to create one

    main

    A TrustAnchor (a.k.a. a root CA) is a minimized representation of an X.509 certificate containing only the essential elements required for verification. This is more memory-efficient than storing full X.509 certificates.

    To create a TrustAnchor from a DER-encoded certificate, use TrustAnchor::try_from_cert_der.

    Note: This method does not validate the certificate. It does not check if the certificate is self-signed or if it has the cA basic constraint. It simply extracts the necessary fields.

    Fields extracted into a TrustAnchor:

    • subject: The value of the subject field.
    • spki: The value of the subjectPublicKeyInfo field.
    • name_constraints: An optional DER-encoded NameConstraints field, if present.
    // Assuming cert_der is a &[u8] containing a DER-encoded certificate
    let trust_anchor = TrustAnchor::try_from_cert_der(cert_der)?;
  6. How end-entity certificate validation works in TLS

    main

    Validating an end-entity certificate in a TLS connection requires three distinct steps. While these can be performed in parallel for optimization, all three must be completed before any application data is sent or processed.

    For Server Certificates:

    1. Validity for TLS Server Use: Call EndEntityCert.verify_is_valid_tls_server_cert to ensure the certificate is valid for server authentication.
    2. DNS Name Validation: Call EndEntityCert.verify_is_valid_for_dns_name to ensure the certificate matches the host being connected to.
    3. Signature Verification: Call EndEntityCert.verify_signature to verify the signature of the ServerKeyExchange message using the certificate's public key.

    For Client Certificates:

    1. Validity for TLS Client Use: Call EndEntityCert.verify_is_valid_tls_client_cert to ensure the certificate is valid for client authentication.
    2. Identity Validation: Call EndEntityCert.verify_is_valid_for_dns_name or EndEntityCert.verify_is_valid_for_at_least_one_dns_name to verify the client's identity (currently supported via DNS hostnames).
    3. Signature Verification: Call EndEntityCert.verify_signature to verify the client's signature in its CertificateVerify message.

    Note: EndEntityCert::from is an inexpensive, deterministic operation. If performing these steps in multiple threads, it is recommended to call EndEntityCert::from multiple times for the same DER-encoded bytes.

  7. Reference `DnsName` and `DnsNameRef` types

    main

    DnsName

    An owned, syntactically valid DNS name stored in a String. Requires the alloc feature. It is useful for storing names that need to persist beyond a specific scope.

    DnsNameRef<'a>

    A lightweight, zero-copy reference to a DNS name (stored as &'a [u8]). It is guaranteed to be syntactically valid upon construction via try_from_ascii.

  8. Format test data for net::VerifySignedData()

    main

    Test data for net::VerifySignedData() must follow a specific structure consisting of a description followed by four PEM-formatted blocks. When adding or modifying test data, you must run the annotation script to ensure consistent formatting and to generate ASN.1 structure comments.

    Important: If you need to add manual comments to a PEM block, place them immediately below the block. The annotation script will insert its own comments describing the parsed ASN.1 structure; any manual comments placed below the script-generated comments will be stripped.

    <A description of the test>
    
    -----BEGIN PUBLIC KEY-----
      <base64-encoded, DER-encoded, SPKI>
      -----END PUBLIC KEY-----
    
    -----BEGIN ALGORITHM-----
      <base64-encoded, DER-encoded, AlgorithmIdentifier for the signature.>
      -----END ALGORITHM-----
    
    -----BEGIN DATA-----
      <base64-encoded data that is being verified>
      -----END DATA-----
    
    -----BEGIN SIGNATURE-----
      <base64-encoded, DER-encoded, BIT STRING of the signature>
      -----END SIGNATURE-----
  9. How to use webpki (Example)

    main

    To see how to integrate webpki into a project, refer to the example code provided in the rustls repository. webpki is commonly used as the certificate validation component within TLS implementations like rustls.

    https://github.com/ctz/rustls#example-code
  10. Configure webpki features

    main

    The webpki crate provides two main feature flags to control its dependencies and capabilities:

    • alloc: Enables features that require heap allocation. This is currently required for all RSA signature algorithms.
    • std: Enables features that require the Rust standard library (libstd). Enabling std automatically implies alloc.