Echalote
Zero-copy Tor protocol for the web 🏎️ (JS + WebAssembly)
Install / Use
/learn @hazae41/EchaloteREADME
npm i @hazae41/echalote
Node Package 📦 • Online Demo 🌐 • Next.js CodeSandbox 🪣
Use at your own risk
This is experimental software in early development
- It has security issues
- Things change quickly
Features
Current features
- 100% TypeScript and ESM
- Zero-copy reading and writing
- Works in the browser
- All cryptography use either WebCrypto or reproducible WebAssembly ports of Rust implementations
- Unsafe Tor protocol (with Ed25519, ntor, kdf-tor)
- Meek (HTTP) transport (without domain-fronting)
- Snowflake (WebRTC/WebSocket) transport (without domain-fronting)
- Unsafe TLS using Cadenas
- HTTP and WebSocket messaging using Fleche
Upcoming features
- Better security
Usage
import { createWebSocketSnowflakeStream, TorClientDuplex, Consensus } from "@hazae41/echalote"
import { Ciphers, TlsClientDuplex } from "@hazae41/cadenas"
const tcp = await createWebSocketSnowflakeStream("wss://snowflake.bamsoftware.com/")
const tor = new TorClientDuplex()
tcp.outer.readable.pipeTo(tor.inner.writable).catch(() => {})
tor.inner.readable.pipeTo(tcp.outer.writable).catch(() => {})
await tor.waitOrThrow()
using circuit = await tor.createOrThrow()
const consensus = await Consensus.fetchOrThrow(circuit)
const middles = consensus.microdescs.filter(it => true
&& it.flags.includes("Fast")
&& it.flags.includes("Stable")
&& it.flags.includes("V2Dir"))
const exits = consensus.microdescs.filter(it => true
&& it.flags.includes("Fast")
&& it.flags.includes("Stable")
&& it.flags.includes("Exit")
&& !it.flags.includes("BadExit"))
const middle = middles[Math.floor(Math.random() * middles.length)]
const middle2 = await Consensus.Microdesc.fetchOrThrow(circuit, middle)
await circuit.extendOrThrow(middle2, AbortSignal.timeout(5000))
const exit = exits[Math.floor(Math.random() * middles.length)]
const exit2 = await Consensus.Microdesc.fetchOrThrow(circuit, exit)
await circuit.extendOrThrow(exit2, AbortSignal.timeout(5000))
const ttcp = await circuit.openOrThrow("twitter.com", 443)
const ciphers = [Ciphers.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
const ttls = new TlsClientDuplex({ host_name: url.hostname, ciphers })
ttcp.outer.readable.pipeTo(ttls.inner.writable).catch(() => { })
ttls.inner.readable.pipeTo(ttcp.outer.writable).catch(() => { })
const response = await fetch("https://twitter.com", { stream: ttls.outer })
const text = await response.text()
Related Skills
himalaya
346.8kCLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
taskflow
346.8kname: taskflow description: Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layer
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
