Summary
JSS's did:nostr authentication makes end-to-end encryption available to pod clients today, with zero server-side changes. Clients sharing a pod can encrypt content using either NIP-44 (modern, authenticated, recommended) or NIP-04 (simple, legacy, widely deployed) — the same Nostr secp256k1 keypair that authenticates to JSS performs the ECDH key exchange. The pod stores ciphertext as ordinary RDF or blob content; JSS never sees plaintext.
This issue tracks the documentation work to make this pattern explicit for JSS users, and addresses the concern raised in solid/specification#788 (E2EE specification work item). The architectural insight: don't design new E2EE for Solid — leverage the existing Nostr primitives already deployed across the decentralized-web ecosystem.
Architecture: content-opaque storage, client-side encryption
Client A (did:nostr_A) Client B (did:nostr_B)
│ │
│ shared_secret = ECDH( │
│ privkey_A, pubkey_B) │
│ │
│ ciphertext = encrypt( │
│ content, shared_secret) │
│ │
├── PUT ciphertext ─────────┐ │
│ ▼ │
│ ┌────────────┐ │
│ │ JSS pod │ │
│ │ (stores │ │
│ │ ciphertext │ │
│ │ as RDF) │ │
│ └────────────┘ │
│ │ │
│ └─ GET ──┤
│ │
│ decrypt(ciphertext,│
│ ECDH(privkey_B, │
│ pubkey_A)) │
The pod's role is content-opaque storage — exactly as today. The encryption boundary is between clients. JSS does not implement encryption, decryption, or key management. This is the architecturally correct shape for E2EE: the server is not in the trust boundary.
Protocols
NIP-44 (recommended for new applications)
The current Nostr E2EE standard. Production-grade, authenticated, side-channel-resistant.
- Cipher: ChaCha20
- Authentication: HMAC-SHA256
- Key derivation: HKDF-SHA256 from ECDH shared secret
- Padding: length-hiding, power-of-two padding scheme
- Versioned wire format (current: v2)
- Spec: https://github.com/nostr-protocol/nips/blob/master/44.md
- External cryptographic review: design analyzed and reviewed pre-deployment
NIP-04 (simple, legacy, backwards-compatible)
The original Nostr DM encryption format. Simpler, widely deployed across older Nostr clients. Acceptable for backwards compatibility; new applications should use NIP-44.
JSS pods store ciphertext for both protocols identically — the wire format is just bytes from the server's perspective.
Ecosystem maturity
The Nostr E2EE ecosystem has substantial deployed infrastructure across multiple funded teams and cross-implementation interoperability:
- White Noise (https://www.whitenoise.chat/) — Nostr-native E2EE messenger; NIP-44 in production
- Damus, Amethyst, Nostur, Iris, Coracle — major Nostr clients with NIP-04 + NIP-44 implementations
- Client libraries across languages:
nostr-tools (JS), NDK (TS), nostr-rs / rust-nostr, nostr-php, python-nostr, nostr-sdk
- Tens of thousands of users sending NIP-04/NIP-44 traffic daily across the Nostr relay network
Adopting these primitives for Solid pod content reuses that maturity rather than reinventing it. New cryptographic protocol design carries years of standardization, review, and ecosystem-bootstrap risk; pointing at NIP-44 carries none of that.
Implementation scope
Server-side: none. JSS already supports did:nostr authentication. Pod content storage is already content-opaque; ciphertext stores exactly like plaintext.
Documentation:
- JSS docs page "E2EE for pod content" — pattern explanation + example code for encrypting before PUT and decrypting after GET
- JSS docs page "Authentication via did:nostr" — link to E2EE as a downstream capability
- README: brief mention of E2EE as a first-class capability under
did:nostr authentication
Optional (separate scope):
- Reference client demo (NIP-44 + JSS pod) as
examples/e2ee or in a separate repo
- Helper utilities for the encrypt-then-PUT / GET-then-decrypt pattern
- Compatibility tests against existing Nostr client libraries
Cross-reference: spec#788
solid/specification#788 proposes E2EE as a new spec work item. This pattern compresses that scope significantly: from "design new Solid-native E2EE protocol" to "document the bridge from did:nostr identity to existing NIP-44/NIP-04 primitives." The bridge already exists architecturally; only the documentation step is missing.
Acceptance
Summary
JSS's
did:nostrauthentication makes end-to-end encryption available to pod clients today, with zero server-side changes. Clients sharing a pod can encrypt content using either NIP-44 (modern, authenticated, recommended) or NIP-04 (simple, legacy, widely deployed) — the same Nostrsecp256k1keypair that authenticates to JSS performs the ECDH key exchange. The pod stores ciphertext as ordinary RDF or blob content; JSS never sees plaintext.This issue tracks the documentation work to make this pattern explicit for JSS users, and addresses the concern raised in solid/specification#788 (E2EE specification work item). The architectural insight: don't design new E2EE for Solid — leverage the existing Nostr primitives already deployed across the decentralized-web ecosystem.
Architecture: content-opaque storage, client-side encryption
The pod's role is content-opaque storage — exactly as today. The encryption boundary is between clients. JSS does not implement encryption, decryption, or key management. This is the architecturally correct shape for E2EE: the server is not in the trust boundary.
Protocols
NIP-44 (recommended for new applications)
The current Nostr E2EE standard. Production-grade, authenticated, side-channel-resistant.
NIP-04 (simple, legacy, backwards-compatible)
The original Nostr DM encryption format. Simpler, widely deployed across older Nostr clients. Acceptable for backwards compatibility; new applications should use NIP-44.
JSS pods store ciphertext for both protocols identically — the wire format is just bytes from the server's perspective.
Ecosystem maturity
The Nostr E2EE ecosystem has substantial deployed infrastructure across multiple funded teams and cross-implementation interoperability:
nostr-tools(JS),NDK(TS),nostr-rs/rust-nostr,nostr-php,python-nostr,nostr-sdkAdopting these primitives for Solid pod content reuses that maturity rather than reinventing it. New cryptographic protocol design carries years of standardization, review, and ecosystem-bootstrap risk; pointing at NIP-44 carries none of that.
Implementation scope
Server-side: none. JSS already supports
did:nostrauthentication. Pod content storage is already content-opaque; ciphertext stores exactly like plaintext.Documentation:
did:nostrauthenticationOptional (separate scope):
examples/e2eeor in a separate repoCross-reference: spec#788
solid/specification#788 proposes E2EE as a new spec work item. This pattern compresses that scope significantly: from "design new Solid-native E2EE protocol" to "document the bridge from
did:nostridentity to existing NIP-44/NIP-04 primitives." The bridge already exists architecturally; only the documentation step is missing.Acceptance
did:nostr→ NIP-44 pattern with example codedid:nostrcapabilities