From 8289febc2acd6dd6c1278434d538ed38dedb32f6 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 4 Aug 2019 12:51:52 +0000 Subject: [PATCH] Updates for proposals 144, 147, 152 New proposal 153 split out from 152 --- .../144-ecies-x25519-aead-ratchet.rst | 10 +- .../147-transport-network-id-check.rst | 8 +- i2p2www/spec/proposals/152-ecies-tunnels.rst | 279 +-------------- .../153-chacha20-layer-encryption.rst | 335 ++++++++++++++++++ 4 files changed, 353 insertions(+), 279 deletions(-) create mode 100644 i2p2www/spec/proposals/153-chacha20-layer-encryption.rst diff --git a/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst b/i2p2www/spec/proposals/144-ecies-x25519-aead-ratchet.rst index a1777817b..f4b016acb 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-07-26 + :lastupdated: 2019-08-04 :status: Open .. contents:: @@ -109,6 +109,8 @@ Goals be a separate proposal - Don't break anything that relies on 32-byte binary destination hashes, e.g. bittorrent - Maintain 0-RTT message delivery using ephemeral-static DH +- Do not require buffering / queueing of messages at this protocol layer; + continue to support unlimited message delivery in both directions without waiting for a response - Upgrade to ephemeral-ephemeral DH after 1 RTT - Maintain handling of out-of-order messages - Maintain 256-bit security @@ -153,7 +155,9 @@ Non-Goals / Out-of-scope - LS2 format (see proposal 123) - New DHT rotation algorithm or shared random generation - New encryption for tunnel building. - That would be in a separate proposal. + See proposal 152. +- New encryption for tunnel layer encryption. + See proposal 153. - Methods of encryption, transmission, and reception of I2NP DLM / DSM / DSRM messages. Not changing. - No LS1-to-LS2 or ElGamal/AES-to-this-proposal communication is supported. @@ -168,7 +172,7 @@ Non-Goals / Out-of-scope Justification ------------- -ElGamal/AES+SessionTag has been our sole end-to-end protocol for around for about 15 years, +ElGamal/AES+SessionTag has been our sole end-to-end protocol for about 15 years, essentially without modifications to the protocol. There are now cryptographic primitives that are faster. We need to enhance the security of the protocol. diff --git a/i2p2www/spec/proposals/147-transport-network-id-check.rst b/i2p2www/spec/proposals/147-transport-network-id-check.rst index 67a5cbd13..890144ce1 100644 --- a/i2p2www/spec/proposals/147-transport-network-id-check.rst +++ b/i2p2www/spec/proposals/147-transport-network-id-check.rst @@ -5,7 +5,7 @@ Transport Network ID Check :author: zzz :created: 2019-02-28 :thread: http://zzz.i2p/topics/2687 - :lastupdated: 2019-07-16 + :lastupdated: 2019-08-04 :status: Open .. contents:: @@ -125,7 +125,7 @@ HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey) '+' means append and '^' means exclusive-or. payloadLength is a 2 byte unsigned integer - protocolVersion is two bytes 0x0000 + protocolVersion is one byte 0x00 {% endhighlight %} @@ -134,11 +134,11 @@ New: .. raw:: html {% highlight lang='dataspec' %} -HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion ^ ((netid - 2) << 1)), macKey) +HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion ^ ((netid - 2) << 8)), macKey) '+' means append, '^' means exclusive-or, '<<' means left shift. payloadLength is a 2 byte unsigned integer - protocolVersion is two bytes 0x0000 + protocolVersion is one byte 0x00 netid is a 1 byte unsigned integer diff --git a/i2p2www/spec/proposals/152-ecies-tunnels.rst b/i2p2www/spec/proposals/152-ecies-tunnels.rst index f2ded763c..e8126a3bd 100644 --- a/i2p2www/spec/proposals/152-ecies-tunnels.rst +++ b/i2p2www/spec/proposals/152-ecies-tunnels.rst @@ -6,7 +6,7 @@ ECIES Tunnels :author: chisana :created: 2019-07-04 :thread: http://zzz.i2p/topics/2737 - :lastupdated: 2019-07-26 + :lastupdated: 2019-08-04 :status: Open .. contents:: @@ -27,12 +27,7 @@ No changes will be made to the format, processing, or encryption of ElGamal hops ElGamal tunnel creators will need to create ephemeral X25519 keypairs per-hop, and follow this spec for creating tunnels containing ECIES hops. -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. +This proposal specifies changes needed for ECIES-X25519 Tunnel Building. Cryptographic Primitives ------------------------ @@ -117,24 +112,6 @@ are supported, TBD. Ranged 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 - specified next hop in a Tunnel Build Reply Message - bit 5: if set, use new (ChaCha20) layer encryption - bits 4-0: Undefined, must set to 0 for compatibility with future options - -{% endhighlight %} - -New layer encryption flag may be moved into Tunnel Build Options, TBD. - Tunnel Reply Records for ECIES ------------------------------ @@ -349,11 +326,9 @@ This means that tunnel hops will only see encrypted records from their same encr For ElGamal and ECIES tunnel creators, they will generate unique ephemeral X25519 keypairs per-hop for encrypting to ECIES hops. -**WARNING**: if the same ephemeral keypair is used for more than one hop, it can only be -used for at most **two** hops, and the hops must be **consecutive**. +Ephemeral keys must be unique per ECIES hop, and per build record. -**WARNING**: Using the same ephemeral keys for non-consecutive hops, or more than two hops, -allows colluding hops to know they're in the same tunnel, **VERY BAD**!!! +**IMPORTANT**: Failing to use unique keys opens an attack vector for colluding hops to confirm they are in the same tunnel. .. raw:: html @@ -372,7 +347,7 @@ allows colluding hops to know they're in the same tunnel, **VERY BAD**!!! Reply Record Encryption for ECIES Hops -------------------------------------- -The nonce must be unique per ChaCha20/ChaCha20-Poly1305 invocation using the same key. +The nonces must be unique per ChaCha20/ChaCha20-Poly1305 invocation using the same key. See [RFC-7539-S4]_ Security Considerations for more information. @@ -426,246 +401,6 @@ ECIES, used with new ephemeral keys per-BuildRequestRecord or VariableTunnelBuil 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: - -- Outbound and Inbound Gateway preprocessing + encryption -- Participant encryption + postprocessing -- Outbound and Inbound Endpoint encryption + postprocessing - -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 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 and Tunnel Creator Message Processing ---------------------------------------------- - -Gateways will fragment and bundle messages in the same way. - -AEAD frames (including the MAC) can be split across fragments, but any dropped -fragments will result in failed AEAD decryption (failed MAC verification). - -Gateway Preprocessing & Encryption ----------------------------------- - -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 -- Use 8-byte ``tunnelNonce`` given the lifetime of tunnels -- Use 8-byte monotonically increasing counter for ``tunnelNonce`` encryption -- Destroy tunnel before 2^(64 - 1) messages: 2^64 - 1 = 18,446,744,073,709,551,615 - - - Nonce limit in place to avoid rollover of the 64-bit counter - - Nonce limit exceedingly unlikely to ever be reached, given this would be over ~3,074,457,345,618,258 msgs/second for 10 minute tunnels - -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' %} - -// For ECIES-only tunnels - // IBGW generates a random nonce, ensuring no collision in its Bloom filter - tunnelNonce = Random(len = 64-bits) - counter = counter + 1 - // IBGW ChaCha20 "encrypts" the preprocessed tunnel messages with its tunnelNonce and layerKey - encMsg = ChaCha20(msg = tunnel msg(s), nonce = tunnelNonce, key = layerKey) - - // 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) - -{% endhighlight %} - -Tunnel message format will slightly change, using an 8-byte nonce instead of a 16-byte IV. -The counter used for encrypting the nonce is appended to the 8-byte ``tunnelNonce``. -The counter is not advanced by tunnel participants. -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 ChaCha20 - - mixed-tunnel hops will encrypt using AES256/ECB+CBC - -- Use the same rules for IV and layer nonces as Inbound tunnels -- For ECIES-only tunnels, advance the nonce once per set of tunnel messages sent - -.. raw:: html - - {% highlight lang='dataspec' %} - - -// For ECIES-only tunnel hops - // For each set of messages, increase the counter - counter = counter + 1 - // For each hop, ChaCha20 the previous tunnelNonce with the current hop's IV key - // The counter is advanced for each set of tunnel messages - tunnelNonce = ChaCha20(msg = prev. tunnelNonce, nonce = counter, 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) - // 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 %} - -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 padding-oracle attacks against ChaCha20. - -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 mixed-tunnel hops, since they are considered unchanged. - -To validate received ``tunnelNonce``, the participant checks against its Bloom filter for duplicates. - -To validate the received counter, the participant checks against it counter Bloom filter for duplicates. - -The two Bloom filters must be independent from one another. - -Participants do not advance the counter. - -After validation, the participant: - -- ChaCha20 encrypts the ``tunnelNonce`` with its ``IVKey`` and received counter -- 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-only tunnel hops - // For verification, tunnel participant should check Bloom filter for received nonce uniqueness - // The counter must also be checked for uniqueness against its own independent Bloom filter - // After verification, ChaCha20 encrypt the tunnelNonce with the hop's IVKey - tunnelNonce = ChaCha20(msg = received tunnelNonce, nonce = received counter, key = IVKey) - encMsg = ChaCha20(msg = received message, nonce = tunnelNonce, key = layerKey) - - // For ElGamal hops (unchanged) - 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`` and counter against the respective Bloom filters -- ChaCha20 decrypt the encrypted data using the received ``tunnelNonce`` & the hop's ``layerKey`` -- ChaCha20 decrypt the ``tunnelNonce`` using the hop's ``IVKey`` and received counter 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 = ChaCha20(msg = received tunnelNonce, nonce = received counter, 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 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. - -Failing to use unique nonces with the same key on different messages breaks ChaCha20. - -Simple counters will be used alongside the ``tunnelNonce`` for encrypting the nonce, -since they are required for proper decryption by the IBEP. - -Using an appended counter allows the IBEP to decrypt the ``tunnelNonce`` for each hop's layer encryption, -recovering the previous nonce. - -The 64-bit counter alongside the ``tunnelNonce`` doesn't reveal any new information to tunnel hops, -and cannot be used for correlation attacks. The counter also doesn't need to be private, as it only -needs to be unique per-message in a given tunnel. Uniqueness can be ensured by a second Bloom filter, -tracking which counter values have been used. - -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 ================================= @@ -713,8 +448,8 @@ Wrapped I2NP message overhead: Tunnel message overhead: -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. +Tunnel layer keys, IV/nonce keys, and reply keys no longer need to be transmitted in ECIES BuildRequest Records. +Unused space claimed by build options, random padding, and the trailing 16 byte Poly1305 MAC. 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. diff --git a/i2p2www/spec/proposals/153-chacha20-layer-encryption.rst b/i2p2www/spec/proposals/153-chacha20-layer-encryption.rst new file mode 100644 index 000000000..e8283be41 --- /dev/null +++ b/i2p2www/spec/proposals/153-chacha20-layer-encryption.rst @@ -0,0 +1,335 @@ +ChaCha Tunnel Layer Encryption +============================== + +.. meta:: + :author: chisana + :created: 2019-08-04 + :thread: http://zzz.i2p/topics/2753 + :lastupdated: 2019-08-04 + :status: Draft + +.. contents:: + +Overview +======== + +This proposal builds on and requires the changes from proposal 152: ECIES Tunnels. + +Only tunnels built through hops supporting the BuildRequestRecord format for ECIES-X25519 +tunnels can implement this specification. + +This specification requires the Tunnel Build Options format for indicating +tunnel layer encryption type, and transmitting layer AEAD keys. + +Goals +----- + +The goals of this proposal are to: + +- Replace AES256/ECB+CBC with ChaCha20 for established tunnel IV and layer encryption +- Use ChaCha20-Poly1305 for inter-hop AEAD protection +- Be undetectable from existing tunnel layer encryption by non-tunnel participants +- Make no changes to overall tunnel message length + +Established Tunnel Message Processing +------------------------------------- + +This section describes changes to: + +- Outbound and Inbound Gateway preprocessing + encryption +- Participant encryption + postprocessing +- Outbound and Inbound Endpoint encryption + postprocessing + +For an overview of current tunnel message processing, see the [Tunnel-Implementation]_ spec. + +Only changes for routers supporting ChaCha20 layer encryption are discussed. + +No changes are considered for mixed tunnel with AES layer encryption, 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 layer encryption must be uniform for all hops in the tunnel, and established using +tunnel build options during the tunnel creation process. + +All gateways and tunnel participants will need to maintain a Bloom filter for validating the two independent nonces. + +The ``nonceKey`` mentioned throughout this proposal takes the place of the ``IVKey`` used in AES layer encryption. +It is generated using the same KDF from proposal 152. + +AEAD Encryption of Hop-to-Hop Messages +-------------------------------------- + +An additional unique ``AEADKey`` will need to be generated for each pair of consecutive hops. +This key will be used by consecutive hops to ChaCha20-Poly1305 encrypt and decrypt the +inner ChaCha20 encrypted tunnel message. + +Tunnel messages will need to reduce the length of the inner encrypted frame by 16 bytes to +accommodate the Poly1305 MAC. + +AEAD cannot be used on the messages directly, since iterative decryption is needed by outbound tunnels. +Iterative decryption can only be achieved, in the way it's used now, using ChaCha20 without AEAD. + +.. raw:: html + + {% highlight lang='dataspec' -%} ++----+----+----+----+----+----+----+----+ + | Tunnel ID | tunnelNonce | + +----+----+----+----+----+----+----+----+ + | tunnelNonce cont. | obfsNonce | + +----+----+----+----+----+----+----+----+ + | obfsNonce cont. | | + +----+----+----+----+ + + | | + + Encrypted Data + + ~ ~ + | | + + +----+----+----+----+ + | | Poly1305 MAC | + +----+----+----+----+ + + | | + + +----+----+----+----+ + | | + +----+----+----+----+ + + Tunnel ID :: `TunnelId` + 4 bytes + the ID of the next hop + + tunnelNonce :: + 8 bytes + the tunnel layer nonce + + obfsNonce :: + 8 bytes + the tunnel layer nonce encryption nonce + + Encrypted Data :: + 992 bytes + the encrypted tunnel message + + Poly1305 MAC :: + 16 bytes + + total size: 1028 Bytes +{% endhighlight %} + +Inner hops (with preceding and following hops), will have two ``AEADKeys``, one for decrypting +the AEAD layer of the previous hop, and encrypting the AEAD layer to the following hop. + +All inner hop participants will thus have 64 additional bytes of key material included in their BuildRequestRecords. + +The Outbound Endpoint and Inbound Gateway will only require an additional 32 bytes of keydata, +since they do not tunnel layer encrypt messages between each other. + +The Outbound Gateway generates its ``outAEAD`` key, which is the same as the first +outbound hop's ``inAEAD`` key. + +The Inbound Endpoint generates its ``inAEAD`` key, which is the same as the final +inbound hop's ``outAEAD`` key. + +Inner hops will receive and ``inAEADKey`` and ``outAEADKey`` which will be used to AEAD decrypt +incoming messages and encrypt outgoing messages, respectively. + +As an example, in a tunnel with inner hops OBGW, A, B, OBEP: + +- A's ``inAEADKey`` is the same as the OBGW's ``outAEADKey`` +- B's ``inAEADKey`` is the same as A's ``outAEADKey`` +- B's ``outAEADKey`` is the same as OBEP's ``inAEADKey`` + +Keys are unique to hop pairs, so OBEP's ``inAEADKey`` will be different than A's ``inAEADKey``, +A's ``outAEADKey`` different than B's ``outAEADKey``, etc. + +Gateway and Tunnel Creator Message Processing +--------------------------------------------- + +Gateways will fragment and bundle messages in the same way, reserving space after the instructions-fragment +frame for the Poly1305 MAC. + +Inner I2NP messages containing AEAD frames (including the MAC) can be split across fragments, +but any dropped fragments will result in failed AEAD decryption (failed MAC verification) at the +endpoint. + +Gateway Preprocessing & Encryption +---------------------------------- + +When tunnels support ChaCha20 layer encryption, gateways will generate two 64-bit nonces per message set. + +Inbound tunnels: + +- Encrypt the IV and tunnel message(s) using ChaCha20 +- Use 8-byte ``tunnelNonce`` and ``obfsNonce`` given the lifetime of tunnels +- Use 8-byte ``obfsNonce`` for ``tunnelNonce`` encryption +- Destroy tunnel before 2^(64 - 1) - 1 sets of messages: 2^63 - 1 = 9,223,372,036,854,775,807 + + - Nonce limit in place to avoid collision of the 64-bit nonces + - Nonce limit nearly impossible to ever be reached, given this would be over ~15,372,286,728,091,294 msgs/second for 10 minute tunnels + +- Tune the Bloom filter based on a reasonable number of expected elements (128 msgs/sec, 1024 msgs/sec? TBD) + +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' %} + +// IBGW generates random nonces, ensuring no collision in its Bloom filter for each nonce + tunnelNonce = Random(len = 64-bits) + obfsNonce = Random(len = 64-bits) + // IBGW ChaCha20 "encrypts" each of the preprocessed tunnel messages with its tunnelNonce and layerKey + encMsg = ChaCha20(msg = tunnel msg, nonce = tunnelNonce, key = layerKey) + + // ChaCha20-Poly1305 encrypt each message's encrypted data frame with the tunnelNonce and outAEADKey + (encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = encMsg, nonce = tunnelNonce, key = outAEADKey) +{% endhighlight %} + +Tunnel message format will slightly change, using two 8-byte nonces instead of a 16-byte IV. +The ``obfsNonce`` used for encrypting the nonce is appended to the 8-byte ``tunnelNonce``, +and is encrypted by each hop using the encrypted ``tunnelNonce`` and the hop's ``nonceKey``. + +After the message set has be pre-emptively decrypted for each hop, the Outbound Gateway +ChaCha20-Poly1305 AEAD encrypts the ciphertext portion of each tunnel message using +the ``tunnelNonce`` and its ``outAEADKey``. + +Outbound tunnels: + +- Iteratively decrypt tunnel messages +- ChaCha20-Poly1305 encrypt preemptively decrypted tunnel message encrypted frames +- Use the same rules for layer nonces as Inbound tunnels +- Generate random nonces once per set of tunnel messages sent + +.. raw:: html + + {% highlight lang='dataspec' %} + + +// For each set of messages, generate unique, random nonces + tunnelNonce = Random(len = 64-bits) + obfsNonce = Random(len = 64-bits) + + // For each hop, ChaCha20 the previous tunnelNonce with the current hop's IV key + tunnelNonce = ChaCha20(msg = prev. tunnelNonce, nonce = obfsNonce, key = hop's nonceKey) + + // 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 each hop, ChaCha20 "decrypt" the obfsNonce with the current hop's encrypted tunnelNonce and nonceKey + obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = hop's nonceKey) + + // After hop processing, ChaCha20-Poly1305 encrypt each tunnel message's "decrypted" data frame with the first hop's encrypted tunnelNonce and inAEADKey + (encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = decMsg, nonce = first hop's encrypted tunnelNonce, key = first hop's inAEADKey / GW outAEADKey) +{% endhighlight %} + +Participant Processing +---------------------- + +Participants will track seen messages in the same way, using decaying Bloom filters. + +Tunnel nonces will each need to be encrypted once per-hop, to prevent confirmation attacks +by non-consecutive, colluding hops. + +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. + +To validate received ``tunnelNonce`` and ``obfsNonce``, participants check each nonce individually +against their Bloom filter for duplicates. + +After validation, the participant: + +- ChaCha20-Poly1305 decrypts each tunnel message's AEAD ciphertext with the received ``tunnelNonce`` and its ``inAEADKey`` +- ChaCha20 encrypts the ``tunnelNonce`` with its ``nonceKey`` and received ``obfsNonce`` +- ChaCha20 encrypts the each tunnel message's encrypted data frame with the encrypted ``tunnelNonce`` and its ``layerKey`` +- ChaCha20-Poly1305 encrypts each tunnel message's encrypted data frame the encrypted ``tunnelNonce`` and its ``outAEADKey`` +- ChaCha20 encrypts the ``obfsNonce`` with its ``nonceKey`` and encrypted ``tunnelNonce`` +- Sends the tuple {``nextTunnelId``, encrypted (``tunnelNonce`` || ``obfsNonce``), AEAD ciphertext || MAC} to the next hop. + +.. raw:: html + + {% highlight lang='dataspec' %} + +// For verification, tunnel hops should check Bloom filter for each received nonce's uniqueness + // After verification, unwrap the AEAD frame(s) byChaCha20-Poly1305 decrypt each tunnel message's encrypted frame + // with the received tunnelNonce and inAEADKey + encTunMsg = ChaCha20-Poly1305-Decrypt(msg = received encMsg \|\| MAC, nonce = received tunnelNonce, key = inAEADKey) + + // ChaCha20 encrypt the tunnelNonce with the obfsNonce and hop's nonceKey + tunnelNonce = ChaCha20(msg = received tunnelNonce, nonce = received obfsNonce, key = nonceKey) + + // ChaCha20 encrypt each tunnel message's encrypted data frame with the encrypted tunnelNonce and hop's layerKey + encMsg = ChaCha20(msg = encTunMsg, nonce = tunnelNonce, key = layerKey) + + // For AEAD protection, also ChaCha20-Poly1305 encrypt each message's encrypted data frame + // with the encrypted tunnelNonce and the hop's outAEADKey + (encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = encMsg, nonce = tunnelNonce, key = outAEADKey) + + // ChaCha20 encrypt the received obfsNonce with the encrypted tunnelNonce and hop's nonceKey + obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = nonceKey) +{% endhighlight %} + +Inbound Endpoint Processing +--------------------------- + +For ChaCha20 tunnels, the following scheme will be used to decrypt each tunnel message: + +- Validate the received ``tunnelNonce`` and ``obfsNonce`` independently against its Bloom filter +- ChaCha20-Poly1305 decrypt the encrypted data frame using the received ``tunnelNonce`` and ``inAEADKey`` +- ChaCha20 decrypt the encrypted data frame using the received ``tunnelNonce`` & the hop's ``layerKey`` +- ChaCha20 decrypt the ``obfsNonce`` using the hop's ``nonceKey`` and received ``tunnelNonce`` to get the preceding ``obfsNonce`` +- ChaCha20 decrypt the received ``tunnelNonce`` using the hop's ``nonceKey`` and decrypted ``obfsNonce`` to get the preceding ``tunnelNonce`` +- ChaCha20 decrypt the encrypted data using the decrypted ``tunnelNonce`` & the preceding hop's ``layerKey`` +- Repeat the steps for nonce and layer decryption for each hop in the tunnel, back to the IBGW +- The AEAD frame decryption is only needed in the first round + +.. raw:: html + + {% highlight lang='dataspec' %} + +// For the first round, ChaCha20-Poly1305 decrypt each message's encrypted data frame + MAC + // using the received tunnelNonce and inAEADKey + msg = encTunMsg \|\| MAC + tunnelNonce = received tunnelNonce + encTunMsg = ChaCha20-Poly1305-Decrypt(msg, nonce = tunnelNonce, key = inAEADKey) + + // Repeat for each hop in the tunnel back to the IBGW + // For every round, ChaCha20 decrypt each hop's layer encryption on each message's encrypted data frame + // Replace the received tunnelNonce w/ the prior round's decrypted tunnelNonce for each hop + decMsg = ChaCha20(msg = encTunMsg, nonce = tunnelNonce, key = layerKey) + obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = nonceKey) + tunnelNonce = ChaCha20(msg = tunnelNonce, nonce = obfsNonce, key = nonceKey) +{% endhighlight %} + +Security Analysis for ChaCha20+ChaCha20-Poly1305 Tunnel Layer Encryption +------------------------------------------------------------------------ + +Switching from AES256/ECB+AES256/CBC to ChaCha20+ChaCha20-Poly1305 has a number of advantages, and new security considerations. + +The biggest security considerations to account for, are that ChaCha20 and ChaCha20-Poly1305 nonces must be unique per-message, +for the life of the key being used. + +Failing to use unique nonces with the same key on different messages breaks ChaCha20 and ChaCha20-Poly1305. + +Using an appended ``obfsNonce`` allows the IBEP to decrypt the ``tunnelNonce`` for each hop's layer encryption, +recovering the previous nonce. + +The ``obfsNonce`` alongside the ``tunnelNonce`` doesn't reveal any new information to tunnel hops, +since the ``obfsNonce`` is encrypted using the encrypted ``tunnelNonce``. This also allows the IBEP to recover +the previous ``obfsNonce`` in a similar way to ``tunnelNonce`` recovery. + +The biggest security advantage is that there are no confirmation or oracle attacks against ChaCha20, +and using ChaCha20-Poly1305 between hops adds AEAD protection against ciphertext manipulation from +out-of-band MitM attackers. + +There are practical oracle attacks against AES256/ECB + AES256/CBC, when the key is reused (as in tunnel layer encryption). + +The oracle attacks against AES256/ECB won't work, because of the double-encryption used, and encryption is over a +single block (the tunnel IV). + +The padding oracle attacks against AES256/CBC won't work, because no padding is used. If tunnel message length ever +changed to non-mod-16 lengths, AES256/CBC would still not be vulnerable due to rejected duplicate IVs. + +Both attacks are also blocked by disallowing multiple oracle calls using the same IV, since duplicate IVs are rejected. -- GitLab