Nostr: npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2
Your content. Your keys. Your rules. No platform required.
Protocol Spec · NIP Draft · LLM Reference · Contributing
Interactive explainer — open in browser and click to advance
Nostr content is either public or NIP-44 encrypted to specific recipients. There is no native mechanism for:
- Audience tiers — different groups seeing different content (family, close friends, subscribers)
- Revocable access — removing a recipient's ability to decrypt future content
- Scalable encryption — encrypting to hundreds of recipients without per-recipient encryption operations
Per-recipient NIP-44 encryption works for DMs but doesn't scale:
| Recipients | NIP-44 approach | Dominion |
|---|---|---|
| 1 | 1 encryption | 1 encryption + 1 key share |
| 10 | 10 encryptions | 1 encryption + 10 key shares |
| 100 | 100 encryptions | 1 encryption + 100 key shares |
| 1,000 | 1,000 encryptions | 1 encryption + 1,000 key shares |
Content is encrypted once with an epoch-based Content Key. Only the lightweight key distribution scales with audience size.
Dominion introduces vaults — encrypted content containers on standard Nostr relays:
- Derive a Content Key (CK) from your private key, the current epoch, and the tier
- Encrypt your content with the CK (AES-256-GCM) and publish to any relay
- Distribute the CK to each tier member via NIP-44 encrypted, NIP-59 gift-wrapped events
- Rotate — new epoch, new CK. Revoked members don't get the new key
No custom relay software. No middleware. No platform. Just standard Nostr events and proven cryptography.
| Use case | How Dominion helps |
|---|---|
| Creator paywall | Encrypt to paying subscribers; revoke on cancellation |
| Family sharing | Private family tier; rotate keys weekly |
| Close friends | Share selectively without making content public |
| Institutional access | Tiered access with automatic key expiry |
| Paid newsletters | One encryption operation, unlimited subscribers |
For scenarios requiring instant revocation (custody disputes, institutional SLA), optional warden relays provide true revocation using NIP-42 AUTH.
npm install dominion-protocolimport { deriveContentKey, contentKeyToHex, getCurrentEpochId, encrypt, decrypt } from 'dominion-protocol';
// Derive this week's Content Key for the "family" tier
const epochId = getCurrentEpochId(); // e.g. "2026-W11"
const ck = deriveContentKey(privateKeyHex, epochId, 'family');
// Encrypt content — one operation regardless of audience size
const ciphertext = encrypt('Hello family!', ck); // base64 string
const plaintext = decrypt(ciphertext, ck); // "Hello family!"import { defaultConfig, addToTier, removeFromTier, revokePubkey } from 'dominion-protocol';
let config = defaultConfig();
config = addToTier(config, 'family', alicePubkey);
config = addToTier(config, 'close_friends', bobPubkey);
config = revokePubkey(config, formerFriendPubkey); // excluded from next rotationimport { buildVaultShareEvent } from 'dominion-protocol/nostr';
// Build a kind 30480 vault share (caller handles NIP-44 + NIP-59 wrapping)
const event = buildVaultShareEvent(authorPubkey, recipientPubkey, ckHex, epochId, 'family');Split Content Keys across multiple parties or relays for redundancy:
import { splitCK, reconstructCK, encodeCKShare, decodeCKShare } from 'dominion-protocol';
const shares = splitCK(ck, 2, 3); // 2-of-3 threshold
const encoded = shares.map(encodeCKShare); // ["1:ab12...", "2:cd34...", "3:ef56..."]
const decoded = encoded.slice(0, 2).map(decodeCKShare);
const recovered = reconstructCK(decoded); // original CKTwo-layer exports — use what you need:
dominion-protocol— universal crypto primitives. Pure functions, zero Nostr knowledge. Works anywhere.dominion-protocol/nostr— Nostr event builders and parsers. Returns unsigned, unencrypted events. The caller handles NIP-44 encryption and NIP-59 gift wrapping.
| Primitive | Implementation |
|---|---|
| Key derivation | HKDF-SHA256 (@noble/hashes) |
| Content encryption | AES-256-GCM, 12-byte random IV (@noble/ciphers) |
| Secret sharing | Shamir over GF(256), irreducible polynomial 0x11b |
| Epoch format | ISO 8601 weeks (YYYY-Www) |
| Kind | Type | Purpose |
|---|---|---|
| 30480 | Parameterised replaceable | Vault share — epoch CK for a specific recipient |
| 30078 | NIP-78 app-specific data | Vault config — self-encrypted tier memberships |
Built on NIP-01, NIP-09, NIP-40, NIP-44, NIP-59, and NIP-78. No new cryptographic primitives.
See spec/protocol.md for the full protocol specification, including epoch rotation, tier management, individual grants, revocation, Lightning-gated access, and optional warden relay infrastructure.
For issues and feature requests, see GitHub Issues.
If you find Dominion useful, consider sending a tip:
- Lightning:
thedonkey@strike.me - Nostr zaps:
npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2