prop. 152 updates

This commit is contained in:
zzz
2019-07-17 22:02:16 +00:00
parent c19c62f6d3
commit 3ea9b06bbb

View File

@@ -1,12 +1,12 @@
=======================================
Tunnels under ECIES-X25519-AEAD-Ratchet
=======================================
=============
ECIES Tunnels
=============
.. meta::
:author: chisana
:created: 2019-07-04
:thread: http://zzz.i2p/topics/2737
:lastupdated: 2019-07-04
:lastupdated: 2019-07-17
:status: Open
.. contents::
@@ -23,17 +23,43 @@ tunnels with mixed ElGamal and ECIES routers are necessary.
Specifications for how to handle mixed tunnel hops are provided.
No changes will be made to the format, processing, or encryption of ElGamal hops.
All ElGamal routers are treated as though running without changes from this document.
The proposal is split into two sections:
- ECIES for Tunnel Building
- ECIES for Tunnel Layer Encryption
If necessary, the proposal can be split into independent proposals for separate analysis and adoption.
Cryptographic Primitives
------------------------
- ChaCha20(msg, nonce, key) - as in [RFC-7539]_
- ChaCha20Poly1305(msg, nonce, AD, key) - as in [NTCP2]_ and [ECIES-X25519]_
- X25519(privateKey, publicKey) - as in [NTCP2]_ and [ECIES-X25519]_
- HKDF(rootKey, sharedSecret, CONTEXT, keylen) - as in [NTCP2]_ and [ECIES-X25519]_
- Blowfish(msg, key) - used only for ECIES-only tunnel nonce encryption, sixteen rounds cipher mode
ECIES for Tunnel Building
=========================
Goals
-----
Replace ElGamal + AES256/CBC with ECIES primitives for tunnel BuildRequestRecords and BuildReplyRecords.
Tunnel Request Records for ECIES Hops
=====================================
-------------------------------------
Request Record Spec Unencrypted (ElGamal)
-----------------------------------------
`````````````````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
bytes 0-3: tunnel ID to receive messages as, nonzero
bytes 4-35: local router identity hash
bytes 36-39: next tunnel ID, nonzero
@@ -51,11 +77,12 @@ bytes 0-3: tunnel ID to receive messages as, nonzero
{% endhighlight %}
Request Record Spec Unencrypted (ECIES)
---------------------------------------
```````````````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
bytes 0-3: tunnel ID to receive messages as, nonzero
bytes 4-35: local router identity hash
bytes 36-39: next tunnel ID, nonzero
@@ -67,34 +94,31 @@ bytes 0-3: tunnel ID to receive messages as, nonzero
{% endhighlight %}
Request Record Spec Encrypted (ECIES)
-------------------------------------
`````````````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
bytes 0-15: hop's truncated identity hash
bytes 16-31: sender's ephemeral public key
bytes 32-112: ChaChaPoly AEAD encrypted build request record
bytes 113-128: Poly1305 MAC
bytes 129-527: Random padding
bytes 16-47: sender's ephemeral public key
bytes 48-128: ChaChaPoly AEAD encrypted build request record
bytes 129-511: Random padding
bytes 512-527: Poly1305 MAC
{% endhighlight %}
**IMPORTANT**: The first 129 bytes of ECIES encrypted build request records cannot cross tunnel message fragments (breaks AEAD encryption).
TBD if it is safe for the following random padding to cross tunnel message fragments.
After full transition to ECIES records, bytes 129-527 can be a range of included padding.
When ranged padding is used, first two bytes of padding can be used to indicate padding length.
For symmetric encryption by other hops, it's necessary to know full record length (w/ padding) without asymetric decryption.
Random padding will be formatted using the Padding block structure from [ECIES-X25519]_ and [NTCP2]_.
Flag Changes for Mixed Tunnels
------------------------------
``````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
Bit order: 76543210 (bit 7 is MSB)
bit 7: if set, allow messages from anyone
bit 6: if set, allow messages to anyone, and send the reply to the
@@ -102,19 +126,21 @@ Bit order: 76543210 (bit 7 is MSB)
bit 5: if set, ChaCha20 reply encryption selected (ECIES build record),
also indicates next hop is ECIES
AES256/CBC (ElGamal) otherwise
bits 4-0: Undefined, must set to 0 for compatibility with future options
bit 4: if set, only ECIES hops in the tunnel, use Blowfish+ChaCha20 layer encryption
bits 3-0: Undefined, must set to 0 for compatibility with future options
{% endhighlight %}
Tunnel Reply Records for ECIES
==============================
------------------------------
Reply Record Spec Unencrypted (ECIES)
-------------------------------------
`````````````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
bytes 0: reply byte
{% endhighlight %}
@@ -125,25 +151,22 @@ Reply flags for ECIES reply records should use the following values to avoid fin
- 30 (TUNNEL_REJECT_BANDWIDTH)
Reply Record Spec Encrypted (ECIES)
-----------------------------------
```````````````````````````````````
.. raw:: html
{% highlight lang='dataspec' %}
bytes 0: ChaChaPoly AEAD encrypted build reply record
bytes 1-16: Poly1305 MAC
bytes 49-527: Random padding
bytes 1-511: Random padding
bytes 512-527: Poly1305 MAC
{% endhighlight %}
**IMPORTANT**: The first 17 bytes of ECIES encrypted build request records cannot cross tunnel message fragments (breaks AEAD encryption).
TBD if it is safe for the following random padding to cross tunnel message fragments.
After full transition to ECIES records, ranged padding rules are the same as for request records.
Symmetric Encryption of Asymmetrically Encrypted Records
========================================================
--------------------------------------------------------
Mixed tunnels are allowed, and necessary, for full network transition from ElGamal to ECIES.
During the transitionary period, a statistically increasing number of routers will be keyed under ECIES keys.
@@ -173,10 +196,7 @@ and the reply key is used to AES256/CBC "decrypt" its reply and other records.
This means later hops in the tunnel are preprocessed using a mix of ChaCha20
and AES256/CBC, using the reply key of preceding hops.
On the reply path, the endpoint (sender) will need to undo the multiple
encryption, using each hop's reply key.
Multiple encryption: https://en.wikipedia.org/wiki/Multiple_encryption
On the reply path, the endpoint (sender) will need to undo the [Multiple-Encryption]_, using each hop's reply key.
As a clarifying example, let's look at an outbound tunnel w/ ECIES surrounded by ElGamal:
@@ -266,10 +286,10 @@ When there are no inbound tunnels at startup, the Sender (IBEP) postprocesses th
* H2's reply key (ChaCha20)
* H1's reply key (AES256/CBC)
Request Record Key, Reply Key, Tunnel Layer and IV Key KDF (ECIES)
==================================================================
Request Record Key, Reply Key, Tunnel Layer Key, and IV Key KDF (ECIES)
---------------------------------------------------------------------------------
The `recordKey` takes the place of the product of the ElGamal exchange. It is used
The ``recordKey`` takes the place of the product of the ElGamal exchange. It is used
to AEAD encrypt request and reply records for ECIES hops.
Below is a description of how to derive the keys previously transmitted in request records.
@@ -277,6 +297,7 @@ Below is a description of how to derive the keys previously transmitted in reque
.. raw:: html
{% highlight lang='dataspec' %}
// Sender generates an X25519 ephemeral keypair per VTBM (sesk, sepk)
sesk = GENERATE_PRIVATE()
sepk = DERIVE_PUBLIC(sesk)
@@ -291,21 +312,22 @@ Below is a description of how to derive the keys previously transmitted in reque
sharedSecret = DH(sesk, hepk) = DH(hesk, sepk)
// Derive a root key from the Sha256 of Sender's ephemeral key and Hop's full identity hash
root_key = Sha256(sepk || hop_ident_hash)
rootKey = Sha256(sepk || hop_ident_hash)
keydata = HKDF(root_key, sharedSecret, "ECIESRequestRcrd", 96)
root_key = keydata[0:31] // update the root key
keydata = HKDF(rootKey, sharedSecret, "ECIESRequestRcrd", 96)
rootKey = keydata[0:31] // update the root key
recordKey = keydata[32:63] // AEAD key for Request Record encryption
replyKey = keydata[64:95] // Hop reply key
keydata = HKDF(root_key, sharedSecret, "TunnelLayerIVKey", 64)
layerKey = keydata[0:31] // Tunnel layer key
IVKey = keydata[32:63] // Tunnel IV key
keydata = HKDF(rootKey, sharedSecret, "TunnelLayerIVKey", 96)
rootKey = keydata[0:31] // update the root key
layerKey = keydata[32:63] // Tunnel layer key
IVKey = keydata[64:96] // Tunnel IV/nonce key
{% endhighlight %}
`replyKey`, `layerKey` and `IVKey` must still be included inside ElGamal records,
and can be generated randomly. The `recordKey` is just the result of ElGamal multiplication.
``replyKey``, ``layerKey`` and ``IVKey`` must still be included inside ElGamal records,
and can be generated randomly. For ElGamal, the ``recordKey`` is just the result of ElGamal multiplication.
Keys are omitted from ECIES records (since they can be derived at the hop).
@@ -315,12 +337,13 @@ Request Record Preprocessing for ECIES Hops
.. raw:: html
{% highlight lang='dataspec' %}
// See record key KDF for key generation
(ciphertext, mac) = ChaCha20-Poly1305(msg = unencrypted record, nonce = 0, AD = Sha256(recordKey), key = recordKey)
// For subsequent records past the initial hop
// nonce = one + zero-indexed order of record in the TunnelBuildMessage
symCiphertext = ChaCha20(msg = ciphertext || MAC || random padding, nonce, key = replyKey of preceding hop)
symCiphertext = ChaCha20(msg = ciphertext \|\| MAC, nonce, key = replyKey of preceding hop)
{% endhighlight %}
@@ -347,6 +370,7 @@ Reply Record Encryption for ECIES Hops
.. raw:: html
{% highlight lang='dataspec' %}
// See reply key KDF for key generation
(ciphertext, MAC) = ChaCha20-Poly1305(msg = reply byte, nonce = 0, AD = Sha256(replyKey), key = replyKey)
@@ -354,7 +378,7 @@ Reply Record Encryption for ECIES Hops
// Advance the nonce to avoid security issues, see [RFC-7539-S4]_ Security Considerations.
// nonce = one + zero-indexed order of record in the TunnelBuildMessage
symCiphertext = ChaCha20(msg = ciphertext || MAC || random padding, nonce, key = replyKey)
symCiphertext = ChaCha20(msg = ciphertext || MAC || random padding, nonce, key = replyKey)
// Other request/reply record encryption
// Advance the nonce to avoid security issues, see [RFC-7539-S4]_ Security Considerations.
@@ -383,8 +407,34 @@ Reply Record Encryption for ElGamal Hops
There are no changes for how ElGamal hops encrypt their replies.
Security Analysis for ECIES + ChaCha20 Tunnel Build Encryption
--------------------------------------------------------------
ElGamal does not provide forward-secrecy for Tunnel Build Messages.
AES256/CBC is in slightly better standing, only being vulnerable to a theoretical weakening from a
known plaintext `biclique` attack.
The only known practical attack against AES256/CBC is a padding oracle attack, when the IV is known to the attacker.
An attacker would need to break the next hop's ElGamal encryption to gain the AES256/CBC key info (reply key and IV).
ElGamal is significantly more CPU-intensive than ECIES, leading to potential resource exhaustion.
ECIES, used with new ephemeral keys per-BuildRequestRecord or VariableTunnelBuildMessage, provides forward-secrecy.
ChaCha20Poly1305 provides AEAD encryption, allowing the recipient to verify message integrity before attempting decryption.
ECIES Tunnel Layer Encryption
=============================
Goals
-----
The goal of this section is to replace AES256/ECB+CBC with Blowfish+ChaCha20 for established tunnel IV and layer encryption.
Established Tunnel Message Processing
=====================================
-------------------------------------
This section describes changes to:
@@ -392,78 +442,106 @@ This section describes changes to:
- Participant encryption + postprocessing
- Outbound and Inbound Endpoint encryption + postprocessing
Changes account for tunnels with mixed routers of non-upgraded-ElGamal and ECIES hops.
Changes are for mixed tunnels, and ElGamal hops are considered unchanged.
For an overview of current tunnel message processing, see the [Tunnel-Implementation]_ spec.
Only changes for ECIES gateways + hops are discussed.
No changes are made for ElGamal routers, meaning ECIES hops will behave
as ElGamal hops in Outbound and Inbound tunnels created by ElGamal routers.
No changes are considered for mixed tunnel with ElGamal routers, until a safe protocol can be devised
for converting a 128-bit AES IV to a 64-bit ChaCha20 nonce. Bloom filters guarantee uniqueness
for the full IV, but the first half of unique IVs could be identical.
This means ECIES routers will use current AES tunnel layer encryption whenever ElGamal hops
are present in the tunnel.
See section on build request records for ECIES hop detection of ElGamal tunnel creators.
Gateway Message Processing
--------------------------
Gateway and Tunnel Creator Message Processing
---------------------------------------------
Gateways will fragment and bundle messages in the same way, but must take care when
fragmenting I2NP messages containing AEAD frames.
Gateways will fragment and bundle messages in the same way.
AEAD frames (including the MAC) must be contained in a single fragment.
AEAD frames (including the MAC) can be split across fragments, but any dropped
fragments will result in failed AEAD decryption (failed MAC verification).
This limitation effectively reduces ECIES session messages to the length of a Tunnel Message
payload minus the inner header and wrapping I2NP message header lengths.
Gateway Preprocessing & Encryption
----------------------------------
TBD if it is safe to fragment a message header from its AEAD frame.
Gateway Encryption
------------------
For mixed tunnels, gateways will still generate an IV for use by ElGamal hops.
For ChaCha20 en/decryption, the IV and tunnel messages are concatenated together.
When tunnels are ECIES-only, gateways will generate 64-bit nonces for use by ECIES hops.
Inbound tunnels:
- Encrypt the IV and tunnel message(s) using ChaCha20
- Maintain a `tunnelNonce` counter for each set of message(s) received after successful tunnel build
- Destroy tunnel before `tunnelNonce` "rolls over": 2^96 - 1 = 79228162514264337593543950335
* unlikely to ever occur, given the lifetime of tunnels
- Use 8-byte ``tunnelNonce`` given the lifetime of tunnels
- Destroy tunnel before 2^(64/2 - 1) messages: 2^31 = 2,147,483,648
- Nonce limit in place to avoid Sweet32 attack on Blowfish
- Nonce limit unlikely to ever be reached, given this would be ~3,579,139 msgs/second for 10 minute tunnels
- Nonce cannot be truncated. For shorter nonce, a different method must be used with smaller state space.
The tunnel's Inbound Gateway (IBGW), processes messages received from another tunnel's Outbound Endpoint (OBEP).
At this point, the outermost message layer is encrypted using point-to-point transport encryption.
The I2NP message headers are visible, at the tunnel layer, to the OBEP and IBGW.
The inner I2NP messsages are wrapped in Garlic cloves, encrypted using end-to-end session encryption.
The IBGW preprocesses the messages into the appropriately formatted tunnel messages, and encrypts as following:
.. raw:: html
{% highlight lang='dataspec' %}
// Gateway generates a random IV
// Gateway encrypts concatenated IV + preprocessed tunnel messages
// Increment the nonce for each set of tunnel messages received
encIV = ChaCha20(msg = IV, nonce = tunnelNonce, key = IVKey)
// For ECIES-only tunnels
// IBGW generates a random nonce, ensuring no collision in its Bloom filter
tunnelNonce = Random(len = 64-bits)
// IBGW ChaCha20 "encrypts" the preprocessed tunnel messages with its tunnelNonce and layerKey
encMsg = ChaCha20(msg = tunnel msg(s), nonce = tunnelNonce, key = layerKey)
{% endhighlight %}
// For mixed tunnels w/ ElGamal hops (unchanged)
encIV = AES256/ECB-Encrypt(msg = prev. encIV, key = hop's IVKey)
encMsg = AES256/CBC-Encrypt(msg = tunnel msg(s), IV = encIV, key = hop's layerKey)
encIV2 = AES256/ECB-Encrypt(msg = encIV, key = hop's IVKey)
Outbound tunnels:
{% endhighlight %}
- Iteratively decrypt the IV and tunnel messages based on hop type
* ECIES hops will encrypt using ChaCha20
* ElGamal hops will encrypt using AES256/ECB
- Use the same rules for IV and layer nonces as Inbound tunnels
Tunnel message format will slightly change, using an 8-byte nonce instead of a 16-byte IV.
The rest of the format is unchanged.
Outbound tunnels:
For outbound tunnels, the tunnel creator is the Outbound Gateway (OBGW).
On outbound tunnel creation, Variable Tunnel Build Messages are created,
preprocessed (iteratively decrypted), and sent out to the first potential hop in the tunnel.
Replies are directed to a zero-hop or existing inbound tunnel's IBGW.
- Iteratively decrypt tunnel messages
- ECIES-only tunnel hops will encrypt using Blowfish+ChaCha20
- mixed-tunnel hops will encrypt using AES256/ECB+CBC
- Use the same rules for IV and layer nonces as Inbound tunnels
.. raw:: html
{% highlight lang='dataspec' %}
// Gateway generates a random IV
// For each hop, decrypt the IV and tunnel message(s) based on hop type
// Increment the nonce for each set of tunnel message(s) sent
// For the first hop, the previous decrypted IV will be the randomly generated IV
// For ECIES hops
decIV = ChaCha20(msg = prev. decIV, nonce = tunnelNonce, key = hop's IVKey)
// For ECIES-only tunnel hops
// For each hop, Blowfish-Decrypt the previous tunnelNonce with the current hop's Blowfish keys
tunnelNonce = Blowfish-Decrypt(msg = prev. tunnelNonce, key = IVKey)
// For each hop, ChaCha20 "decrypt" the tunnel message with the current hop's tunnelNonce and layerKey
decMsg = ChaCha20(msg = tunnel msg(s), nonce = tunnelNonce, key = hop's layerKey)
// For ElGamal hops (unchanged)
decIV = AES256/ECB-Decrypt(msg = prev. decIV, IV = prev. decIV, key = hop's IVKey)
decMsg = AES256/ECB-Decrypt(msg = tunnel msg(s), IV = decIV, key = hop's layerKey)
decIV2 = AES256/ECB-Decrypt(msg = decIV, IV = decIV, key = hop's IVKey)
// Tunnel creator generates a random IV
// For each hop, decrypt the IV and tunnel message(s)
// For the first hop, the previous decrypted IV will be the randomly generated IV
decIV = AES256/ECB-Decrypt(msg = prev. decIV, key = hop's IVKey)
decMsg = AES256/CBC-Decrypt(msg = tunnel msg(s), IV = decIV, key = hop's layerKey)
decIV2 = AES256/ECB-Decrypt(msg = decIV, key = hop's IVKey)
{% endhighlight %}
@@ -473,27 +551,113 @@ Participant Processing
Participants will track seen messages in the same way, using decaying Bloom filters.
IV double-encryption is no longer necessary for ECIES hops,
since there are no confirmation attacks against ChaCha20.
since there are no padding-oracle attacks against ChaCha20.
Use of multiple encryption with ChaCha20 and AES256/ECB also prevents the confirmation attack
against ElGamal hops.
ChaCha20 hops will encrypt the received nonce to prevent confirmation attacks between prior and later hops,
i.e. colluding, non-consecutive hops being able to tell they belong to the same tunnel.
IV double-encryption will still be used for ElGamal hops, since they are considered unchanged.
IV double-encryption will still be used for mixed-tunnel hops, since they are considered unchanged.
To validate received ``tunnelNonce``, the participant checks against its Bloom filter for duplicates.
After validation, the participant:
- Blowfish encrypts the ``tunnelNonce`` with its ``IVKey``
- Uses the encrypted ``tunnelNonce`` & its ``layerKey`` to ChaCha20 encrypt the tunnel message(s)
- Sends the tuple {``tunnelId``, encrypted ``tunnelNonce``, ciphertext} to the next hop.
.. raw:: html
{% highlight lang='dataspec' %}
// For ECIES hops
encIV = ChaCha20(msg = received IV, nonce = tunnelNonce, key = IVKey)
encMsg = ChaCha20(msg = received Msg, nonce = tunnelNonce, key = layerKey)
// For ECIES-only tunnel hops
// For verification, tunnel participant should check Bloom filter for received nonce uniqueness
// After verification, Blowfish encrypt the tunnelNonce with the hop's IVKey
tunnelNonce = Blowfish-Encrypt(msg = received tunnelNonce, key = IVKey)
encMsg = ChaCha20(msg = received message, nonce = tunnelNonce, key = layerKey)
// For ElGamal hops (unchanged)
currentIV = AES256/ECB-Encrypt(msg = received IV, IV = received IV, key = hop's IVKey)
encMsg = AES256/ECB-Encrypt(msg = tunnel msg(s), IV = currentIV, key = hop's layerKey)
nextIV = AES256/ECB-Encrypt(msg = currentIV, IV = currentIV, key = hop's IVKey)
currentIV = AES256/ECB-Encrypt(msg = received IV, key = hop's IVKey)
encMsg = AES256/CBC-Encrypt(msg = tunnel msg(s), IV = currentIV, key = hop's layerKey)
nextIV = AES256/ECB-Encrypt(msg = currentIV, key = hop's IVKey)
{% endhighlight %}
Inbound Endpoint Processing
---------------------------
Inbound Endpoints will check the composition of their tunnel hops (ECIES or ElGamal).
Mixed tunnels are considered unchanged for tunnel layer encryption.
For ECIES-only tunnels, the following scheme will be used:
- Validate the received ``tunnelNonce`` against the Bloom filter
- ChaCha20 decrypt the encrypted data using the received ``tunnelNonce`` & the hop's ``layerKey``
- Blowfish decrypt the ``tunnelNonce`` using the hop's ``IVKey`` to get the preceding ``tunnelNonce``
- ChaCha20 decrypt the encrypted data using the decrypted ``tunnelNonce`` & the preceding hop's ``layerKey``
- Repeat for each hop in the tunnel, back to the IBGW
.. raw:: html
{% highlight lang='dataspec' %}
// For ECIES-only tunnel hops
// Repeat for each hop in the tunnel back to the IBGW
// Replace the received tunnelNonce w/ the prior round hop's decrypted tunnelNonce for subsequent hops
tunnelNonce = Blowfish-Decrypt(msg = received tunnelNonce, key = IVKey)
decMsg(s) = ChaCha20(msg = encrypted layer message(s), nonce = tunnelNonce, key = layerKey)
// For mixed tunnel hops (unchanged)
// Repeat for each hop in the tunnel back to the IBGW
// Replace the received IV w/ the prior round hop's double-decrypted IV for subsequent hops
decIV = AES256/ECB(msg = received IV, key = IVKey)
decMsg = AES256/CBC(msg = tunnel msg(s), IV = decIV, key = layerKey)
decIV2 = AES256/ECB(msg = decIV, key = IVKey)
{% endhighlight %}
Security Analysis for Blowfish+ChaCha20 Tunnel Layer Encryption
------------------------------------------------------
Switching from AES256/ECB to ChaCha20 has a number of advantages, and new security considerations.
The biggest security considerations to account for, are that ChaCha20 nonces must be unique per-message,
for the life of the key being used, and Blowfish is susceptible to Sweet32 birthday attacks.
Failing to use unique nonces with the same key on different messages breaks ChaCha20.
Nonce uniqueness is main reason for using an Blowfish, see [RFC-7539-S4]_.
Simple counters cannot be used, since they require syncing for proper decryption.
Syncing the counter can't be guaranteed at the IBEP, without further changes to tunnel protocols.
Blowfish is only used for nonce encryption to guarantee unique nonces, and prevent non-consecutive
hops in the same tunnel from colluding to know they are in the same tunnel.
The tunnel lifetime of ten minutes and nonce limit of 2^31 messages guarantees that Sweet32 attacks
are ineffective against Blowfish. Exceeding the limit would require over ~3,579,139 messages/second in each tunnel.
Even if 2^31 messages proves to not be a strict enough limit, we can safely reduce the limit by another power of two,
without ever realistically reaching the limit.
Even if a Sweet32 attack were successful, an attacker would only gain access to the ``tunnelNonce``
for the colliding message, which doesn't break the ChaCha20 encryption. Non-consecutive hops
would only be able to confirm they are participants in the same tunnel.
The biggest security advantage is that there are no confirmation or oracle attacks against ChaCha20.
There are chosen/known-plaintext attacks against AES256/ECB, when the key is reused (as in tunnel layer encryption).
It is unlikely the chosen-plaintext attack can be used to recover double-encrypted IVs, since it requires at least two blocks
to be encrypted, and a single pass of the cipher.
An attack confirming a chosen plaintext IV is much more likely, but still unclear if it would be successful given
double-encryption.
The chosen-plaintext producing a recovered IV cannot be used to perform
a padding-oracle attack against AES256/CBC layer encryption, since duplicate IVs are rejected.
Tunnel Message Overhead for ECIES
=================================
@@ -501,82 +665,75 @@ Wrapped I2NP message overhead:
- I2NP Block header: 3 (block type + size) + 9 (I2NP message header) = 12
- New Session Message:
* 25 (min payload len) + 16 (MAC) = 41
* 32 (one-time key) + 40 (ephemeral section) + 16 (MAC) + 41 (min payload) = 129 unbound
* 88 (unbound) + 32 (static section) + 16 (MAC) + 41 (min payload) = 177 bound
- 25 (min payload len) + 16 (MAC) = 41
- 32 (one-time key) + 40 (ephemeral section) + 16 (MAC) + 41 (min payload) = 129 unbound
- 88 (unbound) + 32 (static section) + 16 (MAC) + 41 (min payload) = 177 bound
- Existing Message: 8 (session tag) + payload len + 16 (MAC) = 24 + payload len
- New session:
* 12 (I2NP) + 129 (unbound) = 141 + payload
* 12 (I2NP + 177 (bound) = 189 + payload
- 12 (I2NP) + 129 (unbound) = 141 + payload
- 12 (I2NP + 177 (bound) = 189 + payload
- Existing Session: 12 (I2NP) + 24 = 36 + payload
- Build Request Record: 528 (ElGamal, mixed tunnels)
- Build Request Reply: 528 (ElGamal, mixed tunnels)
Tunnel message overhead:
Tunnel IV no longer needed, unused space claimed by trailing 16 byte Poly1305 MAC
Follow-on fragments no longer usable, all messages must fit in a single fragment
Wrapped I2NP message overhead:
- 4 (tunnel ID) + 1 (padding delim) + 4 (checksum) = 9 (header)
- 3 (first, local delivery)
- 35 (first, router delivery)
- 39 (first, tunnel delivery)
- 7 (follow-on)
- I2NP Block header: 3 (block type + size) + 9 (I2NP message header) = 12
- New Session Message:
Number of messages wrapped in a tunnel message with current max (1024 bytes):
- 25 (min payload len) + 16 (MAC) = 41
- 32 (one-time key) + 40 (ephemeral section) + 16 (MAC) + 41 (min payload) = 129 unbound
- 88 (unbound) + 32 (static section) + 16 (MAC) + 41 (min payload) = 177 bound
- 1024 - 9 (header) = 1015 (max payload length)
- Existing Message: 8 (session tag) + payload len + 16 (MAC) = 24 + payload len
Variable Tunnel Build Message:
- New session:
- For 8 build records, 4 Tunnel Data Messages:
- 1015 = `39 (tunnel) + 528` + `39 (tunnel) + 445`
- 1015 = `7 (follow) + 83` + `39 (tunnel) + 528` + `39 (tunnel) + 319`
- 1015 = `7 (follow) + 209` + `39 (tunnel) + 528` + `39 (tunnel) + 193`
- 1015 = `7 (follow) + 335` + `39 (tunnel) + 528`
- 12 (I2NP) + 129 (unbound) = 141 + payload
- 12 (I2NP + 177 (bound) = 189 + payload
- For 4-5 build records, 3 Tunnel Data Messages:
- 1015 = `39 (tunnel) + 528` + `39 (tunnel) + 445`
- 1015 = `7 (follow) + 83` + `39 (tunnel) + 528` + `39 (tunnel) + 319`
- 1015 = `7 (follow) + 209` + `39 (tunnel) + 528`
- Existing Session: 12 (I2NP) + 24 = 36 + payload
- Build Request Record: 528 (ElGamal, mixed tunnels)
- Build Request Reply: 528 (ElGamal, mixed tunnels)
- For 2-3 build records, 2 Tunnel Data Messages:
- 1015 = `39 (tunnel) + 528` + `39 (tunnel) + 445`
- 1015 = `7 (follow) + 83` + `39 (tunnel) + 528`
Tunnel message overhead:
Even with fragment messages on the edges, all tunnel messages safely contain the ECIES build
request and reply record AEAD frames.
Tunnel layer keys, IV keys, and reply keys no longer need to be transmitted in ECIES BuildRequest Records.
Unused space claimed by random padding and the trailing 16 byte Poly1305 MAC.
Additional payloads calculated on average, distributed evenly per message.
Can adjust number of messages to fit bigger payloads per message, these are just examples.
ECIES session messages will be wrapped in I2NP Data messages, surrounded by a Garlic Clove,
and fragmented in Tunnel Data messages like any other message.
Unbound New Session Message (min payload + addtl. payload):
- 1015 / (3 (local) + 141 + payload) = 7 msgs + 6 bytes per addtl. payload
- 1015 / (35 (router) + 141 + payload) = 5 msgs + 134 bytes per addtl. payload
- 1015 / (39 (tunnel) + 141 + payload) = 5 msgs + 115 bytes per addtl. payload
Bound New Session Message (min payload + addtl. payload):
- 1015 / (3 (local) + 189 + payload) = 5 msgs + 54 bytes per addtl. payload
- 1015 / (35 (router) + 189 + payload) = 4 msgs + 119 bytes per addtl. payload
- 1015 / (39 (tunnel) + 189 + payload) = 4 msgs + 103 bytes per addtl. payload
Existing Session Message (+ payload len):
- 1015 / (3 (local) + 36 + payload) = 17 msgs + 20 bytes per payload
- 1015 / (35 (router) + 36 + payload) = 14 msgs + 21 bytes per payload
- 1015 / (39 (tunnel) + 36 + payload) = 13 msgs + 39 bytes per payload
Dropped fragments will result in AEAD decryption failure (fails MAC verification),
resulting in the entire message being dropped.
References
==========
.. [Prop144]
.. [ECIES-X25519]
{{ proposal_url('144') }}
.. [NTCP2]
https://geti2p.net/spec/ntcp2
.. [Tunnel-Implementation]
https://geti2p.net/en/docs/tunnels/implementation
.. [Multiple-Encryption]
https://en.wikipedia.org/wiki/Multiple_encryption
.. [RFC-7539]
https://tools.ietf.org/html/rfc7539
.. [RFC-7539-S4]
https://tools.ietf.org/html/rfc7539#section-4
.. [SplitMix64]
http://xoshiro.di.unimi.it/splitmix64.c