npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@minerouter/mrsap

v1.1.1

Published

MRSAP — MineRouter Secure Application Protocol. End-to-end encrypted client-server communication with OPAQUE passwordless auth, mTLS device certificates, and optional WireGuard transport.

Readme

MRSAP — MineRouter Secure Application Protocol

End-to-end encrypted client-server communication with zero-knowledge password authentication.

OPAQUE (RFC 9807) + mTLS + Ed25519 + MML (Message Layer)

CI npm License Node TypeScript


Why MRSAP?

Every API today sends the user's password over the wire — even if it's over HTTPS, the server receives the plaintext password. A data breach, a rogue admin, or a logging misconfiguration and passwords are compromised.

MRSAP changes this:

  • The password is NEVER sent over the network. Not hashed, not encrypted — never transmitted.
  • OPAQUE (RFC 9807) uses zero-knowledge proofs: the server never learns the password, yet the client proves knowledge of it.
  • Each device gets a signed identity certificate, bound to the user.
  • Every message is encrypted, sequenced, and verified.
  • The server cannot reveal passwords even if fully compromised.

Key Features

| Feature | What it gives you | |---|---| | OPAQUE password auth | Password never leaves the client. Server doesn't know it. Zero-knowledge. | | Device certificates | Every device has a unique Ed25519 identity signed by your CA. | | MML Message Layer | Multiplexed streams, sequencing, heartbeat, priority per message. | | Session encryption | XChaCha20-Poly1305 per-message encryption with automatic key rotation. | | Transport agnostic | Works over TCP, TLS, WebSocket, WireGuard. You choose. | | Replay protection | Monotonic sequence numbers + timestamp window. | | No CA infrastructure | Your server IS the CA. Generate root keys once, issue device certs automatically. | | No X.509 complexity | Custom Ed25519-based certificate format — simple, auditable, no OpenSSL. |


How it works

CONNECTING ────► OPAQUE handshake ────► Device cert issued ────► Session active
                     │                          │                       │
                 password never              identity signed          every message
                 leaves client               by server CA             encrypted + signed

1. Server setup

import { Server } from '@minerouter/mrsap'

const server = new Server({
  port: 8443,
  storage: myDatabase,   // your Storage implementation
})
await server.listen()

2. Client connect

import { Client } from '@minerouter/mrsap'

// Get credentials from login form — NEVER hardcode them
const username = loginForm.username.value
const password = loginForm.password.value

const client = new Client({
  serverUrl: 'wss://api.myapp.com',
  storage: myVault,
  credentials: { username, password },
})
await client.connect()
// ◄── secure channel established
// ◄── password NEVER sent over network (used only for OPAQUE locally)

3. Make API calls

// RPC-style call
const data = await client.call('/api/users', { method: 'GET' })

// With body
const user = await client.call('/api/users', {
  method: 'POST',
  body: { name: 'Alice', role: 'admin' },
})

Complete Example

Server

import { Server, MemoryStorage } from '@minerouter/mrsap'

const server = new Server({
  port: 8443,
  storage: new MemoryStorage(),
})

server.on('connect', (session) => {
  console.log(`User ${session.username} connected from device ${session.deviceId}`)
})

server.on('call', async (session, call) => {
  if (call.path === '/api/ping') {
    return { status: 200, data: { pong: true, user: session.username } }
  }
  return { status: 404, data: { error: 'not found' } }
})

await server.listen()

Client

import { Client, MemoryStorage } from '@minerouter/mrsap'

const client = new Client({
  serverUrl: 'wss://localhost:8443',
  storage: new MemoryStorage(),
  credentials: { username: 'admin', password: '********' }, // from login form
})

await client.connect()
const result = await client.call('/api/ping')
console.log(result.data) // { pong: true, user: 'admin' }

API Reference

class Client

| Method | Description | |---|---| | new Client(config) | Create a client instance | | await client.connect() | Establish secure channel (OPAQUE + cert) | | await client.call(path, options) | Make an RPC call | | client.isConnected | Whether channel is active | | await client.heartbeat() | Send keepalive |

class Server

| Method | Description | |---|---| | new Server(config) | Create a server instance | | await server.listen() | Start listening for connections | | server.on(event, handler) | Register event handler | | await server.close() | Stop the server |

Events

server.on('connect', (session: ServerSession) => void)
server.on('disconnect', (session: ServerSession) => void)
server.on('call', (session: ServerSession, call: Call) => CallResult)

Configuration

type ClientConfig = {
  serverUrl: string
  storage: Storage           // your storage implementation
  credentials: { username: string; password: string }
}

type ServerConfig = {
  port: number
  storage: Storage
  caKey?: string             // optional: load existing CA
  caCert?: string
}

Storage Interface

Implement this to integrate with your database:

interface Storage {
  getUser(username: string): Promise<UserData | null>
  createUser(username: string, password: string, record: OpaqueRecord): Promise<UserRecord>
  getDevice(deviceId: string): Promise<DeviceRecord | null>
  saveDevice(device: DeviceRecord): Promise<void>
  saveSession(id: string, data: unknown): Promise<void>
  getSession(id: string): Promise<unknown | null>
  deleteSession(id: string): Promise<void>
}

Built-in implementations:

  • MemoryStorage — in-memory, for testing
  • FileStorage — JSON file, for development

Security Model

Protected against

| Threat | MRSAP | |---|---| | Password interception | ❌ Impossible — password never leaves client | | Server data breach | ❌ No password stored, only OPAQUE records | | Replay attack | ❌ Monotonic seq + timestamp ±30s | | Session hijack | ❌ Requires device private key + session key | | MITM | ❌ TLS + certificate verification | | Device impersonation | ❌ Each device has unique Ed25519 cert signed by CA | | Token theft | ❌ No tokens — per-message HMAC + seq |

NOT protected against

| Threat | Mitigation | |---|---| | Malware on client device | Use MRCV (HWID-encrypted key storage, sold separately) | | Compromised CA key | Physical isolation of CA key (offline backup) | | Quantum computer | Will add PQ-hybrid (Kyber + Dilithium) in v2.0 |

Certificate chain

Root CA (Ed25519, offline storage)
  └── Server identity (self-signed, known to client)
  └── Device certificates (issued per-device after OPAQUE)
        ├── Ed25519 key pair (generated on device)
        ├── Bound to: device_id, username
        └── Valid for: 365 days

MML — Message Layer

The MRSAP Message Layer provides the frame format for all communication:

┌──────────────────────────────────────────────┐
│ stream_id  (2 bytes)  — multiplexing stream   │
│ type       (1 byte)   — request/response/etc  │
│ flags      (1 byte)   — priority, EOF, ACK    │
│ seq        (4 bytes)  — anti-replay counter   │
│ ack        (4 bytes)  — last received seq     │
│ length     (4 bytes)  — body length            │
│ checksum   (4 bytes)  — integrity             │
├──────────────────────────────────────────────┤
│ Body (XChaCha20-Poly1305, session key)        │
└──────────────────────────────────────────────┘

Types: HEARTBEAT, REQUEST, RESPONSE, STREAM, ERROR


Transport

MRSAP is transport-agnostic. Choose what fits your use case:

| Transport | Latency | Complexity | Use case | |---|---|---|---| | TCP + TLS | 2-3 RTT | ✅ Simple | Web APIs, mobile apps | | WebSocket | 1 RTT | ✅ Simple | Browser apps, WebSocket-native | | QUIC | 0-1 RTT | 🟡 Medium | Low-latency, unreliable networks | | WireGuard | 0 RTT | 🔴 Advanced | Persistent tunnels, gaming, streaming |

TCP + TLS is the default. Bring your own transport — the Client and Server classes accept raw byte streams.


Why not...

...just use HTTPS + JWT?

JWT requires the server to issue a token. The token can be stolen, replayed, or forged (if signing key leaks). MRSAP's OPAQUE + session key + per-message HMAC eliminates token theft entirely.

...WebAuthn / Passkeys?

WebAuthn is browser-specific and requires a compatible authenticator (hardware key, phone). MRSAP works on any device that can run Node.js — servers, CLIs, IoT, mobile backends.

...just use TLS?

TLS protects the transport layer but does NOT authenticate the user. You still need to send a password or token inside the TLS session. MRSAP adds user authentication + device identity + end-to-end encryption on top of TLS.


Performance

| Operation | Time | Frequency | |---|---|---| | OPAQUE login | ~300-1000ms | Once per session (Argon2id) | | Ed25519 sign | ~0.05ms | Every message | | XChaCha20 encrypt (1KB) | ~0.001ms | Every message | | MML frame encode/decode | ~0.001ms | Every message | | Session key rotation | ~0.01ms | Every 1000 messages |


Use Cases

  • Backend APIs — secure microservice-to-microservice communication
  • IoT devices — authenticate devices without storing passwords
  • CLI tools — authenticate users for CLI commands without token files
  • Multiplayer games — persistent encrypted tunnels for game servers
  • Financial services — zero-knowledge password authentication
  • Healthcare — HIPAA-compliant encrypted data channels

Comparison

| Feature | HTTPS + JWT | TLS + mTLS | MRSAP | |---|---|---|---| | Password on wire | ✅ Plaintext | ✅ Plaintext | ❌ Never | | Server knows password | ✅ Yes | ✅ Yes | ❌ No | | Device identity | ❌ None | ✅ Certificate | ✅ Certificate | | Token theft | ✅ Possible | ❌ N/A | ❌ Impossible | | Replay protection | ❌ None | ✅ TLS | ✅ Seq + HMAC | | Key rotation | ❌ Manual | ❌ Manual | ✅ Auto | | Multiplexing | ❌ One req/conn | ❌ One req/conn | ✅ Streams | | Open standard | ✅ HTTP | ✅ TLS | ✅ RFC 9807 |


Roadmap

  • ✅ v1.0.0 — OPAQUE + mTLS + MML + session encryption
  • 🔜 v1.1.0 — WireGuard transport
  • 🔜 v1.2.0 — QUIC transport (0-RTT)
  • 🔜 v2.0.0 — Post-quantum hybrid (Kyber + Dilithium)
  • 🔜 v2.1.0 — Pub/Sub broker, file streaming

Platform Disclaimer

Tested on: Linux (Ubuntu 22.04+, Node 22).
Windows and macOS: Core tests pass on CI. OPAQUE WASM may require additional configuration.
Browser: Not currently supported (OPAQUE WASM works, but requires bundler configuration).

Feedback and bug reports welcome.


License

MIT