nip-44: remove author names and arbitrary line-breaks.

This commit is contained in:
fiatjaf 2023-12-20 13:56:03 -03:00
parent 822b70a565
commit 4199f20236
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1

66
44.md
View File

@ -2,7 +2,7 @@
## Encrypted Payloads (Versioned)
`optional` `author:paulmillr` `author:staab`
`optional`
The NIP introduces a new data format for keypair-based encryption. This NIP is versioned
to allow multiple algorithm choices to exist simultaneously.
@ -22,12 +22,11 @@ The scheme has a number of important shortcomings:
- Limited message size leak: padding only partially obscures true message length
- No attachments: they are not supported
Lack of forward secrecy is partially mitigated: 1) the messages
should only be stored on relays, specified by the user, instead of a set of
all public relays 2) the relays are supposed to regularly delete older messages.
Lack of forward secrecy is partially mitigated by these two factors:
1. the messages should only be stored on relays, specified by the user, instead of a set of all public relays.
2. the relays are supposed to regularly delete older messages.
For risky situations, users should chat in specialized E2EE messaging software and limit use
of nostr to exchanging contacts.
For risky situations, users should chat in specialized E2EE messaging software and limit use of nostr to exchanging contacts.
## Dependence on NIP-01
@ -35,14 +34,9 @@ It's not enough to use NIP-44 for encryption: the output must also be signed.
In nostr case, the payload is serialized and signed as per NIP-01 rules.
The same event can be serialized in two different ways,
resulting in two distinct signatures. So, it's important
to ensure serialization rules, which are defined in NIP-01,
are the same across different NIP-44 implementations.
The same event can be serialized in two different ways, resulting in two distinct signatures. So, it's important to ensure serialization rules, which are defined in NIP-01, are the same across different NIP-44 implementations.
After serialization, the event is signed by Schnorr signature over secp256k1,
defined in BIP340. It's important to ensure the key and signature validity as
per BIP340 rules.
After serialization, the event is signed by Schnorr signature over secp256k1, defined in BIP340. It's important to ensure the key and signature validity as per BIP340 rules.
## Versions
@ -56,18 +50,12 @@ Currently defined encryption algorithms:
The algorithm choices are justified in a following way:
- Encrypt-then-mac-then-sign instead of encrypt-then-sign-then-mac:
only events wrapped in NIP-01 signed envelope are currently accepted by nostr.
- ChaCha instead of AES: it's faster and has
[better security against multi-key attacks](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/)
- ChaCha instead of XChaCha: XChaCha has not been standardized. Also, we don't need xchacha's improved
collision resistance of nonces: every message has a new (key, nonce) pair.
- HMAC-SHA256 instead of Poly1305: polynomial MACs are much easier to forge
- SHA256 instead of SHA3 or BLAKE: it is already used in nostr. Also blake's
speed advantage is smaller in non-parallel environments
- Custom padding instead of padmé: better leakage reduction for small messages
- Base64 encoding instead of an other compression algorithm: it is widely available,
and is already used in nostr
- Encrypt-then-mac-then-sign instead of encrypt-then-sign-then-mac: only events wrapped in NIP-01 signed envelope are currently accepted by nostr.
- ChaCha instead of AES: it's faster and has [better security against multi-key attacks](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/)
- ChaCha instead of XChaCha: XChaCha has not been standardized. Also, we don't need xchacha's improved collision resistance of nonces: every message has a new (key, nonce) pair.
- HMAC-SHA256 instead of Poly1305: polynomial MACs are much easier to forge SHA256 instead of SHA3 or BLAKE: it is already used in nostr. Also blake's
speed advantage is smaller in non-parallel environments - Custom padding instead of padmé: better leakage reduction for small messages
- Base64 encoding instead of an other compression algorithm: it is widely available, and is already used in nostr
### Functions and operations
@ -77,12 +65,7 @@ The algorithm choices are justified in a following way:
comprised of methods `hkdf_extract(IKM, salt)` and `hkdf_expand(OKM, info, L)`
- `chacha20(key, nonce, data)` is ChaCha20 [(RFC 8439)](https://datatracker.ietf.org/doc/html/rfc8439), with starting counter set to 0
- `hmac_sha256(key, message)` is HMAC [(RFC 2104)](https://datatracker.ietf.org/doc/html/rfc2104)
- `secp256k1_ecdh(priv_a, pub_b)` is multiplication of point B by
scalar a (`a ⋅ B`), defined in
[BIP340](https://github.com/bitcoin/bips/blob/e918b50731397872ad2922a1b08a5a4cd1d6d546/bip-0340.mediawiki).
The operation produces shared point, and we encode the shared point's 32-byte x coordinate,
using method `bytes(P)` from BIP340. Private and public keys must be validated
as per BIP340: pubkey must be a valid, on-curve point, and private key must be a scalar in range `[1, secp256k1_order - 1]`
- `secp256k1_ecdh(priv_a, pub_b)` is multiplication of point B by scalar a (`a ⋅ B`), defined in [BIP340](https://github.com/bitcoin/bips/blob/e918b50731397872ad2922a1b08a5a4cd1d6d546/bip-0340.mediawiki). The operation produces shared point, and we encode the shared point's 32-byte x coordinate, using method `bytes(P)` from BIP340. Private and public keys must be validated as per BIP340: pubkey must be a valid, on-curve point, and private key must be a scalar in range `[1, secp256k1_order - 1]`
- Operators
- `x[i:j]`, where `x` is a byte array and `i, j <= 0`,
returns a `(j - i)`-byte array with a copy of the `i`-th byte (inclusive) to the `j`-th byte (exclusive) of `x`
@ -225,15 +208,11 @@ def decrypt(payload, conversation_key):
- Validate that AAD (nonce) is 32 bytes
7. Base64-encode (with padding) params: `concat(version, nonce, ciphertext, mac)`
After encryption, it's necessary to sign it. Use NIP-01 to serialize the event,
with result base64 assigned to event's `content`. Then, use NIP-01 to sign
the event using schnorr signature scheme over secp256k1.
After encryption, it's necessary to sign it. Use NIP-01 to serialize the event, with result base64 assigned to event's `content`. Then, use NIP-01 to sign the event using schnorr signature scheme over secp256k1.
#### Decryption
Before decryption, it's necessary to validate the message's pubkey and signature.
The public key must be a valid non-zero secp256k1 curve point, and signature must be valid
secp256k1 schnorr signature. For exact validation rules, refer to BIP-340.
Before decryption, it's necessary to validate the message's pubkey and signature. The public key must be a valid non-zero secp256k1 curve point, and signature must be valid secp256k1 schnorr signature. For exact validation rules, refer to BIP-340.
1. Check if first payload's character is `#`
- `#` is an optional future-proof flag that means non-base64 encoding is used
@ -260,11 +239,9 @@ secp256k1 schnorr signature. For exact validation rules, refer to BIP-340.
## Tests and code
A collection of implementations in different languages is
available [on GitHub](https://github.com/paulmillr/nip44).
A collection of implementations in different languages is available at https://github.com/paulmillr/nip44.
We publish extensive test vectors. Instead of having it in the
document directly, a sha256 checksum of vectors is provided:
We publish extensive test vectors. Instead of having it in the document directly, a sha256 checksum of vectors is provided:
269ed0f69e4c192512cc779e78c555090cebc7c785b609e338a62afc3ce25040 nip44.vectors.json
@ -286,11 +263,8 @@ The file also contains intermediate values. A quick guidance with regards to its
- `valid.get_conversation_key`: calculate conversation_key from secret key sec1 and public key pub2
- `valid.get_message_keys`: calculate chacha_key, chacha_nocne, hmac_key from conversation_key and nonce
- `valid.calc_padded_len`: take unpadded length (first value), calculate padded length (second value)
- `valid.encrypt_decrypt`: emulate real conversation. Calculate
pub2 from sec2, verify conversation_key from (sec1, pub2), encrypt, verify payload,
then calculate pub1 from sec1, verify conversation_key from (sec2, pub1), decrypt, verify plaintext.
- `valid.encrypt_decrypt_long_msg`: same as previous step, but instead of a full plaintext and payload,
their checksum is provided.
- `valid.encrypt_decrypt`: emulate real conversation. Calculate pub2 from sec2, verify conversation_key from (sec1, pub2), encrypt, verify payload, then calculate pub1 from sec1, verify conversation_key from (sec2, pub1), decrypt, verify plaintext.
- `valid.encrypt_decrypt_long_msg`: same as previous step, but instead of a full plaintext and payload, their checksum is provided.
- `invalid.encrypt_msg_lengths`
- `invalid.get_conversation_key`: calculating converastion_key must throw an error
- `invalid.decrypt`: decrypting message content must throw an error