Skip to content

Conversation

@tcheeric
Copy link
Owner

Summary

This pull request addresses issues with NIP-44 key derivation, improving compliance with the specification and fixing critical interoperability bugs. It also enhances error handling and updates documentation to reflect best practices.

What changed?

  • Refactored NIP-44 key derivation to use proper HKDF-Extract and HKDF-Expand methods instead of PBKDF2.
  • Improved error handling for unknown Kind enum values.
  • Refactored WebSocket response handling to use CompletableFuture, enabling more robust event-driven notifications.
  • Updated coding guidelines with detailed principles and best practices.
  • Released patch version 1.2.1 to include these fixes.

BREAKING

⚠️ BREAKING: Previously encrypted ciphertext is not compatible with the updated NIP-44 key derivation. Migrating requires re-encrypting messages with the new method.

Review focus

  • Is the updated key derivation strictly compliant with NIP-44?
  • Does the use of CompletableFuture for WebSocket responses align with event-driven design principles?

Checklist

  • Scope ≤ 300 lines (or split/stack)
  • Title is verb + object (e.g., “Refactor auth middleware to async”)
  • Description links the issue and answers “why now?”
  • BREAKING flagged if needed
  • Tests/docs updated (if relevant)

tcheeric and others added 7 commits December 26, 2025 11:17
The NIP-44 specification requires HKDF for key derivation:
- conversation_key = HKDF-Extract(salt="nip44-v2", ikm=shared_x)
- keys = HKDF-Expand(prk=conversation_key, info=nonce, L=76)

The previous implementation incorrectly used PBKDF2WithHmacSHA256,
which caused decryption failures when interoperating with other
NIP-44 implementations (e.g., nostr-tools in JavaScript).

Changes:
- getConversationKey: Use HKDFBytesGenerator with salt for extract
- getMessageKeys: Use HKDFParameters.skipExtractParameters for expand
- Remove unused PBKDF2 imports and constants
- Simplify getConversationKey signature (no longer throws checked exceptions)

This fix enables DM interoperability between Java backend and
JavaScript frontend implementations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Breaking change: NIP-44 now uses correct HKDF key derivation.
Ciphertext encrypted with previous versions will not decrypt.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
HKDF-Extract is defined as HMAC-Hash(salt, IKM), not the full
HKDF Extract+Expand. The previous fix incorrectly used
HKDFBytesGenerator.generateBytes() which performs both steps.

Now uses Mac with HmacSHA256 directly for Extract, which matches
the nostr-tools implementation and NIP-44 specification.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Projects updated:
- nostr-java: 1.2.0 → 1.2.1 (patch)
- All modules: 1.2.0 → 1.2.1 (patch)

Fixes included:
- NIP-44 HKDF-Extract for conversation key derivation
- Kind enum error handling for unknown values
- WebSocket CompletableFuture response handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors NIP-44 encryption to use proper HKDF key derivation instead of PBKDF2, improving cryptographic compliance and interoperability. It also enhances error handling for unknown Kind enum values and refactors WebSocket client response handling to use CompletableFuture for more reliable event-driven notifications.

Changes:

  • Replaced PBKDF2 with HKDF-Extract and HKDF-Expand in NIP-44 key derivation for compliance with the specification
  • Changed Kind.valueOf() to throw IllegalArgumentException for unknown kinds instead of silently returning TEXT_NOTE
  • Refactored StandardWebSocketClient to use CompletableFuture instead of polling-based await mechanism

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pom.xml (multiple) Version bumped from 1.1.1 to 1.2.1 across all modules
nostr-java-crypto/src/main/java/nostr/crypto/nip44/EncryptedPayloads.java Implemented proper HKDF-Extract and HKDF-Expand for NIP-44 key derivation
nostr-java-encryption/src/main/java/nostr/encryption/MessageCipher44.java Removed now-unnecessary exception handling from getConversationKey()
nostr-java-base/src/main/java/nostr/base/Kind.java Changed valueOf() to throw exception for unknown kinds instead of returning TEXT_NOTE
nostr-java-client/src/main/java/nostr/client/springwebsocket/StandardWebSocketClient.java Refactored to use CompletableFuture for event-driven response handling
nostr-java-event/src/test/java/nostr/event/unit/Nip60FilterJsonTest.java Added test for NIP-60 filter JSON serialization
nostr-java-api/src/test/resources/strfry.conf Added strfry relay configuration for integration testing
CHANGELOG.md Updated with 1.2.1 release notes
AGENTS.md Added comprehensive coding guidelines and NIP references
CLAUDE.md Added repository documentation for Claude Code assistant

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a53b78a26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

tcheeric added 4 commits January 21, 2026 03:35
Added `findByValue` for Optional-based Kind lookups and `valueOfStrict` for strict validation, improving flexibility and error handling for unknown or custom kinds.
Added tests for `valueOfStrict` and `findByValue` methods, ensuring strict validation and Optional-based lookups for unknown, valid, and invalid range Kind values.
Replaced responseFuture and events with a thread-safe PendingRequest encapsulating CompletableFuture and event list. Improved response handling, added termination signal checks, and enhanced error handling for WebSocket communication.
@tcheeric tcheeric merged commit 4722425 into develop Jan 21, 2026
1 of 2 checks passed
@tcheeric tcheeric deleted the fix/ws-response-detection branch January 21, 2026 03:44
@tcheeric tcheeric mentioned this pull request Jan 21, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants