From 7736f3fd8bf20719280a9627c05034e0d6c41078 Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 1 Oct 2019 12:46:22 +0000 Subject: [PATCH] proposal 144 updates --- .../144-ecies-x25519-aead-ratchet.rst | 123 +++++++++--------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst b/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst index 5aca82b0..f83fab08 100644 --- a/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst +++ b/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst @@ -5,7 +5,7 @@ ECIES-X25519-AEAD-Ratchet :author: zzz, chisana :created: 2018-11-22 :thread: http://zzz.i2p/topics/2639 - :lastupdated: 2019-09-29 + :lastupdated: 2019-10-01 :status: Open .. contents:: @@ -349,7 +349,9 @@ Bound sessions are similar to the Noise IK pattern. <- s ... e es s ss p -> - <- tag e ee se p + <- tag e ee se + <- p + p -> {% endhighlight %} @@ -1219,9 +1221,10 @@ Encrypted format: Notes ````` -The tag is generated in the Tags KDF, as initialized -in the TagSet KDF below. +The tag is generated in the Session Tags KDF, as initialized +in the DH Initialization KDF below. This correlates the reply to the session. +The Session Key from the DH Initialization is not used. Payload @@ -1233,10 +1236,9 @@ Payload section must contain the following blocks (in order): Optional payload blocks -- I2NP (3) +- Garlic (3) - Padding (254) -Optional blocks can have multiple I2NP blocks, but only a single padding block. If present, the padding block must be the final block. @@ -1251,7 +1253,7 @@ the KDF below, using the chainKey from the New Session message. {% highlight lang='text' %} // Generate tagset tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) - tagset = TAGSET.CREATE(tagsetKey, n = 1) + tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) {% endhighlight %} @@ -1274,7 +1276,7 @@ KDF for Reply Key Section Encrypted Contents // bpk = Bob public static key // Generate the tag - tagsetEntry = tagset.GET_NEXT_ENTRY() + tagsetEntry = tagset_nsr.GET_NEXT_ENTRY() tag = tagsetEntry.SESSION_TAG // MixHash(tag) @@ -1351,6 +1353,8 @@ payload to the NSR message. keydata = HKDF(chainKey, ZEROLEN, "", 64) k_ab = keydata[0:31] k_ba = keydata[32:63] + tagset_ab = DH_INITIALIZE(chainKey, k_ab) + tagset_ba = DH_INITIALIZE(chainKey, k_ba) // AEAD parameters for New Session Reply payload k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) @@ -1428,11 +1432,13 @@ KDF .. raw:: html {% highlight lang='text' %} -See message key ratchet below. +See AEAD section below. - Key: KDF TBD - IV: KDF TBD - Nonce: The message number N in the current chain, as retrieved from the associated Session Tag. + // AEAD parameters for Existing Session payload + k = The 32-byte session key associated with this session tag + n = The message number N in the current chain, as retrieved from the associated Session Tag. + ad = The session tag, 8 bytes + ciphertext = ENCRYPT(k, n, payload, ad) {% endhighlight %} @@ -1566,7 +1572,7 @@ for an AEAD block in an existing session message: .. raw:: html {% highlight lang='dataspec' %} -k :: 32 byte cipher key +k :: 32 byte session key As looked up from the accompanying session tag. n :: Counter-based nonce, 12 bytes. @@ -1694,8 +1700,8 @@ If a DH ratchet step isn't triggered, then the received N minus the length of th is the number of skipped messages in that chain. -Recommended Implementation -`````````````````````````` +Sample Implementation +`````````````````````` We define the following data structures and functions to implement these ratchets. @@ -1810,8 +1816,8 @@ the session should be removed. To avoid a KCI and/or resource exhaustion attack, where an attacker drops Bob's NSR replies to keep Alice sending NS messages, Alice should avoid starting new sessions to Bob after a certain number of retries due to timer expiration. -Alice and Bob each do one DH ratchet to create the inbound and outbound Existing Session -session tag and symmetric key ratchet chains, and once for every Next DH Key block received. +Alice and Bob each do one DH initialization to create the inbound and outbound Existing Session +session tag and symmetric key ratchet chains, and do a DH ratchet for every Next DH Key block received. Alice and Bob each do two session tag ratchets and two symmetric keys ratchets after each DH ratchet. For each new ES message in a given direction, Alice and Bob advance the session @@ -1830,25 +1836,52 @@ Issues ~~~~~~ -KDF -~~~ +DH INITIALIZATION KDF +~~~~~~~~~~~~~~~~~~~~~~~ -This is the definition of TAGSET.CREATE(key, n). +This is the definition of DH_INITIALIZE(rootKey, k) +for a single direction. It creates a tagset, and a +root key to be used for a subsequent DH ratchet if necessary. + +TODO why are we using the chain key after split() ? .. raw:: html {% highlight lang='text' %} Inputs: - 1) Root key - 2) sharedSecret (the DH result from the new session message) - - Received New Session message: - sharedSecret = k from Payload Section - rootKey = chainKey from Payload Section + 1) rootKey = chainKey from Payload Section + 2) k from split() // KDF_RK(rk, dh_out) - keydata = HKDF(rootKey, sharedSecret, "KDFDHRatchetStep", 64) + keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64) + + // Output 1: The next Root Key (KDF input for the next ratchet) + nextRootKey = keydata[0:31] + // Output 2: The chain key to initialize the new + // session tag and symmetric key ratchets + // for Alice to Bob transmissions + ck = keydata[32:63] + + // session tag and symmetric key chain keys + keydata = HKDF(ck, ZEROLEN, "TagAndKeyGenKeys", 64) + sessTag_ck = keydata[0:31] + symmKey_ck = keydata[32:63] + +{% endhighlight %} + + +DH RATCHET KDF +~~~~~~~~~~~~~~~ + +This is used after new DH keys are exchanged, before a tagset +is exhausted. + +TODO + +.. raw:: html + + {% highlight lang='text' %} // See New Session Reply KDF for generating Bob's reply message // and first set of ephemeral keys @@ -1867,37 +1900,8 @@ Inputs: rootKey = nextRootKey from previous DH Ratchet keydata = HKDF(rootKey, sharedSecret, "KDFDHRatchetStep", 64) - For unidirectional (unbound) DH Ratchets - // Output 1: The next Root Key (KDF input for the next ratchet) - nextRootKey = keydata[0:31] - // Output 2: The chain key to initialize the new - // session tag and symmetric key ratchets - // for Alice to Bob transmissions - ck = keydata[32:63] - // Inbound session tag and symmetric key chain keys - keydata = HKDF(ck, ZEROLEN, "TagAndKeyGenKeys", 64) - sessTag_ck = keydata[0:31] - symmKey_ck = keydata[32:63] - - For bidirectional (bound) DH Ratchets: - // Output 1: The next Root Key (KDF input for the next ratchet) - nextRootKey = keydata[0:31] - // Output 2: The chain key to initialize the new - // session tag and symmetric key ratchets - // for Alice to Bob transmissions - ck = keydata[32:63] - // Split() - // Needed to separate key states for inbound and outbound sessions - // Alice's outbound and Bob's inbound session tag and symmetric key chain keys - keydata = HKDF(ck, ZEROLEN, "TagAndKeyGenKeys", 64) - aToBSessTag_ck = keydata[0:31] - aToBSymmKey_ck = keydata[32:63] - // Alice's inbound and Bob's outbound session tag and symmetric key chain keys - keydata = HKDF(ck, ZEROLEN, "BtoAChainsTagSym", 64) - bToASessTag_ck = keydata[0:31] - bToASymmKey_ck = keydata[32:63] - - + //TODO + newTagSet = DH_INITIALIZE(rootKey, sharedSecret) {% endhighlight %} @@ -1950,6 +1954,7 @@ Inputs: First time: output from DH ratchet Subsequent times: output from previous session tag ratchet + Generated: 2) input_key_material = SESSTAG_CONSTANT Must be unique for this chain (generated from chain key), so that the sequence isn't predictable, since session tags @@ -2021,6 +2026,8 @@ Inputs: 1) Symmetric Key Chain key symmKey_ck First time: output from DH ratchet Subsequent times: output from previous symmetric key ratchet + + Generated: 2) input_key_material = SYMMKEY_CONSTANT = ZEROLEN No need for uniqueness. Symmetric keys never go out on the wire. TODO: Set a constant anyway?