forked from I2P_Developers/i2p.www
Updates for proposals 144, 147, 152
New proposal 153 split out from 152
This commit is contained in:
@@ -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.
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -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.
|
||||
|
335
i2p2www/spec/proposals/153-chacha20-layer-encryption.rst
Normal file
335
i2p2www/spec/proposals/153-chacha20-layer-encryption.rst
Normal file
@@ -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.
|
Reference in New Issue
Block a user