From d5d5e1d199faa96bc8ff77f83f088fed3620bae0 Mon Sep 17 00:00:00 2001 From: arthurfranca Date: Sun, 4 Feb 2024 12:47:18 -0300 Subject: [PATCH 1/3] Add custom salt --- 44.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/44.md b/44.md index f3071ea985..b2272cdad2 100644 --- a/44.md +++ b/44.md @@ -37,7 +37,7 @@ messaging software and limit use of nostr to exchanging contacts. On its own, messages sent using this scheme have a number of important shortcomings: - No deniability: it is possible to prove an event was signed by a particular key -- No forward secrecy: when a key is compromised, it is possible to decrypt all previous conversations +- No forward secrecy (if using default salt): when a key is compromised, it is possible to decrypt all previous conversations - No post-compromise security: when a key is compromised, it is possible to decrypt all future conversations - No post-quantum security: a powerful quantum computer would be able to decrypt the messages - IP address leak: user IP may be seen by relays and all intermediaries between user and relay @@ -64,13 +64,15 @@ NIP-44 version 2 has the following design characteristics: is smaller in non-parallel environments. - A custom padding scheme is used instead of padmé because it provides better leakage reduction for small messages. - Base64 encoding is used instead of another compression algorithm because it is widely available, and is already used in nostr. +- Custom salt is allowed for conversation key calculation to enable forward secrecy. ### Encryption 1. Calculate a conversation key - Execute ECDH (scalar multiplication) of public key B by private key A Output `shared_x` must be unhashed, 32-byte encoded x coordinate of the shared point - - Use HKDF-extract with sha256, `IKM=shared_x` and `salt=utf8_encode('nip44-v2')` + - Use HKDF-extract with sha256, `IKM=shared_x` and `salt=utf8_encode(custom_string || 'nip44-v2')` + - Validate that salt is up to 32 bytes - HKDF output will be a `conversation_key` between two users. - It is always the same, when key roles are swapped: `conv(a, B) == conv(b, A)` 2. Generate a random 32-byte nonce @@ -220,9 +222,11 @@ def hmac_aad(key, message, aad): return hmac(sha256, key, concat(aad, message)); # Calculates long-term key between users A and B: `get_key(Apriv, Bpub) == get_key(Bpriv, Apub)` -def get_conversation_key(private_key_a, public_key_b): +def get_conversation_key(private_key_a, public_key_b, salt): + if (!salt) salt = utf8_encode('nip44-v2') + if len(salt) > 32: raise Exception('invalid salt length') shared_x = secp256k1_ecdh(private_key_a, public_key_b) - return hkdf_extract(IKM=shared_x, salt=utf8_encode('nip44-v2')) + return hkdf_extract(IKM=shared_x, salt) # Calculates unique per-message key def get_message_keys(conversation_key, nonce): From 163e09bfeb514ce16514a20086e568ab2473e80a Mon Sep 17 00:00:00 2001 From: arthurfranca Date: Mon, 5 Feb 2024 14:52:18 -0300 Subject: [PATCH 2/3] Fix syntax --- 44.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/44.md b/44.md index b2272cdad2..e602d885ca 100644 --- a/44.md +++ b/44.md @@ -223,7 +223,7 @@ def hmac_aad(key, message, aad): # Calculates long-term key between users A and B: `get_key(Apriv, Bpub) == get_key(Bpriv, Apub)` def get_conversation_key(private_key_a, public_key_b, salt): - if (!salt) salt = utf8_encode('nip44-v2') + if not salt: salt = utf8_encode('nip44-v2') if len(salt) > 32: raise Exception('invalid salt length') shared_x = secp256k1_ecdh(private_key_a, public_key_b) return hkdf_extract(IKM=shared_x, salt) From adb706ca1f1cc534ec36c1fea35b134bc5fbc0e2 Mon Sep 17 00:00:00 2001 From: arthurfranca Date: Mon, 5 Feb 2024 18:21:13 -0300 Subject: [PATCH 3/3] Don't talk about forward secrecy --- 44.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/44.md b/44.md index e602d885ca..174a25ebc1 100644 --- a/44.md +++ b/44.md @@ -37,7 +37,7 @@ messaging software and limit use of nostr to exchanging contacts. On its own, messages sent using this scheme have a number of important shortcomings: - No deniability: it is possible to prove an event was signed by a particular key -- No forward secrecy (if using default salt): when a key is compromised, it is possible to decrypt all previous conversations +- No forward secrecy: when a key is compromised, it is possible to decrypt all previous conversations - No post-compromise security: when a key is compromised, it is possible to decrypt all future conversations - No post-quantum security: a powerful quantum computer would be able to decrypt the messages - IP address leak: user IP may be seen by relays and all intermediaries between user and relay @@ -64,7 +64,6 @@ NIP-44 version 2 has the following design characteristics: is smaller in non-parallel environments. - A custom padding scheme is used instead of padmé because it provides better leakage reduction for small messages. - Base64 encoding is used instead of another compression algorithm because it is widely available, and is already used in nostr. -- Custom salt is allowed for conversation key calculation to enable forward secrecy. ### Encryption