NIP-44 v3: more secure and flexible encryption

"Would you like to allow decrypting all events?" No thanks.

semisol

May 15, 2026 · 6 min read

If you just want to read the specification, it's at https://spec.nostr.land/nip44v3.

The problem with current encryption#

The current specification, NIP-44 v2, was created during simpler times: Nostr was smaller, remote signers were rare, and pasting nsecs was the standard.

Since then, things have changed. Large events are much more common, using remote signers is the norm, and encryption is everywhere.


When you want to allow a Nostr app to encrypt/decrypt data, by default, most signers prompt you to approve or reject it.

Depending on your signer, you might get a prompt that:

  1. Shows the raw data.
    Good, but you can't know if the [["p", ...], ...] list is the private mute list you wanted to edit, or actually the member list for your group chat.
  2. Shows no information at all, just that decryption was requested. Not helpful.
  3. Tells you a rough type, such as JSON, or plaintext.
    This is much better but has the same problem as 1: Two different contexts can share the same format without being related.

Encrypted data is now integral to most Nostr apps. Applications need access to decrypt to look for new DMs, load your private lists, store application settings, and much more.

The sheer number of decryption requests can cause permission fatigue, leading users to allow all decryption requests without confirmation.

This can be exploited by malicious applications to exfiltrate sensitive conversations, ecash/LN wallet keys, and more:

Quoted note

There has been a discussion about how to allow restricting decryption/encryption, and the conclusion was: The only robust solution is a new AEAD scheme.

It has been 21 months without any progress.

There are also other issues with the current encryption scheme:

Large data#

Have you ever tried to use a remote signer with a follow list that is larger than 2000 users? No?

Well, you can't, even if you want to.

Events like this are over the size limit of NIP-44 v2, making it impossible to manage such lists with a remote signer. You instead need to use your nsec directly, or use a browser extension.

Binary encoding#

There are many use cases where encrypting binary data can be useful. However, NIP-44 v2 only supports UTF-8 encoded text, and support for binary data is inconsistent.

Some of these use cases include:

This overhead adds up, and wastes mobile data and relay resources.

What is NIP-44 v3?#

NIP-44 v3 is a new encryption scheme that solves these issues, without introducing any new cryptographic primitives or constructions in Nostr.

Some of the features:

Context binding#

NIP-44 v3 supports context binding, which means each message has an associated context.

The signer can use the context from the message to identify what it is, and accept/deny accordingly: a private message, your mute list, or your LN wallet's data.

Comparison of signer prompts with and without context-bound encryption

Much nicer, isn't it?

This also prevents the usage of an encrypted piece of data, such as a private message, in another context like a long-form draft.

The specific implementation in NIP-44 v3 has two fields:

Getting started#

The NIP-44 v3 specification is available at https://spec.nostr.land/nip44v3, and includes the main specification, a less-formal implementation guide, and test vectors.

An implementation of NIP-44 v3 in Go is available as pkg.nostr.land/go/ncrypt. This also supports NIP-44 v2, NIP-04, and provides a way to detect the encryption version used.

The specification is still a draft, but it is unlikely to change except for the formatting, and the addition of new test vectors.

Why not submit it as a NIP now?#

I plan to submit NIP-44 v3 to the main NIPs repository at a future date.

However, the NIPs repository's "process" (or lack thereof) significantly slows down the adoption of any new specifications.

For this reason, this specification is released as a standalone repository.

This allows the development of secure encryption to start now, instead of after months of waiting for a single approval from the "official" maintainers.

Some technical details#

The cryptography in NIP-44 v3 does not differ significantly from NIP-44 v2.

HKDF is used to derive per-message subkeys, which protects the shared secrets and ensures the keys are unbiased. The main difference includes using info/salt correctly compared to v2, and separate HKDF-Expand calls for each key.

The ChaCha20 nonce is set to all-zeroes, as any given encryption key is only used to encrypt one message due to the subkey derivation.

The encoding has additional fields for the kind and scope, and the MAC now incorporates those as well.

NIP-44 v3 incorporates a slightly modified version of the padding in NIP-44 v2, that increases the uncertainty of the padding size for short messages, like DMs, without much overhead.

The padding used by NIP-44 v3 does not enforce a specific algorithm, but it is strongly recommended that all implementations use the reference algorithm.

End#

Thanks for reading! If you have any feedback, please reply or tag me.

If you want to support my work, consider zapping.

3

Written by

👨‍💻 software developer 📨 nostr.land relay all opinions are my own.

semisol@nostr.land

Comments3

JackTheMimic

Maybe I missed something in the spec but what would stop a malicious app from embedding different kind decryption within the cyhertext and the 32-bit integer is just to comply with the signer's request. A kind 10000 decryption request but hidden within is a 30001 list for example?
Open in a Nostr client