Harden unwrapGift for the receive side: verify the seal's BIP-340 signature
and recomputed id, enforce that the rumor's author matches the seal signer
(NIP-59 anti-spoofing), and check the rumor id against its contents. The
rumor is unsigned by design, so sender authentication rests on the seal.
Add UnwrapDirectMessage to NostrDmActor, returning the authenticated sender,
content, timestamp, and tags. Cover both with tests: an unwrap round-trip and
a rejection of a wrap whose inner rumor spoofs a different author.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add outbound NIP-17 private messaging: build the kind-14 rumor -> kind-13
seal -> kind-1059 gift wrap chain on the existing NIP-44 primitives, wrapped
in NostrDmActor (WrapDirectMessage/GiftWrapped). Publishing is left to
NostrPublishActor.
Extract nostrEventId() from signNostrEvent so the unsigned rumor can compute
its id without a signature. Export the new actor and nip17 helpers. Add a
round-trip test (wrap -> unwrap) and a negative decryption test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- nip19.dart: bech32 encodeNpub/encodeNsec for raw keys (no TLV entities),
verified against the canonical NIP-19 test vectors.
- nip05.dart: verifyNip05 with an injectable http.Client plus a pure
nip05MatchesPubkey helper for the .well-known/nostr.json check.
- fetchProfileFor(fetcher, pubkey): fetches and parses any user's kind-0 into
a typed NostrProfile (newest-wins), generalizing the own-key FetchProfile.
- Export all three from swarm.dart; unit tests for each (bech32 vectors,
MockClient HTTP cases, fake-relay profile parsing).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop-in replacement for NostrSignerActor that delegates signing to an
external signer over NIP-46 (bunker:// URI, NIP-44 encrypted kind-24133).
Includes 8 tests with a fully self-contained fake relay helper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>