Skip to content

nip44: add v3 (kind/scope-aware) encrypt/decrypt #322

@kwsantiago

Description

@kwsantiago

Assigned: @kwsantiago

Decision: build it, matching the reference signer (Amber)

NIP-44 v3 is not yet in the NIP-44 spec (v2 is current), but the reference signer ships a full implementation per the nostr-land/nip44v3 draft, so keep follows it for interop. Amber: Nip44v3 cipher + NIP44_V3_ENCRYPT / NIP44_V3_DECRYPT signer types + nip44v3Encrypt/Decrypt(plaintext, priv, pub, kind, scope).

Algorithm (from Amber Nip44v3.kt, version byte 0x03)

  • ECDH(secp256k1) → HKDF-SHA256, salt "nip44-v3\x00" || nonce (32-byte nonce), info encryption_key / mac_key.
  • ChaCha20 with an all-zeroes 96-bit nonce over padded plaintext (v2-style min-32 padding).
  • HMAC-SHA256 over nonce || kind || scope_len || scope || ciphertext.
  • kind + scope are authenticated alongside the ciphertext (cross-context replay protection) — the v3 distinction vs v2.
  • Wire (base64): version(0x03) || nonce(32) || mac(32) || kind(u32be) || scope_len(u32be) || scope || ciphertext.
  • Production must not allow caller-supplied nonce (Amber exposes a nonce overload for tests only).

Proposed work (RMP: crypto in Rust)

  • keep (Rust): add nip44_v3 to keep-core crypto alongside v2 (nip44_v3_encrypt/decrypt(plaintext, priv, pub, kind, scope)), fail-closed on malformed/short payloads + MAC mismatch + missing kind. Expose over FFI (keep-mobile). Port Amber's Nip44v3Test.kt vectors for parity.
  • keep-android: wire NIP44_V3_ENCRYPT / NIP44_V3_DECRYPT NIP-55 request types (kind + scope params) on both transports + the NIP-46 methods; distinct permission scope from v2; reject malformed v3 (missing kind) fail-closed.

Cadence

keep PR (cipher + FFI + tests) → merge → pin → keep-android PR (NIP-55/46 wiring + permission scope).

Priority

Emerging — v3 is a draft, but the reference signer implements it; build for interop parity.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestnip46NIP-46 remote signer protocolnip55NIP-55 signer protocolp2Priority

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions