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.
npm install daku
Why 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 |
import { generateKeyPair, createAuth, verifyAuth } from "daku";
const { privateKey, publicKey } = generateKeyPair();
const token = await createAuth(privateKey);
const userId = await verifyAuth(token);
That's it. No signup forms, no email verification, no password resets.
What DAKU Offers
🔑 Identity
generateKeyPair()
getPublicKey(privateKey)
getUsername(publicKey)
🎫 Authentication
createAuth(privateKey, pow?)
verifyAuth(token, pow?)
✍️ Signatures
sign(message, privateKey, pow?)
verify(message, sig, publicKey, pow?)
sha256(message)
🔐 E2E Encryption
deriveSharedSecret(myPrivate, theirPublic)
encrypt(plaintext, key)
decrypt(ciphertext, key)
20+ Use Cases
| 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
import { deriveSharedSecret, encrypt, decrypt } from "daku";
import crypto from "node:crypto";
const groupKey = crypto.randomBytes(32).toString("hex");
for (const member of members) {
const secret = deriveSharedSecret(admin.privateKey, member.publicKey);
const encryptedKey = await encrypt(groupKey, secret);
}
const memberSecret = deriveSharedSecret(member.privateKey, admin.publicKey);
const groupKey = await decrypt(encryptedKey, memberSecret);
const message = await encrypt("Hello group!", groupKey);
Security
| 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
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
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
import { deriveSharedSecret, encrypt, decrypt } from "daku";
const secret = deriveSharedSecret(myPrivateKey, theirPublicKey);
const encrypted = await encrypt("Hello!", secret);
ws.send(encrypted);
ws.onmessage = async (e) => {
const message = await decrypt(e.data, secret);
console.log(message);
};
API Reference
generateKeyPair()
Creates a new secp256k1 keypair.
const { privateKey, publicKey } = generateKeyPair();
getPublicKey(privateKey)
Derives public key from private key.
const publicKey = getPublicKey(privateKey);
getUsername(publicKey)
Generates a deterministic human-readable username.
const name = getUsername(publicKey);
createAuth(privateKey, pow?)
Creates a signed authentication token. Default POW difficulty is 2.
const token = await createAuth(privateKey);
const token = await createAuth(privateKey, 3);
verifyAuth(token, pow?)
Verifies an auth token. Returns publicKey on success, null on failure.
const publicKey = await verifyAuth(token);
if (publicKey) {
}
sign(message, privateKey, pow?)
Signs a message with proof-of-work.
const sig = await sign("Hello", privateKey);
verify(message, signatureData, publicKey, pow?)
Verifies a signature.
const isValid = await verify("Hello", sig, publicKey);
sha256(message)
SHA-256 hash.
const hash = await sha256("Hello");
deriveSharedSecret(myPrivateKey, theirPublicKey)
ECDH key agreement. Both parties derive the same secret.
const secret = deriveSharedSecret(alice.privateKey, bob.publicKey);
encrypt(plaintext, key)
AES-256-GCM encryption.
const ciphertext = await encrypt("Secret message", sharedSecret);
decrypt(ciphertext, key)
AES-256-GCM decryption. Returns null on failure.
const plaintext = await decrypt(ciphertext, sharedSecret);
Comparison
| 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
npm install daku
Requirements: Node.js 16+ or modern browser
License
ISC © besoeasy
Leave no trace. Just authenticate.