forked from I2P_Developers/i2p.www
proposal 144 updates
This commit is contained in:
@@ -5,7 +5,7 @@ ECIES-X25519-AEAD-Ratchet
|
|||||||
:author: zzz, chisana
|
:author: zzz, chisana
|
||||||
:created: 2018-11-22
|
:created: 2018-11-22
|
||||||
:thread: http://zzz.i2p/topics/2639
|
:thread: http://zzz.i2p/topics/2639
|
||||||
:lastupdated: 2019-09-29
|
:lastupdated: 2019-10-01
|
||||||
:status: Open
|
:status: Open
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
@@ -349,7 +349,9 @@ Bound sessions are similar to the Noise IK pattern.
|
|||||||
<- s
|
<- s
|
||||||
...
|
...
|
||||||
e es s ss p ->
|
e es s ss p ->
|
||||||
<- tag e ee se p
|
<- tag e ee se
|
||||||
|
<- p
|
||||||
|
p ->
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -1219,9 +1221,10 @@ Encrypted format:
|
|||||||
|
|
||||||
Notes
|
Notes
|
||||||
`````
|
`````
|
||||||
The tag is generated in the Tags KDF, as initialized
|
The tag is generated in the Session Tags KDF, as initialized
|
||||||
in the TagSet KDF below.
|
in the DH Initialization KDF below.
|
||||||
This correlates the reply to the session.
|
This correlates the reply to the session.
|
||||||
|
The Session Key from the DH Initialization is not used.
|
||||||
|
|
||||||
|
|
||||||
Payload
|
Payload
|
||||||
@@ -1233,10 +1236,9 @@ Payload section must contain the following blocks (in order):
|
|||||||
|
|
||||||
Optional payload blocks
|
Optional payload blocks
|
||||||
|
|
||||||
- I2NP (3)
|
- Garlic (3)
|
||||||
- Padding (254)
|
- 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.
|
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' %}
|
{% highlight lang='text' %}
|
||||||
// Generate tagset
|
// Generate tagset
|
||||||
tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
|
tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
|
||||||
tagset = TAGSET.CREATE(tagsetKey, n = 1)
|
tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -1274,7 +1276,7 @@ KDF for Reply Key Section Encrypted Contents
|
|||||||
// bpk = Bob public static key
|
// bpk = Bob public static key
|
||||||
|
|
||||||
// Generate the tag
|
// Generate the tag
|
||||||
tagsetEntry = tagset.GET_NEXT_ENTRY()
|
tagsetEntry = tagset_nsr.GET_NEXT_ENTRY()
|
||||||
tag = tagsetEntry.SESSION_TAG
|
tag = tagsetEntry.SESSION_TAG
|
||||||
|
|
||||||
// MixHash(tag)
|
// MixHash(tag)
|
||||||
@@ -1351,6 +1353,8 @@ payload to the NSR message.
|
|||||||
keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||||
k_ab = keydata[0:31]
|
k_ab = keydata[0:31]
|
||||||
k_ba = keydata[32:63]
|
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
|
// AEAD parameters for New Session Reply payload
|
||||||
k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
||||||
@@ -1428,11 +1432,13 @@ KDF
|
|||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='text' %}
|
{% highlight lang='text' %}
|
||||||
See message key ratchet below.
|
See AEAD section below.
|
||||||
|
|
||||||
Key: KDF TBD
|
// AEAD parameters for Existing Session payload
|
||||||
IV: KDF TBD
|
k = The 32-byte session key associated with this session tag
|
||||||
Nonce: The message number N in the current chain, as retrieved from the associated 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 %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
|
||||||
@@ -1566,7 +1572,7 @@ for an AEAD block in an existing session message:
|
|||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
k :: 32 byte cipher key
|
k :: 32 byte session key
|
||||||
As looked up from the accompanying session tag.
|
As looked up from the accompanying session tag.
|
||||||
|
|
||||||
n :: Counter-based nonce, 12 bytes.
|
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.
|
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.
|
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,
|
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 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
|
Alice and Bob each do one DH initialization to create the inbound and outbound Existing Session
|
||||||
session tag and symmetric key ratchet chains, and once for every Next DH Key block received.
|
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
|
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
|
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
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='text' %}
|
{% highlight lang='text' %}
|
||||||
Inputs:
|
Inputs:
|
||||||
1) Root key
|
1) rootKey = chainKey from Payload Section
|
||||||
2) sharedSecret (the DH result from the new session message)
|
2) k from split()
|
||||||
|
|
||||||
Received New Session message:
|
|
||||||
sharedSecret = k from Payload Section
|
|
||||||
rootKey = chainKey from Payload Section
|
|
||||||
|
|
||||||
// KDF_RK(rk, dh_out)
|
// 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
|
// See New Session Reply KDF for generating Bob's reply message
|
||||||
// and first set of ephemeral keys
|
// and first set of ephemeral keys
|
||||||
@@ -1867,37 +1900,8 @@ Inputs:
|
|||||||
rootKey = nextRootKey from previous DH Ratchet
|
rootKey = nextRootKey from previous DH Ratchet
|
||||||
keydata = HKDF(rootKey, sharedSecret, "KDFDHRatchetStep", 64)
|
keydata = HKDF(rootKey, sharedSecret, "KDFDHRatchetStep", 64)
|
||||||
|
|
||||||
For unidirectional (unbound) DH Ratchets
|
//TODO
|
||||||
// Output 1: The next Root Key (KDF input for the next ratchet)
|
newTagSet = DH_INITIALIZE(rootKey, sharedSecret)
|
||||||
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]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -1950,6 +1954,7 @@ Inputs:
|
|||||||
First time: output from DH ratchet
|
First time: output from DH ratchet
|
||||||
Subsequent times: output from previous session tag ratchet
|
Subsequent times: output from previous session tag ratchet
|
||||||
|
|
||||||
|
Generated:
|
||||||
2) input_key_material = SESSTAG_CONSTANT
|
2) input_key_material = SESSTAG_CONSTANT
|
||||||
Must be unique for this chain (generated from chain key),
|
Must be unique for this chain (generated from chain key),
|
||||||
so that the sequence isn't predictable, since session tags
|
so that the sequence isn't predictable, since session tags
|
||||||
@@ -2021,6 +2026,8 @@ Inputs:
|
|||||||
1) Symmetric Key Chain key symmKey_ck
|
1) Symmetric Key Chain key symmKey_ck
|
||||||
First time: output from DH ratchet
|
First time: output from DH ratchet
|
||||||
Subsequent times: output from previous symmetric key ratchet
|
Subsequent times: output from previous symmetric key ratchet
|
||||||
|
|
||||||
|
Generated:
|
||||||
2) input_key_material = SYMMKEY_CONSTANT = ZEROLEN
|
2) input_key_material = SYMMKEY_CONSTANT = ZEROLEN
|
||||||
No need for uniqueness. Symmetric keys never go out on the wire.
|
No need for uniqueness. Symmetric keys never go out on the wire.
|
||||||
TODO: Set a constant anyway?
|
TODO: Set a constant anyway?
|
||||||
|
Reference in New Issue
Block a user