How to Configure the iroh Crypto Provider: ring vs aws‑lc‑rs
Configure the iroh crypto provider by enabling either the tls-ring or tls-aws-lc-rs Cargo feature, or manually inject a CryptoProvider into Builder::crypto_provider() before calling bind().
The n0-computer/iroh networking library uses rustls for QUIC/TLS encryption and relies on a pluggable crypto provider to supply the underlying cryptographic primitives. You can select between the ring and aws-lc-rs implementations either through compile-time feature flags or explicit runtime configuration.
Understanding iroh Crypto Providers
Iroh delegates all TLS cryptography to rustls via the CryptoProvider trait. The library supports two distinct provider implementations:
ring– The original Rust cryptography library, enabled via thetls-ringfeature and accessed throughrustls::crypto::ring::default_provider()aws-lc-rs– A newer OpenSSL-based alternative, enabled via thetls-aws-lc-rsfeature and accessed throughrustls::crypto::aws_lc_rs::default_provider()
Only one provider feature needs to be enabled for a working build. If you enable both features simultaneously, the ring provider takes precedence according to the feature-gate logic in src/endpoint/presets.rs (lines 66–70).
Automatic Configuration via Presets
Iroh provides convenient presets that automatically configure the crypto provider based on your enabled Cargo features.
Minimal Preset
The Minimal preset in src/endpoint/presets.rs (lines 52–73) contains the core selection logic:
// Simplified excerpt from src/endpoint/presets.rs
#[cfg(feature = "tls-ring")]
let provider = Arc::new(rustls::crypto::ring::default_provider());
#[cfg(all(feature = "tls-aws-lc-rs", not(feature = "tls-ring")))]
let provider = Arc::new(rustls::crypto::aws_lc_rs::default_provider());
When using Endpoint::builder(preset).bind().await, this preset checks feature flags at compile time and initializes the appropriate provider automatically.
N0 Preset
The N0 preset (lines 81–90 in src/endpoint/presets.rs) builds upon Minimal while adding relay and address lookup defaults. It inherits the same crypto provider selection behavior, making it the recommended starting point for most applications.
Manual Configuration
For custom setups, you can bypass presets and set the provider directly on the Builder. The crypto_provider field is defined at line 49 of src/endpoint.rs and is validated during the bind() call (lines 28–31), which aborts with BindError::InvalidCryptoProvider if no provider is set.
use std::sync::Arc;
use iroh::endpoint::Builder;
use rustls::crypto::{ring, aws_lc_rs};
// Explicitly choose ring
let provider = Arc::new(ring::default_provider());
// Or explicitly choose aws-lc-rs
// let provider = Arc::new(aws_lc_rs::default_provider());
let builder = Builder::empty()
.crypto_provider(provider)
.relay_mode(iroh::RelayMode::Default);
let endpoint = builder.bind().await?;
The Builder::crypto_provider() method stores an Arc<dyn CryptoProvider> that the TLS layer later clones and uses when constructing client and server configurations in src/tls.rs (lines 79–84).
Compile-Time Selection with Cargo Features
Add the desired feature to your Cargo.toml to statically select the provider without writing configuration code:
[dependencies]
# Use ring (preferred default)
iroh = { version = "0.x", features = ["tls-ring"] }
# Or use aws-lc-rs
iroh = { version = "0.x", features = ["tls-aws-lc-rs"] }
When both features are enabled, the Minimal preset prefers ring due to the #[cfg(feature = "tls-ring")] block taking precedence over the #[cfg(all(feature = "tls-aws-lc-rs", not(feature = "tls-ring")))] fallback.
Summary
- Iroh crypto providers implement the rustls
CryptoProvidertrait and supply TLS/QUIC cryptographic primitives. - Two providers are supported:
ring(featuretls-ring) andaws-lc-rs(featuretls-aws-lc-rs). - Presets (
MinimalandN0) automatically select the provider based on enabled features insrc/endpoint/presets.rs. - Manual configuration uses
Builder::crypto_provider()to inject anArc<CryptoProvider>before callingbind(). - Validation occurs at bind time; missing providers trigger
BindError::InvalidCryptoProvider(defined insrc/endpoint.rs). - Ring is preferred when both feature flags are enabled simultaneously.
Frequently Asked Questions
What happens if I enable both tls-ring and tls-aws-lc-rs?
If both features are enabled, iroh defaults to the ring provider. The Minimal preset in src/endpoint/presets.rs checks for the tls-ring feature first (lines 66–70), and only falls back to aws-lc-rs if tls-ring is disabled.
Can I switch crypto providers at runtime?
Yes. While presets select providers at compile time based on features, you can manually construct a Builder and call crypto_provider() with any Arc<dyn CryptoProvider> implementation. This allows runtime selection or custom provider implementations, though the standard iroh builders only support the two built-in options.
Where is the crypto provider actually used in the connection?
The provider is cloned from the builder and passed to rustls when constructing TLS configurations in src/tls.rs (lines 79–84). It drives all cryptographic operations during the QUIC handshake and subsequent encrypted communication.
Do I need to configure anything else when using a custom crypto provider?
If you manually set the crypto provider via Builder::crypto_provider(), ensure you have enabled the corresponding Cargo feature for the underlying rustls crate, or ensure your custom provider is fully compatible with iroh's QUIC implementation. The bind() method in src/endpoint.rs validates the provider exists (lines 28–31) but does not verify feature flag consistency.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →