https://github.com/besoeasy/daku
Leave no trace. Just authenticate.
https://github.com/besoeasy/daku
authentication no-email passwordless
Last synced: 5 months ago
JSON representation
Leave no trace. Just authenticate.
- Host: GitHub
- URL: https://github.com/besoeasy/daku
- Owner: besoeasy
- Created: 2025-12-06T22:15:01.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-12-31T23:19:53.000Z (6 months ago)
- Last Synced: 2026-01-05T12:19:22.918Z (6 months ago)
- Topics: authentication, no-email, passwordless
- Language: JavaScript
- Homepage: https://www.npmjs.com/package/daku
- Size: 111 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# DAKU
> **Anonymous authentication & encryption. Zero personal data. One library.**
**DAKU** (Punjabi for "bandits") is a minimal cryptographic toolkit for building passwordless, privacy-first applications. No emails, no passwords, no databases of credentials to breach.
```bash
npm install daku
```
---
## Why DAKU?
| Traditional Auth | DAKU |
|------------------|------|
| Store emails & passwords | Just verify signatures |
| Hash passwords, manage resets | No passwords exist |
| GDPR compliance headaches | No PII collected |
| Database = honeypot for hackers | Nothing sensitive to steal |
| OAuth complexity | 3 functions to authenticate |
```javascript
import { generateKeyPair, createAuth, verifyAuth } from "daku";
// User creates identity (client-side, once)
const { privateKey, publicKey } = generateKeyPair();
// User logs in (client-side)
const token = await createAuth(privateKey);
// Server verifies (server-side)
const userId = await verifyAuth(token); // Returns publicKey or null
```
**That's it.** No signup forms, no email verification, no password resets.
---
## What DAKU Offers
### 🔑 Identity
```javascript
generateKeyPair() // Create new keypair identity
getPublicKey(privateKey) // Derive public key from private
getUsername(publicKey) // Human-readable name like "oceanrunning4523"
```
### 🎫 Authentication
```javascript
createAuth(privateKey, pow?) // Create login token (with spam protection)
verifyAuth(token, pow?) // Verify token, returns publicKey or null
```
### ✍️ Signatures
```javascript
sign(message, privateKey, pow?) // Sign any data
verify(message, sig, publicKey, pow?) // Verify signature
sha256(message) // SHA-256 hash
```
### 🔐 E2E Encryption
```javascript
deriveSharedSecret(myPrivate, theirPublic) // ECDH key agreement
encrypt(plaintext, key) // AES-256-GCM encrypt
decrypt(ciphertext, key) // AES-256-GCM decrypt
```
---
## 20+ Use Cases
| # | Use Case |
|---|----------|
| 1 | **Anonymous chat apps** — Users communicate without revealing identity or phone numbers |
| 2 | **Passwordless API authentication** — Clients sign requests instead of using API keys |
| 3 | **End-to-end encrypted messaging** — Private conversations only sender and receiver can read |
| 4 | **Anonymous feedback systems** — Collect honest feedback without identifying who submitted it |
| 5 | **Whistleblower platforms** — Secure, anonymous submission of sensitive information to journalists |
| 6 | **Decentralized identity** — Users own their identity, no central authority controls access |
| 7 | **IoT device authentication** — Devices authenticate without passwords or certificate authorities |
| 8 | **Wallet-based login** — Same keys work with Bitcoin/Ethereum ecosystems (secp256k1) |
| 9 | **Document signing** — Cryptographically sign contracts, agreements, or any digital document |
| 10 | **Anonymous voting systems** — Verify votes are legitimate without revealing who voted |
| 11 | **Encrypted file sharing** — Share files that only intended recipients can decrypt |
| 12 | **Private note-taking apps** — Notes encrypted locally, unreadable even if server breached |
| 13 | **Spam-resistant forms** — Proof-of-work prevents bots from mass-submitting without CAPTCHAs |
| 14 | **Multiplayer game authentication** — Players authenticate without creating accounts or emails |
| 15 | **Anonymous support tickets** — Users get help without revealing personal information |
| 16 | **Secure configuration sharing** — Share secrets between team members with E2E encryption |
| 17 | **Timestamped proof of existence** — Sign documents to prove they existed at specific time |
| 18 | **Private health apps** — Health data stays encrypted, only user can access it |
| 19 | **Anonymous marketplace** — Buy/sell without linking transactions to real identity |
| 20 | **Encrypted backups** — Backup data that only you can restore, even on untrusted storage |
| 21 | **CLI tool authentication** — Command-line tools authenticate without browser OAuth flows |
| 22 | **Peer-to-peer apps** — Direct encrypted communication between users without servers |
| 23 | **Private analytics** — Collect anonymous usage data without tracking individuals |
| 24 | **Secure team collaboration** — Group encryption for team channels and shared documents |
---
## How It Works
### Authentication Flow
```
┌─────────────────────────────────────────────────────────────┐
│ CLIENT │
│ │
│ 1. First visit: generateKeyPair() → save privateKey │
│ 2. Login: createAuth(privateKey) → token │
│ 3. Send token to server │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ SERVER │
│ │
│ 1. verifyAuth(token) → publicKey (user ID) │
│ 2. publicKey is the unique, permanent user identifier │
│ 3. No passwords, no emails, no database of credentials │
└─────────────────────────────────────────────────────────────┘
```
### E2E Encryption Flow
```
Alice Bob
│ │
│ 1. deriveSharedSecret(alice.priv, bob.pub) │
│ ═══════════════════════════════════ │
│ (Both derive SAME secret) │
│ ═══════════════════════════════════ │
│ 2. deriveSharedSecret(bob.priv, alice.pub) │
│ │
│ 3. encrypt("Hello", secret) ──────────────►│
│ ◄──────────────│ 4. decrypt(cipher, secret)
│ │
└─────────────────────────────────────────────┘
Only Alice & Bob can read messages
```
### Group Encryption
```javascript
import { deriveSharedSecret, encrypt, decrypt } from "daku";
import crypto from "node:crypto";
// Admin creates group key (just random 32 bytes)
const groupKey = crypto.randomBytes(32).toString("hex");
// Distribute to each member securely
for (const member of members) {
const secret = deriveSharedSecret(admin.privateKey, member.publicKey);
const encryptedKey = await encrypt(groupKey, secret);
// Send encryptedKey to member
}
// Member decrypts their copy
const memberSecret = deriveSharedSecret(member.privateKey, admin.publicKey);
const groupKey = await decrypt(encryptedKey, memberSecret);
// Everyone encrypts/decrypts with the shared group key
const message = await encrypt("Hello group!", groupKey);
```
---
## Security
| Feature | Implementation |
|---------|----------------|
| **Signatures** | secp256k1 ECDSA (same as Bitcoin/Ethereum) |
| **Encryption** | AES-256-GCM with random 96-bit IV |
| **Key Exchange** | ECDH (Elliptic Curve Diffie-Hellman) |
| **Hashing** | SHA-256 |
| **Spam Protection** | Proof-of-work (configurable difficulty) |
| **Token Expiry** | Auth tokens valid for 1 minute only |
### What DAKU Protects Against
- ✅ Password breaches (no passwords exist)
- ✅ Credential stuffing (nothing to stuff)
- ✅ Phishing (no credentials to phish)
- ✅ Database leaks (no PII stored)
- ✅ Replay attacks (1-minute token expiry)
- ✅ Spam/bots (proof-of-work)
- ✅ Man-in-the-middle (E2E encryption)
### User Responsibilities
- 🔑 Users must securely store their private key
- 🔑 Lost private key = lost identity (no recovery)
- 🔑 Compromised private key = compromised identity
---
## Examples
### Express.js Middleware
```javascript
import { verifyAuth, getUsername } from "daku";
async function authMiddleware(req, res, next) {
const token = req.headers.authorization?.replace("Bearer ", "");
const publicKey = await verifyAuth(token);
if (!publicKey) {
return res.status(401).json({ error: "Unauthorized" });
}
req.userId = publicKey;
req.username = getUsername(publicKey);
next();
}
```
### React Login
```javascript
import { generateKeyPair, createAuth } from "daku";
function useAuth() {
const login = async () => {
let privateKey = localStorage.getItem("privateKey");
if (!privateKey) {
const keys = generateKeyPair();
privateKey = keys.privateKey;
localStorage.setItem("privateKey", privateKey);
}
const token = await createAuth(privateKey);
return fetch("/api/login", {
headers: { Authorization: `Bearer ${token}` }
});
};
return { login };
}
```
### Encrypted Chat
```javascript
import { deriveSharedSecret, encrypt, decrypt } from "daku";
// Both users derive the same shared secret
const secret = deriveSharedSecret(myPrivateKey, theirPublicKey);
// Send encrypted message
const encrypted = await encrypt("Hello!", secret);
ws.send(encrypted);
// Receive and decrypt
ws.onmessage = async (e) => {
const message = await decrypt(e.data, secret);
console.log(message);
};
```
---
## API Reference
### `generateKeyPair()`
Creates a new secp256k1 keypair.
```javascript
const { privateKey, publicKey } = generateKeyPair();
// privateKey: 64-char hex (keep secret!)
// publicKey: 66-char hex (share freely)
```
### `getPublicKey(privateKey)`
Derives public key from private key.
```javascript
const publicKey = getPublicKey(privateKey);
```
### `getUsername(publicKey)`
Generates a deterministic human-readable username.
```javascript
const name = getUsername(publicKey); // "oceanrunning4523"
```
### `createAuth(privateKey, pow?)`
Creates a signed authentication token. Default POW difficulty is 2.
```javascript
const token = await createAuth(privateKey);
const token = await createAuth(privateKey, 3); // Higher difficulty
```
### `verifyAuth(token, pow?)`
Verifies an auth token. Returns `publicKey` on success, `null` on failure.
```javascript
const publicKey = await verifyAuth(token);
if (publicKey) {
// Authenticated! publicKey is the user ID
}
```
### `sign(message, privateKey, pow?)`
Signs a message with proof-of-work.
```javascript
const sig = await sign("Hello", privateKey);
// { signature: "...", pow: 123 }
```
### `verify(message, signatureData, publicKey, pow?)`
Verifies a signature.
```javascript
const isValid = await verify("Hello", sig, publicKey);
```
### `sha256(message)`
SHA-256 hash.
```javascript
const hash = await sha256("Hello"); // Uint8Array(32)
```
### `deriveSharedSecret(myPrivateKey, theirPublicKey)`
ECDH key agreement. Both parties derive the same secret.
```javascript
const secret = deriveSharedSecret(alice.privateKey, bob.publicKey);
// Same as: deriveSharedSecret(bob.privateKey, alice.publicKey)
```
### `encrypt(plaintext, key)`
AES-256-GCM encryption.
```javascript
const ciphertext = await encrypt("Secret message", sharedSecret);
```
### `decrypt(ciphertext, key)`
AES-256-GCM decryption. Returns `null` on failure.
```javascript
const plaintext = await decrypt(ciphertext, sharedSecret);
```
---
## Comparison
| Feature | DAKU | Passport.js | Auth0 | Firebase Auth |
|---------|------|-------------|-------|---------------|
| No passwords | ✅ | ❌ | ❌ | ❌ |
| No email required | ✅ | ❌ | ❌ | ❌ |
| No database needed | ✅ | ❌ | ❌ | ❌ |
| E2E encryption | ✅ | ❌ | ❌ | ❌ |
| Self-hosted | ✅ | ✅ | ❌ | ❌ |
| Zero dependencies* | ✅ | ❌ | ❌ | ❌ |
| Works offline | ✅ | ❌ | ❌ | ❌ |
| Bundle size | ~50KB | ~200KB | SDK required | SDK required |
*Only 2 peer dependencies: `@noble/secp256k1` and `@noble/hashes`
---
## Installation
```bash
npm install daku
```
**Requirements:** Node.js 16+ or modern browser
---
## License
ISC © [besoeasy](https://github.com/besoeasy)
---
Leave no trace. Just authenticate.