I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 8289febc authored by zzz's avatar zzz
Browse files

Updates for proposals 144, 147, 152

New proposal 153 split out from 152
parent 609c2c62
No related branches found
No related tags found
No related merge requests found
...@@ -5,7 +5,7 @@ ECIES-X25519-AEAD-Ratchet ...@@ -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-07-26 :lastupdated: 2019-08-04
:status: Open :status: Open
.. contents:: .. contents::
...@@ -109,6 +109,8 @@ Goals ...@@ -109,6 +109,8 @@ Goals
be a separate proposal be a separate proposal
- Don't break anything that relies on 32-byte binary destination hashes, e.g. bittorrent - Don't break anything that relies on 32-byte binary destination hashes, e.g. bittorrent
- Maintain 0-RTT message delivery using ephemeral-static DH - 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 - Upgrade to ephemeral-ephemeral DH after 1 RTT
- Maintain handling of out-of-order messages - Maintain handling of out-of-order messages
- Maintain 256-bit security - Maintain 256-bit security
...@@ -153,7 +155,9 @@ Non-Goals / Out-of-scope ...@@ -153,7 +155,9 @@ Non-Goals / Out-of-scope
- LS2 format (see proposal 123) - LS2 format (see proposal 123)
- New DHT rotation algorithm or shared random generation - New DHT rotation algorithm or shared random generation
- New encryption for tunnel building. - 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. - Methods of encryption, transmission, and reception of I2NP DLM / DSM / DSRM messages.
Not changing. Not changing.
- No LS1-to-LS2 or ElGamal/AES-to-this-proposal communication is supported. - No LS1-to-LS2 or ElGamal/AES-to-this-proposal communication is supported.
...@@ -168,7 +172,7 @@ Non-Goals / Out-of-scope ...@@ -168,7 +172,7 @@ Non-Goals / Out-of-scope
Justification 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. essentially without modifications to the protocol.
There are now cryptographic primitives that are faster. There are now cryptographic primitives that are faster.
We need to enhance the security of the protocol. We need to enhance the security of the protocol.
......
...@@ -5,7 +5,7 @@ Transport Network ID Check ...@@ -5,7 +5,7 @@ Transport Network ID Check
:author: zzz :author: zzz
:created: 2019-02-28 :created: 2019-02-28
:thread: http://zzz.i2p/topics/2687 :thread: http://zzz.i2p/topics/2687
:lastupdated: 2019-07-16 :lastupdated: 2019-08-04
:status: Open :status: Open
.. contents:: .. contents::
...@@ -125,7 +125,7 @@ HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey) ...@@ -125,7 +125,7 @@ HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey)
'+' means append and '^' means exclusive-or. '+' means append and '^' means exclusive-or.
payloadLength is a 2 byte unsigned integer payloadLength is a 2 byte unsigned integer
protocolVersion is two bytes 0x0000 protocolVersion is one byte 0x00
{% endhighlight %} {% endhighlight %}
...@@ -134,11 +134,11 @@ New: ...@@ -134,11 +134,11 @@ New:
.. raw:: html .. raw:: html
{% highlight lang='dataspec' %} {% 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. '+' means append, '^' means exclusive-or, '<<' means left shift.
payloadLength is a 2 byte unsigned integer payloadLength is a 2 byte unsigned integer
protocolVersion is two bytes 0x0000 protocolVersion is one byte 0x00
netid is a 1 byte unsigned integer netid is a 1 byte unsigned integer
......
...@@ -6,7 +6,7 @@ ECIES Tunnels ...@@ -6,7 +6,7 @@ ECIES Tunnels
:author: chisana :author: chisana
:created: 2019-07-04 :created: 2019-07-04
:thread: http://zzz.i2p/topics/2737 :thread: http://zzz.i2p/topics/2737
:lastupdated: 2019-07-26 :lastupdated: 2019-08-04
:status: Open :status: Open
.. contents:: .. contents::
...@@ -27,12 +27,7 @@ No changes will be made to the format, processing, or encryption of ElGamal hops ...@@ -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 ElGamal tunnel creators will need to create ephemeral X25519 keypairs per-hop, and
follow this spec for creating tunnels containing ECIES hops. follow this spec for creating tunnels containing ECIES hops.
The proposal is split into two sections: This proposal specifies changes needed for ECIES-X25519 Tunnel Building.
- 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 Cryptographic Primitives
------------------------ ------------------------
...@@ -117,24 +112,6 @@ are supported, TBD. ...@@ -117,24 +112,6 @@ are supported, TBD.
Ranged random padding will be formatted using the Padding block structure from [ECIES-X25519]_ and [NTCP2]_. 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 Tunnel Reply Records for ECIES
------------------------------ ------------------------------
...@@ -349,11 +326,9 @@ This means that tunnel hops will only see encrypted records from their same encr ...@@ -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 For ElGamal and ECIES tunnel creators, they will generate unique ephemeral X25519 keypairs
per-hop for encrypting to ECIES hops. per-hop for encrypting to ECIES hops.
**WARNING**: if the same ephemeral keypair is used for more than one hop, it can only be Ephemeral keys must be unique per ECIES hop, and per build record.
used for at most **two** hops, and the hops must be **consecutive**.
**WARNING**: Using the same ephemeral keys for non-consecutive hops, or more than two hops, **IMPORTANT**: Failing to use unique keys opens an attack vector for colluding hops to confirm they are in the same tunnel.
allows colluding hops to know they're in the same tunnel, **VERY BAD**!!!
.. raw:: html .. raw:: html
...@@ -372,7 +347,7 @@ allows colluding hops to know they're in the same tunnel, **VERY BAD**!!! ...@@ -372,7 +347,7 @@ allows colluding hops to know they're in the same tunnel, **VERY BAD**!!!
Reply Record Encryption for ECIES Hops 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. See [RFC-7539-S4]_ Security Considerations for more information.
...@@ -426,246 +401,6 @@ ECIES, used with new ephemeral keys per-BuildRequestRecord or VariableTunnelBuil ...@@ -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. 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 Tunnel Message Overhead for ECIES
================================= =================================
...@@ -713,8 +448,8 @@ Wrapped I2NP message overhead: ...@@ -713,8 +448,8 @@ Wrapped I2NP message overhead:
Tunnel message overhead: Tunnel message overhead:
Tunnel layer keys, IV keys, and reply keys no longer need to be transmitted in ECIES BuildRequest Records. Tunnel layer keys, IV/nonce 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. 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, 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. and fragmented in Tunnel Data messages like any other message.
......
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.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment