Laan Tungir 5681f17f64 Fix NIP-04/NIP-44 interop gaps and NIP-42 id verification
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.
2026-09-27 18:10:37 -04:00
2026-08-13 12:42:40 -04:00
2026-08-13 12:42:40 -04:00
2026-09-27 10:24:10 -04:00
2026-09-27 10:24:10 -04:00
2026-09-27 10:24:10 -04:00

NOSTR Core Library — Rust

A Rust implementation of the NOSTR protocol library, ported from the C nostr_core_lib project.

Version License Build Status

📋 NIP Implementation Status

Core Protocol NIPs

  • NIP-01 — Basic protocol flow — event creation, signing, and validation
  • NIP-02 — Contact List and Petnames
  • NIP-03 — OpenTimestamps Attestations for Events
  • NIP-04 — Encrypted Direct Messages (legacy)
  • NIP-05 — Mapping Nostr keys to DNS-based internet identifiers
  • NIP-06 — Basic key derivation from mnemonic seed phrase
  • NIP-07 — window.nostr capability for web browsers
  • NIP-08 — Handling Mentions
  • NIP-09 — Event Deletion
  • NIP-10 — Conventions for clients' use of e and p tags in text events
  • NIP-11 — Relay Information Document
  • NIP-12 — Generic Tag Queries
  • NIP-13 — Proof of Work
  • NIP-14 — Subject tag in text events
  • NIP-15 — Nostr Marketplace
  • NIP-16 — Event Treatment
  • NIP-17 — Private Direct Messages
  • NIP-18 — Reposts
  • NIP-19 — bech32-encoded entities
  • NIP-20 — Command Results
  • NIP-21 — nostr: URI scheme
  • NIP-22 — Event created_at Limits
  • NIP-23 — Long-form Content
  • NIP-24 — Extra metadata fields and tags
  • NIP-25 — Reactions
  • NIP-26 — Delegated Event Signing
  • NIP-27 — Text Note References
  • NIP-28 — Public Chat
  • NIP-29 — Relay-based Groups
  • NIP-30 — Custom Emoji
  • NIP-31 — Dealing with Unknown Events
  • NIP-32 — Labeling
  • NIP-33 — Parameterized Replaceable Events
  • NIP-34 — git stuff
  • NIP-35 — Torrents
  • NIP-36 — Sensitive Content
  • NIP-37 — Draft Events
  • NIP-38 — User Statuses
  • NIP-39 — External Identities in Profiles
  • NIP-40 — Expiration Timestamp
  • NIP-42 — Authentication of clients to relays
  • NIP-44 — Versioned Encryption
  • NIP-45 — Counting results
  • NIP-46 — Nostr Remote Signing
  • NIP-47 — Wallet Connect
  • NIP-48 — Proxy Tags
  • NIP-49 — Private Key Encryption
  • NIP-50 — Search Capability
  • NIP-51 — Lists
  • NIP-52 — Calendar Events
  • NIP-53 — Live Activities
  • NIP-54 — Wiki
  • NIP-55 — Android Signer Application
  • NIP-56 — Reporting
  • NIP-57 — Lightning Zaps
  • NIP-58 — Badges
  • NIP-59 — Gift Wrap
  • NIP-60 — Cashu Wallet
  • NIP-61 — Nutzaps
  • NIP-62 — Log events
  • NIP-64 — Chess (PGN)
  • NIP-65 — Relay List Metadata
  • NIP-66 — Relay Monitor
  • NIP-68 — Web badges
  • NIP-69 — Peer-to-peer Order events
  • NIP-70 — Protected Events
  • NIP-71 — Video Events
  • NIP-72 — Moderated Communities
  • NIP-73 — External Content IDs
  • NIP-75 — Zap Goals
  • NIP-77 — Arbitrary custom app data
  • NIP-78 — Application-specific data
  • NIP-84 — Highlights
  • NIP-86 — Relay Management API
  • NIP-87 — Relay List Recommendations
  • NIP-88 — Stella: A Stellar Relay
  • NIP-89 — Recommended Application Handlers
  • NIP-90 — Data Vending Machines
  • NIP-92 — Media Attachments
  • NIP-94 — File Metadata
  • NIP-96 — HTTP File Storage Integration
  • NIP-98 — HTTP Auth
  • NIP-99 — Classified Listings

Legend: ✅ Implemented | ❌ Not Implemented

Implementation Summary: 14 of 96+ NIPs fully implemented (14.6%)

Workspace Structure

nostr_core_lib_rust/
├── core/              # Core types, errors, crypto, utilities
├── relay/             # WebSocket, HTTP, relay pool
├── nips/              # All NIP implementations
├── signer/            # Signer trait, local + signer remote
├── services/          # Request validator, Blossom, Cashu
├── nostr-core/        # Umbrella re-export crate
├── examples/          # Example programs
│   ├── keypair_generator/  # Generate Nostr keypairs
│   └── event_signer/       # Create and sign events
└── tests/             # Integration tests (ported from C)

Building

# Build all crates
cargo build

# Build release binaries
cargo build --release

# Run all tests (202 total)
cargo test --workspace

Usage

Generate a keypair

cargo run -p keypair-generator

Sign a text note

cargo run -p event-signer -- nsec1... "Hello, Nostr!"

Use as a library dependency

Add to your Cargo.toml:

[dependencies]
nostr-core = { git = "ssh://git@laantungir.net:2222/laantungir/nostr_core_lib_rust.git" }

Test Summary

Crate Tests Description
nostr-core 34 Types, errors, crypto, utilities
nostr-nips 68 All 14 NIP implementations
nostr-relay 8 WebSocket, HTTP, relay pool
nostr-signer 23 Signer trait, local + signer
nostr-services 31 Validator, Blossom, Cashu
integration-tests 38 Ported from C test suite
Total 202

Versioning

This project uses Semantic Versioning with a single source of truth in the VERSION file. The workspace version in Cargo.toml and the badge in README.md are kept in sync by the increment_and_push.sh script.

Releasing a new version

# Patch bump (bug fixes): 0.2.0 → 0.2.1
./increment_and_push.sh patch

# Minor bump (new features): 0.2.0 → 0.3.0
./increment_and_push.sh minor

# Major bump (breaking changes): 0.2.0 → 1.0.0
./increment_and_push.sh major

# Prerelease bump: 0.2.0 → 0.2.0-pre.1
./increment_and_push.sh prerelease

# Set an explicit version
./increment_and_push.sh 1.2.3

# Preview without modifying files or git
./increment_and_push.sh minor --dry-run

# Bump without pushing to origin
./increment_and_push.sh patch no-push

The script:

  1. Reads the current version from VERSION.
  2. Computes the next version per the requested bump type.
  3. Updates VERSION, the workspace version in Cargo.toml, and the badge in README.md.
  4. Moves the [Unreleased] section in CHANGELOG.md to the new version with today's date.
  5. Verifies the workspace still builds with cargo build --workspace.
  6. Creates a [release] vX.Y.Z commit and an annotated vX.Y.Z git tag.
  7. Pushes the branch and tag to origin (unless no-push).

Changelog

See CHANGELOG.md for a record of notable changes per release. Follow the Keep a Changelog format when adding entries under [Unreleased].

License

MIT

S
Description
No description provided
Readme
627 MiB
Languages
Rust 97.3%
Shell 2.7%