An HTTP client and server built on top of @hyperswarm/secret-stream for end-to-end encrypted HTTP communication over TCP.
- End-to-end encryption - All HTTP traffic is encrypted using Hyperswarm's SecretStream protocol
- Identity verification - Cryptographic verification of server identity via public keys
- Drop-in replacement - Compatible with standard
fetch()API and HTTP servers - Custom key pairs - Support for persistent client identities across requests
- Connection pooling - Built on Undici for efficient connection management
npm install secret-stream-httpimport { fetch } from 'secret-stream-http'
const response = await fetch('http://localhost:3000/hello')
console.log(await response.text())The fetch() function works just like the standard Fetch API but automatically
encrypts all communication using SecretStream.
import { createServer as createHttpServer } from 'node:http'
import { createServer } from 'secret-stream-http'
// Create your HTTP handler
const httpServer = createHttpServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello, World!')
})
// Wrap it with SecretStream encryption
const server = createServer(httpServer)
server.listen(3000, () => {
console.log('Server listening on port 3000')
console.log('Server public key:', server.publicKey.toString('hex'))
})By default, a global agent with a random key pair is used. You can provide custom key pairs for persistent client identities:
import { fetch, Agent } from 'secret-stream-http'
// Generate a key pair
const keyPair = Agent.keyPair()
// Create an agent with the key pair
const agent = new Agent({ keyPair })
// Use per-request
const response = await fetch('http://localhost:3000/', {
dispatcher: agent,
})import { setGlobalDispatcher, Agent } from 'secret-stream-http'
const keyPair = Agent.keyPair()
const agent = new Agent({ keyPair })
setGlobalDispatcher(agent)
// All subsequent fetch calls will use this agent
await fetch('http://localhost:3000/')Verify that you're connecting to the expected server by pinning its public key:
import { Agent } from 'secret-stream-http'
// Get the server's public key (e.g., from server.publicKey)
const serverPublicKey = Buffer.from('...', 'hex')
const agent = new Agent({
remotePublicKey: serverPublicKey,
})
// This will only succeed if connected to the server with matching public key
const response = await fetch('http://localhost:3000/', {
dispatcher: agent,
})Attempting to connect to a server with a different public key will result in an error:
Error: Remote public key does not match expected key
Generate and reuse server key pairs for persistent server identities:
import { createServer, Agent } from 'secret-stream-http'
const keyPair = Agent.keyPair()
const server = createServer(httpServer, { keyPair })
console.log('Public key:', server.publicKey.toString('hex'))Access the client's public key in your server handlers:
import { createServer } from 'node:http'
const httpServer = createServer((req, res) => {
const clientPublicKey = req.socket.remotePublicKey
console.log('Client public key:', clientPublicKey.toString('hex'))
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Authenticated')
})Standard Fetch API with automatic SecretStream encryption. The dispatcher
option can be used to specify a custom agent.
Creates a new HTTP agent for encrypted connections.
Options:
keyPair?: { publicKey: Buffer, secretKey: Buffer }- Key pair for client identity (generated if not provided)remotePublicKey?: Buffer- Expected server public key for identity verification- All other Undici Agent options
Static method to generate a new cryptographic key pair.
Set the default agent used by all fetch() calls.
Get the current global dispatcher.
Wraps an HTTP server with SecretStream encryption.
Parameters:
httpServer- Node.js HTTP server instanceoptions.keyPair?- Server key pair (generated if not provided)
Returns: TCP server with publicKey property
The returned server is a standard Node.js TCP server. Call .listen() to start
accepting connections.
-
Client side: The
Agentcreates a TCP connection and wraps it with Hyperswarm's SecretStream for encryption before making HTTP requests. -
Server side: The TCP server accepts connections, wraps each socket with SecretStream, and forwards the decrypted stream to the HTTP server.
-
Encryption: All HTTP traffic (including headers and body) is encrypted end-to-end using the Noise protocol via SecretStream.
-
Authentication: Public keys are exchanged during the SecretStream handshake, allowing both parties to verify each other's identity.
MIT License. See LICENSE file for details.