rustls: a Rust TLS library where the crypto provider is a pluggable choice
A modern TLS library in Rust
At a glance
- What is it?
- rustls is a TLS 1.2 and 1.3 library for Rust clients and servers. Since 0.22 the cryptographic primitives come from a selectable CryptoProvider, and from 0.24 that choice must be made explicitly.
- Who is it for?
- Adopt rustls when you are writing a Rust client or server that needs TLS 1.2 and 1.3 and you want the cryptography dependency to be a visible, replaceable choice rather than a build-time default. Do not adopt it as a drop-in replacement for an OpenSSL-based C or C++ stack, and do not assume the aws-lc-rs provider builds on every architecture; the README points at the aws-lc-rs platform FAQ for those constraints.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What rustls solves, and who ends up depending on it
rustls is a TLS 1.2 and TLS 1.3 implementation for both clients and servers, written in Rust. Its stated approach is to provide a good level of cryptographic security, to require no configuration to reach that level, and to offer no unsafe features or obsolete cryptography by default. That third clause is the one that separates it from a general-purpose TLS toolkit: the defaults are meant to be safe without a tuning pass.
The audience is Rust application and infrastructure developers. If you are writing an HTTP client, a database driver, a proxy, or a service that terminates TLS, you either call rustls directly or you call something built on it. The README lists Tokio users as a group that may prefer to work through a Tokio integration rather than through the core crate. The examples directory is the intended entry point: it contains demos that show I/O handling through a stream helper and more complex asynchronous I/O built on mio.
The CryptoProvider is the architecture, not a detail
TLS is a protocol plus a pile of primitives: key exchange, signatures, AEAD ciphers, hashing. rustls separates the two. A crypto::CryptoProvider is a collection of crypto primitive implementations, and supplying a custom instance replaces all of the cryptography dependencies of rustls at once. The README frames that as a route to portability across a wider set of architectures and environments, and as a route to meeting compliance requirements.
Provider selection has changed across versions, and the change matters for anyone reading older tutorials. Since 0.22 it has been possible to choose the provider. In versions before 0.24 both first-party providers shipped inside the rustls crate and Cargo features selected the preferred one, with the aws-lc-rs feature enabled by default. From 0.24, users must explicitly provide a crypto provider when constructing ClientConfig or ServerConfig instances. Code written against the feature-flag era will not compile unchanged against 0.24.
The project maintains two first-party providers. rustls-aws-lc-rs wraps the aws-lc-rs crate, and the README describes it as harder to build on some platforms but with excellent performance and a complete feature set that includes post-quantum algorithms. rustls-ring wraps ring, builds more easily across platforms, and has a more limited feature set; the README gives post-quantum algorithms as the example of what it lacks. The Rustls team recommends rustls-aws-lc-rs. That recommendation is a performance and feature judgement, not a statement that ring is unfit; the README explicitly points at the aws-lc-rs FAQ for platform and architecture constraints, which is where the build risk lives.
Third-party providers exist for teams whose constraints the first-party pair does not meet. The README lists providers built on BoringSSL, OpenSSL, mbedTLS, wolfCrypt, graviola, Microsoft SymCrypt, and the RustCrypto primitives, plus rustls-ccm for AES-CCM cipher suites aimed at IoT and constrained-device protocols. Some are labelled work in progress or experimental in that list. Treat that labelling as load-bearing: a provider that wraps a C library is a different supply-chain and build proposition from one written in Rust, even though the rustls API above it looks identical.
Installing rustls and standing up a first client config
The README points at docs.rs for documentation and at the examples directory for working code. Provider selection is the first thing to get right, because from 0.24 the config constructors require a provider. The README documents the provider crates as rustls-aws-lc-rs and rustls-ring, and the workspace Cargo.toml pins aws-lc-rs at version 1.18 with default features off. The README does not print a complete client example, so treat the provider crate's own documentation as the authority on its builder API.
The workspace file shows how the crates are laid out rather than how to depend on them. Its members list includes rustls, rustls-aws-lc-rs, rustls-ring, rustls-test, rustls-util, rustls-bench, rustls-post-quantum, rustls-provider-test, rustls-fuzzing-provider, examples, bogo, ci-bench, connect-tests, and openssl-tests, with the fuzz directory deliberately excluded because cargo fuzz requires nightly.
[workspace.dependencies]
aws-lc-rs = { version = "1.18", default-features = false }That entry is the dependency declaration the workspace uses for the AWS-LC provider's underlying crate. What it tells you is that default features are turned off there, which is consistent with the README's point that the provider choice is meant to be explicit rather than inherited. For a runnable end-to-end path, the README directs you to examples/, which contains demos for stream-based I/O and for asynchronous I/O via mio; that directory is the honest place to start because it shows the I/O plumbing a config plugs into.
Where rustls is the wrong tool
The provider model is also the main friction. If you want TLS to be one dependency that works everywhere with no further thought, rustls asks you to think. You must pick a provider, and the two first-party options trade against each other: aws-lc-rs for feature completeness and performance, ring for build portability. Choosing aws-lc-rs and then discovering your target architecture is not covered means a build failure, and the README sends you to the aws-lc-rs FAQ rather than promising universal support. Choosing ring means giving up post-quantum algorithms, which for a long-lived deployment is a real constraint rather than a footnote.
There is a second boundary that the README states plainly: the project aims to maintain reasonable API surface stability, but the API may evolve as new features and performance improvements land. That is not a stability guarantee, and the 0.22 to 0.24 provider change is the concrete example of what evolution looks like in practice. If your codebase pins rustls and cannot absorb a migration, that is a cost to price in.
Finally, rustls is a Rust library. If your stack is C, C++, Go, or a language with a mature binding to an existing TLS implementation, adopting rustls means adopting Rust or writing a binding layer. The README does not present rustls as a system TLS replacement for other languages, and nothing in the repository layout suggests a C API is the intended interface.
rustls against OpenSSL and against native-tls
The comparison people actually search for is rustls versus OpenSSL, and the difference is structural rather than a feature checklist. OpenSSL is a C library with a long-lived ABI, a configuration surface that spans decades of protocol history, and bindings from nearly every language. rustls is a Rust library whose cryptography is supplied by a provider crate, so the set of algorithms you ship is determined by a dependency you name, not by a build configuration you inherit. That is the trade: rustls gives you a smaller, more legible dependency graph and no obsolete cryptography by default, and in exchange it gives up the ubiquity and the drop-in ABI that make OpenSSL the default answer outside Rust.
The second comparison, rustls versus native-tls, is about indirection. A native-TLS style approach delegates to whatever TLS stack the platform provides, which keeps the binary small and inherits platform trust configuration, but it also means your protocol behaviour and your cryptography vary by operating system. rustls implements TLS 1.2 and 1.3 itself and behaves the same wherever it compiles, at the cost of you managing trust roots and provider selection in your own code. Neither is strictly better; they fail in different places.
Maintenance, licensing, and the cost of upgrading
The repository is not archived, and the last push was on 2026-09-21. Releases are frequent: 0.23.45 on 2026-09-14, 0.23.44 on 2026-09-07, and 0.23.43 on 2026-07-29. Detailed changes for each release are listed at the project's releases page, and there is a CHANGELOG.md at the repository root. Upstream also maintains a ROADMAP.md and a BENCHMARKING.md, the latter described as a way to prevent performance regressions and to let you evaluate rustls on your target hardware. That last point is worth taking literally: the project publishes benchmarks rather than promising a number, so measure on your own hardware.
Upgrade cost is dominated by the provider migration, not by the protocol work. The 0.24 change requiring an explicit provider at ClientConfig and ServerConfig construction is a source-level change, and the README notes that before 0.24 the aws-lc-rs feature was on by default. Any code that relied on that default will need editing. Treat the release notes as the authoritative migration guide; the README does not document rollback or downgrade paths.
On licensing, the repository root contains LICENSE, LICENSE-APACHE, LICENSE-ISC, and LICENSE-MIT. The GitHub licence field reports NOASSERTION, which means the platform did not map the repository's licensing to a single recognized identifier. The presence of both Apache and MIT files alongside an ISC file means the terms are not a single obvious choice, and the crate you depend on may carry different terms from the provider crate you pair it with. Read the licence files in the repository and in each provider crate before you ship; this is not legal advice.
Editorial conclusion
Adopt rustls when you are writing a Rust client or server that needs TLS 1.2 and 1.3 and you want the cryptography dependency to be a visible, replaceable choice rather than a build-time default. Do not adopt it as a drop-in replacement for an OpenSSL-based C or C++ stack, and do not assume the aws-lc-rs provider builds on every architecture; the README points at the aws-lc-rs platform FAQ for those constraints. Before you commit, verify which provider you are pulling in, whether it supports the cipher suites your peers require, and whether your target architecture is covered by that provider's build support.
Frequently asked questions
What is rustls?
rustls is a TLS library written in Rust that implements TLS 1.2 and TLS 1.3 for both clients and servers. Its stated approach is to provide a good level of cryptographic security with no configuration, and to offer no unsafe features or obsolete cryptography by default.
Is rustls pure Rust?
The library itself is platform independent Rust, but it requires cryptography primitives, and those come from a crypto::CryptoProvider. The first-party providers wrap the aws-lc-rs and ring crates, so the cryptography underneath is not necessarily pure Rust.
What are the key features of rustls?
It implements TLS 1.2 and TLS 1.3 for clients and servers, requires no configuration to reach a good level of cryptographic security, and exposes no unsafe features or obsolete cryptography by default. Since 0.22 the cryptographic primitives are supplied by a selectable CryptoProvider.
What is the difference between rustls and native-tls?
A native-TLS approach delegates to the TLS stack the platform provides, so protocol behaviour and cryptography vary by operating system. rustls implements TLS 1.2 and 1.3 itself and behaves the same wherever it compiles, which means you manage trust roots and provider selection in your own code.
What are the alternatives to rustls?
The README lists third-party crypto providers for rustls built on OpenSSL, BoringSSL, mbedTLS, wolfCrypt, graviola, Microsoft SymCrypt, and the RustCrypto primitives, some of them labelled work in progress or experimental. These replace the cryptography underneath rustls rather than replacing rustls itself.
Community notes