# What Is subtle‑tls and How It Powers WebAssembly TLS in webtor‑rs

> Discover subtle-tls, a WebAssembly TLS 1.3 client powering webtor-rs. Learn how it leverages the browser's SubtleCrypto API for secure HTTPS without native dependencies.

- Repository: [igor53627/webtor-rs](https://github.com/igor53627/webtor-rs)
- Tags: deep-dive
- Published: 2026-03-04

---

**subtle‑tls is a lightweight TLS 1.3 client library for WebAssembly that delegates cryptographic operations to the browser's SubtleCrypto API, enabling secure HTTPS and Snowflake transport in webtor‑rs without native dependencies.**

The `igor53627/webtor‑rs` repository implements a fully functional Tor client in Rust that compiles to WebAssembly for browser environments. Because standard TLS libraries like `ring` cannot target WASM, the project includes **subtle‑tls** as a specialized alternative that bridges the Tor protocol stack with browser-native cryptography.

## What Is subtle‑tls?

**subtle‑tls** is a TLS 1.3 implementation (with automatic TLS 1.2 fallback) designed specifically for `wasm32` targets. Unlike conventional Rust TLS crates that depend on native cryptographic libraries, it routes all crypto operations through the browser's **SubtleCrypto** API using `js‑sys` and `web‑sys` bindings.

Key capabilities include:

- **TLS 1.3 primary with TLS 1.2 fallback**: The client negotiates TLS 1.3 automatically and falls back to TLS 1.2 only when the modern handshake fails.
- **Hybrid key exchange**: Uses P‑256 ECDH via SubtleCrypto and X25519 via a pure‑Rust implementation.
- **Modern cipher suites**: AES‑128‑GCM and AES‑256‑GCM through SubtleCrypto, with ChaCha20‑Poly1305 available as a pure‑Rust fallback.
- **Embedded certificate validation**: Ships with a minimal Let’s Encrypt root store (~3.5 KB) including hostname verification.
- **Async stream interface**: Exposes `TlsStream<S>` that implements `AsyncRead` and `AsyncWrite` for integration with async Rust ecosystems.

All code resides under `#[cfg(target_arch = "wasm32")]` guards, ensuring it compiles only into WebAssembly bundles.

## How webtor‑rs Uses subtle‑tls

In the `webtor‑rs` codebase, **subtle‑tls** serves as the exclusive TLS implementation when targeting WASM. It secures two critical communication paths:

### HTTPS Requests Over Tor Circuits

When `TorClient::request` in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) detects an `https://` URL, it constructs a `TlsConfig` specifying TLS 1.3 as the primary version with TLS 1.2 as fallback. The code invokes `TlsConnector::connect` to wrap the raw Tor circuit stream, producing a `TlsStream` that encrypts the HTTP traffic.

```rust
let config = TlsConfig {
    skip_verification: false,
    alpn_protocols: vec!["http/1.1".to_string()],
    version: TlsVersion::Tls13,
};
let connector = TlsConnector::with_config(config);

match connector.connect(stream, &host).await {
    Ok(mut tls_stream) => {
        execute_http_request_wasm(&mut tls_stream, &request_bytes).await?;
    }
    Err(tls13_err) => {
        // Fallback to TLS 1.2
        let config_tls12 = TlsConfig {
            skip_verification: false,
            alpn_protocols: vec!["http/1.1".to_string()],
            version: TlsVersion::Tls12,
        };
        let connector_tls12 = TlsConnector::with_config(config_tls12);
        let mut tls_stream = connector_tls12.connect_tls12(stream_tls12, &host).await?;
        execute_http_request_wasm_tls12(&mut tls_stream, &request_bytes).await?;
    }
}

```

The `execute_http_request_wasm` helper manages async read/write operations on the encrypted stream. See the TLS implementation block in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) (lines 199–236).

### Snowflake WebSocket Transport

For the Snowflake bridge—available only in browser builds—the transport stack builds a pipeline from WebSocket through Turbo, KCP, and SMUX layers. In [`webtor/src/snowflake_ws.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/snowflake_ws.rs), the code applies a `TlsConnector` with `skip_verification = true` to the SMUX stream because Snowflake uses self‑signed certificates.

```rust
let tls_config = TlsConfig {
    skip_verification: true, // Snowflake uses self-signed certs
    alpn_protocols: vec![],
    ..Default::default()
};
let connector = TlsConnector::with_config(tls_config);
let tls_stream = connector.connect(smux, "www.example.com").await?;

```

This yields a `TlsStream` that encrypts Snowflake traffic before it enters the Tor network. The TLS wrapping occurs at lines 140–152 of [`webtor/src/snowflake_ws.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/snowflake_ws.rs).

## Why SubtleCrypto Instead of Native TLS?

Standard Rust TLS libraries rely on `ring` or other native cryptographic implementations that cannot compile to WebAssembly. Additionally, browsers lack support for `std::time::Instant` and block direct access to OS‑level cryptographic facilities.

**subtle‑tls** solves these constraints by delegating to the browser's **SubtleCrypto** API. This approach provides hardware‑accelerated, standards‑compliant cryptography across all modern browsers without requiring WASM-bindgen shims for system libraries.

## Key Source Files

Understanding the integration requires examining these specific locations in the `igor53627/webtor‑rs` repository:

- **`subtle‑tls/src/lib.rs`**: Defines the public API including `TlsConnector`, `TlsConfig`, and `TlsStream`.
- **[`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs)**: Contains the HTTPS request logic that selects `subtle‑tls` for WASM targets (lines 199–236).
- **[`webtor/src/snowflake_ws.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/snowflake_ws.rs)**: Implements the Snowflake bridge stack with TLS wrapping after SMUX (lines 140–152).
- **`subtle‑tls/README.md`**: Documents the architecture, testing procedures, and design rationale.

## Summary

- **subtle‑tls** is a WebAssembly‑specific TLS 1.3/1.2 client that replaces native crypto with browser SubtleCrypto APIs.
- It enables HTTPS requests in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) by wrapping Tor circuit streams with `TlsConnector::connect` and providing automatic version fallback.
- It secures the Snowflake bridge in [`webtor/src/snowflake_ws.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/snowflake_ws.rs) by applying TLS to SMUX streams with certificate verification disabled for self‑signed Snowflake certs.
- The library is conditionally compiled under `#[cfg(target_arch = "wasm32")]` and integrates with the async ecosystem via `AsyncRead`/`AsyncWrite` traits.

## Frequently Asked Questions

### What makes subtle‑tls different from rustls or native‑tls?

**subtle‑tls** is built exclusively for WebAssembly environments. While **rustls** depends on `ring` for cryptographic primitives and **native‑tls** binds to OpenSSL or Schannel, **subtle‑tls** delegates all operations to the browser's SubtleCrypto API. This eliminates native dependencies that cannot compile to WASM while providing hardware acceleration through the browser.

### Does subtle‑tls support modern TLS 1.3 features?

Yes. **subtle‑tls** prioritizes TLS 1.3 negotiation and automatically falls back to TLS 1.2 only when the remote server fails the modern handshake. It supports TLS 1.3 cipher suites including AES‑128‑GCM and AES‑256‑GCM via SubtleCrypto, plus X25519 and ChaCha20‑Poly1305 through pure‑Rust fallbacks.

### Why does the Snowflake transport skip certificate verification?

The Snowflake bridge in [`webtor/src/snowflake_ws.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/snowflake_ws.rs) uses `skip_verification: true` because Snowflake servers employ self‑signed certificates that would fail standard validation. This is a deliberate security trade‑off for the specific Snowflake transport path, while standard HTTPS requests in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) enforce full certificate validation against the embedded Let’s Encrypt root store.

### Can subtle‑tls be used outside of webtor‑rs?

Yes. Although designed for the `webtor‑rs` project, **subtle‑tls** is a standalone crate within the repository that can be imported into any Rust project targeting `wasm32`. It provides a standard `TlsConnector` interface compatible with any stream implementing `AsyncRead` and `AsyncWrite`, making it suitable for general‑purpose WASM TLS needs.