Skip to content

feat(nwcp): add NIP-44 v2 encryption - #51

Open
satwise wants to merge 1 commit into
lnbits:mainfrom
satwise:feat/nip44-v2
Open

feat(nwcp): add NIP-44 v2 encryption#51
satwise wants to merge 1 commit into
lnbits:mainfrom
satwise:feat/nip44-v2

Conversation

@satwise

@satwise satwise commented Jul 4, 2026

Copy link
Copy Markdown

Summary

  • advertise nip44_v2 nip04 in the NIP-47 kind-13194 info event
  • decrypt NIP-44 v2 request events when the request includes ["encryption", "nip44_v2"]
  • encrypt responses with the same scheme requested by the client while preserving NIP-04 fallback
  • add coverage for the published NIP-44 vector and NIP-44 request/response handling

Closes #41

Testing

  • uvx ruff check nwcp.py tests/unit/test_nwcp.py
  • uvx black --check nwcp.py tests/unit/test_nwcp.py
  • python -m py_compile nwcp.py tests/unit/test_nwcp.py
  • direct NIP-44 harness with real pynostr, coincurve==20.0.0, cryptography, loguru, and websockets plus lightweight LNbits stubs

Note: full uv run pytest is blocked in this Windows environment because LNbits pulls uvloop, which does not support Windows.

Copilot AI review requested due to automatic review settings July 4, 2026 15:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds NIP-44 v2 support to NWCServiceProvider so the provider can advertise, decrypt requests, and encrypt responses using nip44_v2, while preserving nip04 as a fallback for compatibility with existing clients.

Changes:

  • Add NIP-44 v2 encrypt/decrypt implementation (HKDF-SHA256 + ChaCha20 + HMAC-SHA256) and route request/response handling based on an encryption tag.
  • Advertise supported encryptions (nip44_v2 nip04) in the kind-13194 info event.
  • Add unit tests for the published NIP-44 v2 vector and for end-to-end request/response handling using nip44_v2.

Reviewed changes

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

File Description
nwcp.py Implements NIP-44 v2 crypto, adds encryption negotiation via tags, and updates info event advertisement + response encryption behavior.
tests/unit/test_nwcp.py Adds vector test and async handling tests to cover NIP-44 v2 request decryption and response encryption/tagging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nwcp.py
Comment on lines +314 to +318
def _encrypt_nip44_v2_message(
self, message: str, public_key_hex: str, nonce: bytes | None = None
) -> str:
nonce = nonce or secrets.token_bytes(32)
conversation_key = self._get_conversation_key(public_key_hex)
Comment thread nwcp.py
@TheCryptoDonkey

Copy link
Copy Markdown

I maintain @forgesworn/nwc-kit, a NIP-44-only NWC client, so LNbits is currently unreachable from it and I have a direct interest in this landing. I went through the encryption code rather than just the diff summary, and it holds up.

Padding. I transcribed _nip44_v2_calc_padded_len and compared it against nostr-tools for plaintext lengths 1, 2, 31, 32, 33, 63, 64, 65, 100, 255, 256, 257, 512, 1000, 4096, 10000, 32768 and 65535, deriving the padded length from the actual ciphertext size. All eighteen agree byte for byte, including every chunk boundary.

Constants. NIP44_V2_MIN_DECODED_SIZE = 99 and NIP44_V2_MIN_PAYLOAD_SIZE = 132 are both right, and they are easy to get wrong: 99 is 1 + 32 + (2 + 32) + 32, so it only works out if the 2-byte length prefix inside the padded blob has been accounted for, and 132 is that base64-encoded. The extended prefix path matches the spec's extended_prefix_threshold behaviour too, including using a zero u16 as the signal.

One suggestion. NIP-44 publishes extended length prefix test vectors covering exactly the 65535 to 65536 boundary, given as SHA-256 checksums of the plaintext and payload since the payloads are too large to inline. Since this PR implements the 6-byte prefix path, those vectors would exercise it directly. test_nip44_v2_encryptdecrypt_vector currently covers the standard vector, and the boundary is the part most likely to harbour an off-by-one.

Offer. If it would help, I am happy to build this branch, point a NIP-44-only client at it and report back on the thread. That is worth slightly more than the usual smoke test here: most NWC clients negotiate down to NIP-04, so they pass whether or not the NIP-44 path is correct. One that cannot fall back exercises it or fails.

Thanks for writing this. Advertising nip44_v2 matters beyond LNbits, since clients that dropped NIP-04 entirely cannot talk to a wallet service that only offers it.

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.

Add NIP-44 v2 encryption

3 participants