# How to Configure the iroh Crypto Provider: ring vs aws‑lc‑rs

> Configure iroh crypto provider: choose between ring and aws-lc-rs features or inject manually. Learn how to set up your iroh crypto provider for optimal performance.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-06-21

---

**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 the `tls-ring` feature and accessed through `rustls::crypto::ring::default_provider()`
- **`aws-lc-rs`** – A newer OpenSSL-based alternative, enabled via the `tls-aws-lc-rs` feature and accessed through `rustls::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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/src/endpoint/presets.rs) (lines 52–73) contains the core selection logic:

```rust
// 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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/src/endpoint.rs) and is validated during the `bind()` call (lines 28–31), which aborts with `BindError::InvalidCryptoProvider` if no provider is set.

```rust
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`](https://github.com/n0-computer/iroh/blob/main/src/tls.rs) (lines 79–84).

## Compile-Time Selection with Cargo Features

Add the desired feature to your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml) to statically select the provider without writing configuration code:

```toml
[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 `CryptoProvider` trait and supply TLS/QUIC cryptographic primitives.
- **Two providers** are supported: `ring` (feature `tls-ring`) and `aws-lc-rs` (feature `tls-aws-lc-rs`).
- **Presets** (`Minimal` and `N0`) automatically select the provider based on enabled features in [`src/endpoint/presets.rs`](https://github.com/n0-computer/iroh/blob/main/src/endpoint/presets.rs).
- **Manual configuration** uses `Builder::crypto_provider()` to inject an `Arc<CryptoProvider>` before calling `bind()`.
- **Validation** occurs at bind time; missing providers trigger `BindError::InvalidCryptoProvider` (defined in [`src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/src/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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/src/endpoint.rs) validates the provider exists (lines 28–31) but does not verify feature flag consistency.