Skip to content

NeaByteLab/Trustless-ID

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trustless ID

Anonymous ID: request, decode, verify time-bound. No server, no storage.

Node Deno Bun Browser

Module type: ESM npm version JSR CI License

Features

  • Trustless — No server or DB; key from a shared identifier (connectorId) both sides agree on.
  • Connector-bound — Same connectorId = same pair; others can’t decode or verify.
  • Request, decode, verifyrequestdecode to codeIdverify with user input (number or digits).
  • Time-bound — Payloads expire automatically and predictably in 1–60 seconds (configurable).
  • Session IDhashId can be one-time per session (default) or stable per user for repeated identity proof.

Installation

Note

Prerequisites: For Deno install from deno.com. For npm use Node.js (e.g. nodejs.org).

npm:

npm install @neabyte/trustless-id

Deno (JSR):

deno add jsr:@neabyte/trustless-id

Quick Start

Use a connector ID (connectorId) (e.g. service URL or app identifier) on both sides. Generate a one-time hashId via generate(connectorId), create an instance via create(connectorId), build a requestId via request(hashId, expireTime?), then client decodes to a numeric code (codeId) to show the user; verifier checks the user-entered code with verify(requestId, secret).

import trustless from '@neabyte/trustless-id'

// Connector ID (same on both sides)
const connectorId = 'trustless://auth/example.com:0.1.0?service=none'

// One-time hashId per session
const hashId = trustless.generate(connectorId)

// Instance for connector (same on client and verifier)
const instance = trustless.create(connectorId)

// Build payload; send requestId to verifier (QR / link / form)
const requestId = instance.request(hashId, 10)

// Client decodes to get code (show to user so they can type it at verifier)
const codeId = instance.decode(hashId, requestId)
if (codeId !== null) {
  console.log('Code:', codeId)
  // Verifier side: check user-entered secret
  console.log('Verify:', instance.verify(requestId, codeId))
}

TOTP vs Trustless-ID

Aspect TOTP Trustless-ID
Secret A shared secret is generated and stored by both the server and the user (e.g. in an authenticator app). No stored secret. Only a connector ID (connectorId) (e.g. service URL or app identifier) is agreed on; the key is derived from it when needed.
Code derivation Code is computed from the shared secret and the current time window (e.g. 30s) using HMAC-SHA1. Code is derived from the session’s hashId and the encoded requestId using a FNV-1a–style mix; time is embedded in the request payload.
Server / backend A server (or backend) must store the secret per user and validate the code on each login. No server or database. Client uses same connectorId to derive key, decode to code; verifier uses same connectorId to verify the user-entered code locally.
Typical use Two-factor authentication (2FA): prove that the user possesses the shared secret at login time. One-time pairing or repeated identity: same connector; client uses requestdecode → code, verifier uses verify. Use a new hashId per session (anonymous) or one stable hashId per user (repeated proof, no server storage).

Documentation

  • USAGE.md — Full API, flow, and type reference; how to use the library end-to-end and every method.
  • USECASE.md — Use cases to clarify flow and architecture (actors, channels, secure vs leak conditions).

Build & Test

From the repo root (requires Deno).

Check — format, lint, and typecheck source:

deno task check

Unit tests — format/lint tests and run all tests:

deno task test

Tests live under tests/ (Trustless flow, Cipher, Security, Expiration, EdgeCases).

License

This project is licensed under the MIT license. See the LICENSE file for details.