The 0.1.1 and 0.1.2 fixes passed the test suite because every crypto test
only round-tripped our own output, which a wrong-but-symmetric
implementation also passes. Verified all paths against `nak` and found a
third instance of the same class of bug still live in the released code.
- Signer (CRITICAL): LocalSigner::nip04_encrypt/decrypt still used a private
copy of the pre-0.1.1 NIP-04 code (SHA-256-hashed ECDH key, base64(iv||ct)
layout), so it could neither read nor produce standard NIP-04 DMs. NIP-04
now lives only in nostr_core::crypto::nip04; nostr_nips::nip004 re-exports
it and LocalSigner delegates to it.
- NIP-44: reject empty plaintext on encrypt and on decrypt (length prefix 0)
per spec; bound payload length to 99..=65603. We previously emitted
payloads that nak rejects with "invalid padding".
- NIP-42 (security): verify_auth_event now recomputes the event id. Tags and
content could be altered after signing and the event still verified,
because only the signature over the claimed id was checked.
- Docs: keys.rs claimed NIP-44 uses the hashed ECDH output, the exact
mix-up behind the 0.1.2 fix. Corrected, and ecdh_shared_secret now warns
that no NIP uses it.
Tests:
- nak-generated known-answer vectors for NIP-04, NIP-44 and LocalSigner; the
integration NIP-04 "known_vectors" test now checks real ciphertext
byte-for-byte instead of round-tripping.
- Official NIP-06 spec vectors; real RFC 5869 HKDF, HMAC-SHA512 and PBKDF2
values (these previously asserted only output length, and the HMAC-SHA512
expected constant was fabricated and never compared).
- Fixed mistyped BIP-32 chain codes in NIP-06 test comments.
- Negative tests: tampered NIP-44 MAC/ciphertext, zero length prefix,
malformed NIP-04 input, NIP-42 tampered body / bad sig / wrong relay /
stale timestamp.
- Documented the rule in tests/src/lib.rs: every encryption scheme needs at
least one vector from an independent implementation.