How Iroh Ensures Security and TLS Encryption: Raw Public Keys and QUIC Implementation

Iroh guarantees secure peer-to-peer communication by implementing TLS 1.3 over QUIC with raw public key authentication (RFC 7250), eliminating traditional PKI dependencies while maintaining end-to-end encryption and forward secrecy through a unified TlsConfig architecture.

The n0-computer/iroh repository secures all network traffic using a zero-trust model that replaces X.509 certificates with cryptographic public key authentication. Understanding how Iroh ensures security and TLS encryption requires examining its rustls integration, centralized configuration management, and relay-side transport handling.

Raw Public Key Authentication (RFC 7250)

Instead of relying on traditional X.509 certificates and Certificate Authorities, Iroh embeds raw public keys directly into the TLS handshake using the RFC 7250 extension. This approach eliminates PKI dependencies while maintaining strong peer authentication.

The ResolveRawPublicKeyCert resolver derives the public key from the node's SecretKey and supplies it to rustls during the handshake. This implementation appears in iroh/src/tls.rs and ensures each node cryptographically proves its identity without certificate chains.

Unified TLS Configuration Architecture

Iroh centralizes all TLS state within the TlsConfig struct to ensure consistency across client and server sessions. This configuration manages certificate verification, session caching, and cryptographic providers through a single source of truth.

TlsConfig Structure

The TlsConfig struct holds the node's secret key, certificate resolver, and custom verifiers for both client and server authentication. Key components include:

  • Memory-based session-ticket cache: Limited to DEFAULT_MAX_TLS_TICKETS (approximately 150 KB) to prevent unbounded memory growth
  • Injectable crypto provider: The crypto_provider field accepts custom rustls cryptographic implementations
  • Dual verifier support: Separate verifiers for client and server authentication ensure role-specific validation logic

Source reference: iroh/src/tls.rs (lines 45-52).

Client Configuration

When initiating connections, the make_client_config method constructs a rustls::ClientConfig with security-hardened defaults:

  • Restricts TLS to verifier::PROTOCOL_VERSIONS (TLS 1.3)
  • Implements custom certificate verification via server_verifier
  • Integrates the raw-public-key resolver (cert_resolver)
  • Enables early-data (0-RTT) for connection resumption
  • Supports optional key-logging via SSLKEYLOGFILE for debugging
  • Wraps the result in a QuicClientConfig for QUIC transport

Source reference: iroh/src/tls.rs (lines 72-98).

Server Configuration

The make_server_config method creates a symmetric rustls::ServerConfig for incoming connections:

  • Uses identical protocol versions and crypto providers as the client
  • Enforces client-certificate verification through client_verifier
  • Supplies the same raw-public-key resolver for peer authentication
  • Enables early-data with maximum size set to u32::MAX per RFC 9001 requirements
  • Optionally enables key-logging for development environments

Source reference: iroh/src/tls.rs (lines 100-122).

Relay-Side TLS Implementation

Iroh's relay client implements independent TLS handling for connections to relay servers, maintaining security guarantees even when traffic traverses intermediary nodes.

Relay Client TLS

The relay client constructs its own rustls::ClientConfig and tokio_rustls::TlsConnector in iroh-relay/src/client/tls.rs. This implementation respects the same raw-public-key verification strategy used in direct peer connections while allowing TLS to be bypassed for non-secure schemes (http/ws).

Source references: lines 31-38 and 65-78.

MaybeTlsStreamBuilder

The MaybeTlsStreamBuilder determines whether TLS is required based on the URL scheme, extracts the server name for verification, and performs the handshake via TlsConnector. The resulting MaybeTlsStream abstracts over plain TCP or TLS-wrapped transport, providing a unified interface for the QUIC stack.

Source reference: iroh-relay/src/client/tls.rs (lines 78-90).

Security Guarantees

Iroh's TLS implementation provides four critical security properties:

  • End-to-end encryption: All traffic is encrypted using TLS 1.3 cipher suites with no downgrade attacks possible
  • Authenticity: Raw public keys ensure cryptographic peer identity without trusting third-party CAs
  • Forward secrecy: QUIC's TLS 1.3 integration ensures session keys cannot be compromised retroactively
  • Replay protection: 0-RTT session tickets are carefully bounded by the DEFAULT_MAX_TLS_TICKETS limit to prevent replay attacks

Implementation Examples

The following examples demonstrate creating secure TLS configurations for Iroh nodes:

// Creating a TLS configuration for a node
use iroh_base::SecretKey;
use std::sync::Arc;
use iroh::tls::TlsConfig;

// Generate node identity and select crypto provider
let sk = SecretKey::generate();
let provider = rustls::crypto::CryptoProvider::default();
let tls_cfg = TlsConfig::new(
    sk.clone(), 
    TlsConfig::DEFAULT_MAX_TLS_TICKETS, 
    Arc::new(provider)
);

// Build client configuration
let client_cfg = tls_cfg.make_client_config(/*keylog=*/false)?;
let quic_client = client_cfg; // Ready for QUIC transport

// Build server configuration  
let server_cfg = tls_cfg.make_server_config(/*keylog=*/false)?;
let quic_server = server_cfg; // Ready for QUIC listener

For relay connections with custom TLS settings:

// Dialing a relay with TLS
use iroh_relay::client::MaybeTlsStreamBuilder;
use rustls::ClientConfig;

// Configure rustls with custom verification
let tls_cfg = ClientConfig::builder()
    .with_safe_defaults()
    .with_custom_certificate_verifier(Arc::new(my_verifier))
    .with_root_certificates(my_root_store)
    .with_no_client_auth();

let builder = MaybeTlsStreamBuilder::new(relay_url, dns_resolver, tls_cfg);
let stream = builder.connect().await?; // Returns MaybeTlsStream

Summary

  • Iroh uses TLS 1.3 over QUIC with raw public key authentication (RFC 7250) instead of X.509 certificates, implemented in iroh/src/tls.rs
  • The TlsConfig struct centralizes security state including session ticket caching (~150 KB limit) and cryptographic providers
  • Client and server configurations are generated via make_client_config and make_server_config with 0-RTT support and strict protocol version enforcement
  • The relay client maintains TLS security through MaybeTlsStreamBuilder in iroh-relay/src/client/tls.rs, supporting scheme-aware connection logic
  • All components provide end-to-end encryption, forward secrecy, and replay attack resistance without PKI infrastructure

Frequently Asked Questions

How does Iroh verify identity without Certificate Authorities?

Iroh implements raw public key authentication as defined in RFC 7250. Instead of validating X.509 certificate chains against trusted root CAs, the TLS handshake embeds the peer's public key directly. The ResolveRawPublicKeyCert resolver in iroh/src/tls.rs derives this key from the node's SecretKey, ensuring cryptographic identity verification without PKI infrastructure.

What TLS versions does Iroh support?

Iroh strictly enforces TLS 1.3 through the verifier::PROTOCOL_VERSIONS configuration. The implementation in iroh/src/tls.rs explicitly disables older TLS versions to prevent downgrade attacks and ensure forward secrecy through modern cipher suites.

Can Iroh TLS traffic be decrypted for debugging purposes?

Yes, Iroh supports optional key-logging via the SSLKEYLOGFILE environment variable. When enabled in make_client_config or make_server_config, the system logs TLS session keys that can be imported into tools like Wireshark. This feature is disabled by default in production builds to prevent information leakage.

How does Iroh prevent replay attacks with 0-RTT enabled?

While Iroh enables 0-RTT (early-data) for performance, it mitigates replay attacks by strictly bounding the session ticket cache to DEFAULT_MAX_TLS_TICKETS (approximately 150 KB). This limit prevents attackers from accumulating large numbers of tickets for replay attacks, as implemented in the TlsConfig memory-based cache.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →