upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfiatjaf <fiatjaf@gmail.com>2023-12-20 13:56:03 -0300
committerfiatjaf <fiatjaf@gmail.com>2023-12-20 13:56:03 -0300
commit4199f202365fc4c1a464b1033d040597bccbb08d (patch)
tree34a24a95352e210a0b4467ea2e59f0e16a7abd88
parent822b70a565678222706dd6284eb7abcaadfc5115 (diff)
nip-44: remove author names and arbitrary line-breaks.
-rw-r--r--44.md66
1 files changed, 20 insertions, 46 deletions
diff --git a/44.md b/44.md
index 1282d26..e66a7b3 100644
--- a/44.md
+++ b/44.md
@@ -2,7 +2,7 @@
2 2
3## Encrypted Payloads (Versioned) 3## Encrypted Payloads (Versioned)
4 4
5`optional` `author:paulmillr` `author:staab` 5`optional`
6 6
7The NIP introduces a new data format for keypair-based encryption. This NIP is versioned 7The NIP introduces a new data format for keypair-based encryption. This NIP is versioned
8to allow multiple algorithm choices to exist simultaneously. 8to allow multiple algorithm choices to exist simultaneously.
@@ -22,12 +22,11 @@ The scheme has a number of important shortcomings:
22- Limited message size leak: padding only partially obscures true message length 22- Limited message size leak: padding only partially obscures true message length
23- No attachments: they are not supported 23- No attachments: they are not supported
24 24
25Lack of forward secrecy is partially mitigated: 1) the messages 25Lack of forward secrecy is partially mitigated by these two factors:
26should only be stored on relays, specified by the user, instead of a set of 26 1. the messages should only be stored on relays, specified by the user, instead of a set of all public relays.
27all public relays 2) the relays are supposed to regularly delete older messages. 27 2. the relays are supposed to regularly delete older messages.
28 28
29For risky situations, users should chat in specialized E2EE messaging software and limit use 29For risky situations, users should chat in specialized E2EE messaging software and limit use of nostr to exchanging contacts.
30of nostr to exchanging contacts.
31 30
32## Dependence on NIP-01 31## Dependence on NIP-01
33 32
@@ -35,14 +34,9 @@ It's not enough to use NIP-44 for encryption: the output must also be signed.
35 34
36In nostr case, the payload is serialized and signed as per NIP-01 rules. 35In nostr case, the payload is serialized and signed as per NIP-01 rules.
37 36
38The same event can be serialized in two different ways, 37The 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.
39resulting in two distinct signatures. So, it's important
40to ensure serialization rules, which are defined in NIP-01,
41are the same across different NIP-44 implementations.
42 38
43After serialization, the event is signed by Schnorr signature over secp256k1, 39After 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.
44defined in BIP340. It's important to ensure the key and signature validity as
45per BIP340 rules.
46 40
47## Versions 41## Versions
48 42
@@ -56,18 +50,12 @@ Currently defined encryption algorithms:
56 50
57The algorithm choices are justified in a following way: 51The algorithm choices are justified in a following way:
58 52
59- Encrypt-then-mac-then-sign instead of encrypt-then-sign-then-mac: 53- 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.
60 only events wrapped in NIP-01 signed envelope are currently accepted by nostr. 54- 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/)
61- ChaCha instead of AES: it's faster and has 55- 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.
62 [better security against multi-key attacks](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/) 56- 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
63- ChaCha instead of XChaCha: XChaCha has not been standardized. Also, we don't need xchacha's improved 57 speed advantage is smaller in non-parallel environments - Custom padding instead of padmé: better leakage reduction for small messages
64 collision resistance of nonces: every message has a new (key, nonce) pair. 58- Base64 encoding instead of an other compression algorithm: it is widely available, and is already used in nostr
65- HMAC-SHA256 instead of Poly1305: polynomial MACs are much easier to forge
66- SHA256 instead of SHA3 or BLAKE: it is already used in nostr. Also blake's
67 speed advantage is smaller in non-parallel environments
68- Custom padding instead of padmé: better leakage reduction for small messages
69- Base64 encoding instead of an other compression algorithm: it is widely available,
70 and is already used in nostr
71 59
72### Functions and operations 60### Functions and operations
73 61
@@ -77,12 +65,7 @@ The algorithm choices are justified in a following way:
77 comprised of methods `hkdf_extract(IKM, salt)` and `hkdf_expand(OKM, info, L)` 65 comprised of methods `hkdf_extract(IKM, salt)` and `hkdf_expand(OKM, info, L)`
78 - `chacha20(key, nonce, data)` is ChaCha20 [(RFC 8439)](https://datatracker.ietf.org/doc/html/rfc8439), with starting counter set to 0 66 - `chacha20(key, nonce, data)` is ChaCha20 [(RFC 8439)](https://datatracker.ietf.org/doc/html/rfc8439), with starting counter set to 0
79 - `hmac_sha256(key, message)` is HMAC [(RFC 2104)](https://datatracker.ietf.org/doc/html/rfc2104) 67 - `hmac_sha256(key, message)` is HMAC [(RFC 2104)](https://datatracker.ietf.org/doc/html/rfc2104)
80 - `secp256k1_ecdh(priv_a, pub_b)` is multiplication of point B by 68 - `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]`
81 scalar a (`a ⋅ B`), defined in
82 [BIP340](https://github.com/bitcoin/bips/blob/e918b50731397872ad2922a1b08a5a4cd1d6d546/bip-0340.mediawiki).
83 The operation produces shared point, and we encode the shared point's 32-byte x coordinate,
84 using method `bytes(P)` from BIP340. Private and public keys must be validated
85 as per BIP340: pubkey must be a valid, on-curve point, and private key must be a scalar in range `[1, secp256k1_order - 1]`
86- Operators 69- Operators
87 - `x[i:j]`, where `x` is a byte array and `i, j <= 0`, 70 - `x[i:j]`, where `x` is a byte array and `i, j <= 0`,
88 returns a `(j - i)`-byte array with a copy of the `i`-th byte (inclusive) to the `j`-th byte (exclusive) of `x` 71 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):
225 - Validate that AAD (nonce) is 32 bytes 208 - Validate that AAD (nonce) is 32 bytes
2267. Base64-encode (with padding) params: `concat(version, nonce, ciphertext, mac)` 2097. Base64-encode (with padding) params: `concat(version, nonce, ciphertext, mac)`
227 210
228After encryption, it's necessary to sign it. Use NIP-01 to serialize the event, 211After 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.
229with result base64 assigned to event's `content`. Then, use NIP-01 to sign
230the event using schnorr signature scheme over secp256k1.
231 212
232#### Decryption 213#### Decryption
233 214
234Before decryption, it's necessary to validate the message's pubkey and signature. 215Before 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.
235The public key must be a valid non-zero secp256k1 curve point, and signature must be valid
236secp256k1 schnorr signature. For exact validation rules, refer to BIP-340.
237 216
2381. Check if first payload's character is `#` 2171. Check if first payload's character is `#`
239 - `#` is an optional future-proof flag that means non-base64 encoding is used 218 - `#` 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.
260 239
261## Tests and code 240## Tests and code
262 241
263A collection of implementations in different languages is 242A collection of implementations in different languages is available at https://github.com/paulmillr/nip44.
264available [on GitHub](https://github.com/paulmillr/nip44).
265 243
266We publish extensive test vectors. Instead of having it in the 244We publish extensive test vectors. Instead of having it in the document directly, a sha256 checksum of vectors is provided:
267document directly, a sha256 checksum of vectors is provided:
268 245
269 269ed0f69e4c192512cc779e78c555090cebc7c785b609e338a62afc3ce25040 nip44.vectors.json 246 269ed0f69e4c192512cc779e78c555090cebc7c785b609e338a62afc3ce25040 nip44.vectors.json
270 247
@@ -286,11 +263,8 @@ The file also contains intermediate values. A quick guidance with regards to its
286- `valid.get_conversation_key`: calculate conversation_key from secret key sec1 and public key pub2 263- `valid.get_conversation_key`: calculate conversation_key from secret key sec1 and public key pub2
287- `valid.get_message_keys`: calculate chacha_key, chacha_nocne, hmac_key from conversation_key and nonce 264- `valid.get_message_keys`: calculate chacha_key, chacha_nocne, hmac_key from conversation_key and nonce
288- `valid.calc_padded_len`: take unpadded length (first value), calculate padded length (second value) 265- `valid.calc_padded_len`: take unpadded length (first value), calculate padded length (second value)
289- `valid.encrypt_decrypt`: emulate real conversation. Calculate 266- `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.
290 pub2 from sec2, verify conversation_key from (sec1, pub2), encrypt, verify payload, 267- `valid.encrypt_decrypt_long_msg`: same as previous step, but instead of a full plaintext and payload, their checksum is provided.
291 then calculate pub1 from sec1, verify conversation_key from (sec2, pub1), decrypt, verify plaintext.
292- `valid.encrypt_decrypt_long_msg`: same as previous step, but instead of a full plaintext and payload,
293 their checksum is provided.
294- `invalid.encrypt_msg_lengths` 268- `invalid.encrypt_msg_lengths`
295- `invalid.get_conversation_key`: calculating converastion_key must throw an error 269- `invalid.get_conversation_key`: calculating converastion_key must throw an error
296- `invalid.decrypt`: decrypting message content must throw an error 270- `invalid.decrypt`: decrypting message content must throw an error