proposal 152 updates
This commit is contained in:
@ -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-18
|
:lastupdated: 2019-07-19
|
||||||
:status: Open
|
:status: Open
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
@ -24,7 +24,8 @@ Specifications for how to handle mixed tunnel hops are provided.
|
|||||||
|
|
||||||
No changes will be made to the format, processing, or encryption of ElGamal hops.
|
No changes will be made to the format, processing, or encryption of ElGamal hops.
|
||||||
|
|
||||||
All ElGamal routers are treated as though running without changes from this document.
|
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:
|
The proposal is split into two sections:
|
||||||
|
|
||||||
@ -90,9 +91,12 @@ bytes 0-3: tunnel ID to receive messages as, nonzero
|
|||||||
byte 72: flags
|
byte 72: flags
|
||||||
bytes 73-76: request time (in hours since the epoch, rounded down)
|
bytes 73-76: request time (in hours since the epoch, rounded down)
|
||||||
bytes 77-80: next message ID
|
bytes 77-80: next message ID
|
||||||
|
bytes 81-464: tunnel build options / random padding
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The tunnel build options block will be defined by [Tunnel-Build-Options]_.
|
||||||
|
|
||||||
Request Record Spec Encrypted (ECIES)
|
Request Record Spec Encrypted (ECIES)
|
||||||
`````````````````````````````````````
|
`````````````````````````````````````
|
||||||
|
|
||||||
@ -102,8 +106,7 @@ Request Record Spec Encrypted (ECIES)
|
|||||||
|
|
||||||
bytes 0-15: hop's truncated identity hash
|
bytes 0-15: hop's truncated identity hash
|
||||||
bytes 16-47: sender's ephemeral public key
|
bytes 16-47: sender's ephemeral public key
|
||||||
bytes 48-128: ChaChaPoly AEAD encrypted build request record
|
bytes 48-511: ChaChaPoly AEAD encrypted BuildRequestRecord
|
||||||
bytes 129-511: Random padding
|
|
||||||
bytes 512-527: Poly1305 MAC
|
bytes 512-527: Poly1305 MAC
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
@ -123,11 +126,8 @@ Bit order: 76543210 (bit 7 is MSB)
|
|||||||
bit 7: if set, allow messages from anyone
|
bit 7: if set, allow messages from anyone
|
||||||
bit 6: if set, allow messages to anyone, and send the reply to the
|
bit 6: if set, allow messages to anyone, and send the reply to the
|
||||||
specified next hop in a Tunnel Build Reply Message
|
specified next hop in a Tunnel Build Reply Message
|
||||||
bit 5: if set, ChaCha20 reply encryption selected (ECIES build record),
|
bit 5: if set, only ECIES hops in the tunnel, use Blowfish+ChaCha20 layer encryption
|
||||||
also indicates next hop is ECIES
|
bits 4-0: Undefined, must set to 0 for compatibility with future options
|
||||||
AES256/CBC (ElGamal) otherwise
|
|
||||||
bit 4: if set, only ECIES hops in the tunnel, use Blowfish+ChaCha20 layer encryption
|
|
||||||
bits 3-0: Undefined, must set to 0 for compatibility with future options
|
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@ -142,10 +142,12 @@ Reply Record Spec Unencrypted (ECIES)
|
|||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
|
|
||||||
bytes 0: Reply byte
|
bytes 0: Reply byte
|
||||||
bytes 1-511: Random padding
|
bytes 1-511: Tunnel Build Options / Random padding
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
For options formatting refer to the [Tunnel-Build-Options]_ spec.
|
||||||
|
|
||||||
Reply flags for ECIES reply records should use the following values to avoid fingerprinting:
|
Reply flags for ECIES reply records should use the following values to avoid fingerprinting:
|
||||||
|
|
||||||
- 0x00 (accept)
|
- 0x00 (accept)
|
||||||
@ -189,17 +191,11 @@ Symmetric cryptography preprocessing will run in the same way:
|
|||||||
- once by the hop
|
- once by the hop
|
||||||
- once on final reply processing
|
- once on final reply processing
|
||||||
|
|
||||||
When mixed routers are hops in the same tunnel, and the current hop is ECIES,
|
When mixed tunnels are used, tunnel creators will need to base the symmetric encryption
|
||||||
it will check if reply encryption flag is set (indicating ChaCha20).
|
of BuildRequestRecord on the current and previous hop's encryption type.
|
||||||
|
|
||||||
If the current hop is an ECIES hop, and ChaCha20 reply encryption is selected,
|
Each hop will use it's own encryption type for encrypting BuildReplyRecords, and the other
|
||||||
the reply key is used to ChaCha20 "decrypt" its reply and other records.
|
records in the VariableTunnelBuildMessage (VTBM).
|
||||||
|
|
||||||
If the current hop is an ElGamal hop, the reply encryption bit is ignored,
|
|
||||||
and the reply key is used to AES256/CBC "decrypt" its reply and other records.
|
|
||||||
|
|
||||||
This means later hops in the tunnel are preprocessed using a mix of ChaCha20
|
|
||||||
and AES256/CBC, using the reply key of preceding hops.
|
|
||||||
|
|
||||||
On the reply path, the endpoint (sender) will need to undo the [Multiple-Encryption]_, using each hop's reply key.
|
On the reply path, the endpoint (sender) will need to undo the [Multiple-Encryption]_, using each hop's reply key.
|
||||||
|
|
||||||
@ -207,15 +203,17 @@ As a clarifying example, let's look at an outbound tunnel w/ ECIES surrounded by
|
|||||||
|
|
||||||
- Sender (OBGW) -> ElGamal (H1) -> ECIES (H2) -> ElGamal (H3)
|
- Sender (OBGW) -> ElGamal (H1) -> ECIES (H2) -> ElGamal (H3)
|
||||||
|
|
||||||
All records are in their encrypted state (using ElGamal or ECIES).
|
All BuildRequestRecords are in their encrypted state (using ElGamal or ECIES).
|
||||||
|
|
||||||
AES256/CBC cipher, when used, is still used for each record, without chaining across multiple records.
|
AES256/CBC cipher, when used, is still used for each record, without chaining across multiple records.
|
||||||
|
|
||||||
|
Likewise, ChaCha20 will be used to encrypt each record, not streaming across the entire VTBM.
|
||||||
|
|
||||||
The request records are preprocessed by the Sender (OBGW):
|
The request records are preprocessed by the Sender (OBGW):
|
||||||
|
|
||||||
- H3's record is "encrypted" using:
|
- H3's record is "encrypted" using:
|
||||||
|
|
||||||
- H2's reply key (AES256/CBC)
|
- H2's reply key (ChaCha20)
|
||||||
- H1's reply key (AES256/CBC)
|
- H1's reply key (AES256/CBC)
|
||||||
|
|
||||||
- H2's record is "encrypted" using:
|
- H2's record is "encrypted" using:
|
||||||
@ -226,8 +224,6 @@ The request records are preprocessed by the Sender (OBGW):
|
|||||||
|
|
||||||
Only H2 checks the reply encryption flag, and sees its followed by AES256/CBC.
|
Only H2 checks the reply encryption flag, and sees its followed by AES256/CBC.
|
||||||
|
|
||||||
H3 checks the flags, sees it is an OBEP (bit 6 set), and ignores the reply encryption bit.
|
|
||||||
|
|
||||||
After being processed by each hop, the records are in a "decrypted" state:
|
After being processed by each hop, the records are in a "decrypted" state:
|
||||||
|
|
||||||
- H3's record is "decrypted" using:
|
- H3's record is "decrypted" using:
|
||||||
@ -237,15 +233,15 @@ After being processed by each hop, the records are in a "decrypted" state:
|
|||||||
- H2's record is "decrypted" using:
|
- H2's record is "decrypted" using:
|
||||||
|
|
||||||
- H3's reply key (AES256/CBC)
|
- H3's reply key (AES256/CBC)
|
||||||
- H2's reply key (AES256/CBC)
|
- H2's reply key (ChaCha20-Poly1305)
|
||||||
|
|
||||||
- H1's record is "decrypted" using:
|
- H1's record is "decrypted" using:
|
||||||
|
|
||||||
- H3's reply key (AES256/CBC)
|
- H3's reply key (AES256/CBC)
|
||||||
- H2's reply key (AES256/CBC)
|
- H2's reply key (ChaCha20)
|
||||||
- H1's reply key (AES256/CBC)
|
- H1's reply key (AES256/CBC)
|
||||||
|
|
||||||
When there are no inbound tunnels at startup, the Sender (IBEP) postprocesses the reply:
|
The tunnel creator, a.k.a. Inbound Endpoint (IBEP), postprocesses the reply:
|
||||||
|
|
||||||
- H3's record is "encrypted" using:
|
- H3's record is "encrypted" using:
|
||||||
|
|
||||||
@ -254,76 +250,19 @@ When there are no inbound tunnels at startup, the Sender (IBEP) postprocesses th
|
|||||||
- H2's record is "encrypted" using:
|
- H2's record is "encrypted" using:
|
||||||
|
|
||||||
- H3's reply key (AES256/CBC)
|
- H3's reply key (AES256/CBC)
|
||||||
- H2's reply key (AES256/CBC)
|
- H2's reply key (ChaCha20-Poly1305)
|
||||||
|
|
||||||
- H1's record is "encrypted" using:
|
- H1's record is "encrypted" using:
|
||||||
|
|
||||||
- H3's reply key (AES256/CBC)
|
- H3's reply key (AES256/CBC)
|
||||||
- H2's reply key (AES256/CBC)
|
|
||||||
- H1's reply key (AES256/CBC)
|
|
||||||
|
|
||||||
If H3 (OBEP) is an ECIES hop, it checks the reply encryption flag for
|
|
||||||
ChaCha20 (bit 5 set) or AES256/CBC (bit 5 unset).
|
|
||||||
|
|
||||||
H2 would also see that the reply encryption flag is set, and "decrypt" its reply
|
|
||||||
and other records using ChaCha20.
|
|
||||||
|
|
||||||
So our example changes to the following hops:
|
|
||||||
|
|
||||||
- Sender (OBGW) -> ElGamal (H1) -> ECIES (H2) -> ECIES (H3)
|
|
||||||
|
|
||||||
The request records are preprocessed by the Sender (OBGW):
|
|
||||||
|
|
||||||
- H3's record is "encrypted" using:
|
|
||||||
|
|
||||||
- H2's reply key (ChaCha20)
|
|
||||||
- H1's reply key (AES256/CBC)
|
|
||||||
|
|
||||||
- H2's record is "encrypted" using:
|
|
||||||
|
|
||||||
- H1's reply key (AES256/CBC)
|
|
||||||
|
|
||||||
- H1's record goes out without symmetric encryption
|
|
||||||
|
|
||||||
After being processed by each hop, the records are in a "decrypted" state:
|
|
||||||
|
|
||||||
- H3's record is "decrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
|
|
||||||
- H2's record is "decrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
- H2's reply key (ChaCha20)
|
|
||||||
|
|
||||||
- H1's record is "decrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
- H2's reply key (ChaCha20)
|
|
||||||
- H1's reply key (AES256/CBC)
|
|
||||||
|
|
||||||
When there are no inbound tunnels at startup, the Sender (IBEP) postprocesses the reply:
|
|
||||||
|
|
||||||
- H3's record is "encrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
|
|
||||||
- H2's record is "encrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
- H2's reply key (ChaCha20)
|
|
||||||
|
|
||||||
- H1's record is "encrypted" using:
|
|
||||||
|
|
||||||
- H3's reply key (ChaCha20)
|
|
||||||
- H2's reply key (ChaCha20)
|
- H2's reply key (ChaCha20)
|
||||||
- H1's reply key (AES256/CBC)
|
- H1's reply key (AES256/CBC)
|
||||||
|
|
||||||
Request Record Key, Reply Key, Tunnel Layer Key, and IV Key KDF (ECIES)
|
Request Record Key, Reply Key, Tunnel Layer Key, and IV Key KDF (ECIES)
|
||||||
---------------------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
The ``recordKey`` takes the place of the product of the ElGamal exchange. It is used
|
The ``recordKey`` takes the place of the product of the ElGamal exchange. It is used
|
||||||
to AEAD encrypt request and reply records for ECIES hops.
|
to AEAD encrypt request records for ECIES hops.
|
||||||
|
|
||||||
Below is a description of how to derive the keys previously transmitted in request records.
|
Below is a description of how to derive the keys previously transmitted in request records.
|
||||||
|
|
||||||
@ -331,7 +270,7 @@ Below is a description of how to derive the keys previously transmitted in reque
|
|||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
|
|
||||||
// Sender generates an X25519 ephemeral keypair per VTBM (sesk, sepk)
|
// Sender generates an X25519 ephemeral keypair per ECIES hop in the VTBM (sesk, sepk)
|
||||||
sesk = GENERATE_PRIVATE()
|
sesk = GENERATE_PRIVATE()
|
||||||
sepk = DERIVE_PUBLIC(sesk)
|
sepk = DERIVE_PUBLIC(sesk)
|
||||||
|
|
||||||
@ -360,42 +299,58 @@ Below is a description of how to derive the keys previously transmitted in reque
|
|||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
``replyKey``, ``layerKey`` and ``IVKey`` must still be included inside ElGamal records,
|
``replyKey``, ``layerKey`` and ``IVKey`` must still be included inside ElGamal records,
|
||||||
and can be generated randomly. For ElGamal, the ``recordKey`` is just the result of ElGamal multiplication.
|
and can be generated randomly. For ElGamal, the ``recordKey`` is not needed, since the
|
||||||
|
tunnel creator can directly encrypt to an ElGamal hop's public key.
|
||||||
|
|
||||||
Keys are omitted from ECIES records (since they can be derived at the hop).
|
Keys are omitted from ECIES records (since they can be derived at the hop).
|
||||||
|
|
||||||
Request Record Preprocessing for ECIES Hops
|
BuildRequestRecord Encryption for ECIES Hops
|
||||||
-------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
|
|
||||||
// See record key KDF for key generation
|
// See record key KDF for key generation
|
||||||
(ciphertext, mac) = ChaCha20-Poly1305(msg = unencrypted record, nonce = 0, AD = Sha256(recordKey), key = recordKey)
|
// Repeat for each ECIES hop record in the VTBM
|
||||||
|
(ciphertext, mac) = ChaCha20-Poly1305(msg = unencrypted record, nonce = 0, AD = Sha256(hop's recordKey), key = hop's recordKey)
|
||||||
|
encryptedRecord = ciphertext \|\| MAC
|
||||||
|
|
||||||
// For subsequent records past the initial hop
|
For subsequent records past the initial hop, pre-emptively decrypt for each preceding hop in the tunnel
|
||||||
// nonce = one \+ zero-indexed order of record in the TunnelBuildMessage
|
|
||||||
symCiphertext = ChaCha20(msg = ciphertext \|\| MAC, nonce, key = replyKey of preceding hop)
|
// If the preceding hop is ECIES:
|
||||||
|
nonce = one \+ zero-indexed order of record in the VariableTunnelBuildMessage
|
||||||
|
key = replyKey of preceding hop
|
||||||
|
symCiphertext = ChaCha20(msg = encryptedRecord, nonce, key)
|
||||||
|
|
||||||
|
// If the preceding hop is ElGamal:
|
||||||
|
IV = reply IV of preceding hop
|
||||||
|
key = reply key of preceding hop
|
||||||
|
symCiphertext = AES256/CBC-Decrypt(msg = encryptedRecord, IV, key)
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
Request Record Encryption from ElGamal Tunnel Creators
|
Request Record Encryption from ElGamal + ECIES Tunnel Creators
|
||||||
------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
No changes are made for how ElGamal routers preprocess and encrypt request records.
|
ElGamal tunnel creators will need to generate an ephemeral X25519 keypair for each
|
||||||
|
ECIES hop in the tunnel, and use scheme above for encrypting their BuildRequestRecord.
|
||||||
|
ElGamal tunnel creators will use the scheme prior to this spec for encrypting to ElGamal hops.
|
||||||
|
|
||||||
This means ECIES hops will behave like ElGamal hops in ElGamal created tunnels.
|
ECIES tunnel creators will need to encrypt to the ElGamal hop's public key using the
|
||||||
|
scheme prior to this spec. ECIES tunnel creators will use the above scheme for encrypting
|
||||||
|
to ECIES hops.
|
||||||
|
|
||||||
For ECIES hops to detect ElGamal tunnel creators, trial-decryption is needed.
|
This means that tunnel hops will only see encrypted records from their same encryption type.
|
||||||
|
|
||||||
It will be necessary to first try decrypting the request record as though it came from an ECIES router.
|
For ElGamal and ECIES tunnel creators, they will generate unique ephemeral X25519 keypairs
|
||||||
|
per-hop for encrypting to ECIES hops.
|
||||||
|
|
||||||
If trial-decryption fails, attempt decryption as though from an ElGamal router.
|
**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**.
|
||||||
|
|
||||||
If the record includes expected fields (keys + IV, flags, etc, and valid Sha256 of preceding data), ElGamal decryption was succesful.
|
**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**!!!
|
||||||
If ElGamal decryption fails, drop the message without reply, or forwarding to next hop.
|
|
||||||
|
|
||||||
Reply Record Encryption for ECIES Hops
|
Reply Record Encryption for ECIES Hops
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
@ -409,27 +364,14 @@ See [RFC-7539-S4]_ Security Considerations for more information.
|
|||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
|
|
||||||
// See reply key KDF for key generation
|
// See reply key KDF for key generation
|
||||||
(ciphertext, MAC) = ChaCha20-Poly1305(msg = reply byte, nonce = 0, AD = Sha256(replyKey), key = replyKey)
|
msg = reply byte \|\| build options \|\| random padding
|
||||||
|
(ciphertext, MAC) = ChaCha20-Poly1305(msg, nonce = 0, AD = Sha256(replyKey), key = replyKey)
|
||||||
If ChaCha20 reply encryption is set in the request record (flags bit 5 set):
|
|
||||||
|
|
||||||
// Use a unique nonce per-record
|
|
||||||
nonce = one \+ zero-indexed order of record in the VariableTunnelBuildMessage
|
|
||||||
symCiphertext = ChaCha20(msg = ciphertext \|\| MAC \|\| random padding, nonce, key = replyKey)
|
|
||||||
|
|
||||||
// Other request/reply record encryption
|
// Other request/reply record encryption
|
||||||
// Use a unique nonce per-record
|
// Use a unique nonce per-record
|
||||||
nonce = one \+ number of records \+ zero-indexed order of record in the VariableTunnelBuildMessage
|
nonce = one \+ number of records \+ zero-indexed order of record in the VariableTunnelBuildMessage
|
||||||
symCiphertext = ChaCha20(msg = multiple encrypted record, nonce, key = replyKey)
|
symCiphertext = ChaCha20(msg = multiple encrypted record, nonce, key = replyKey)
|
||||||
|
|
||||||
If AES256/CBC reply encryption is set in the request record (flag bit 5 unset):
|
|
||||||
|
|
||||||
// Other request/reply record encryption
|
|
||||||
msg = multiple encrypted record
|
|
||||||
key = replyKey
|
|
||||||
IV = Sha256(replyKey \|\| hop static public key)
|
|
||||||
symCiphertext = AES256-CBC-Encrypt(msg, key, IV)
|
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
While mixed tunnels are used, reply records are the same size, though the format is different.
|
While mixed tunnels are used, reply records are the same size, though the format is different.
|
||||||
@ -439,7 +381,9 @@ After full transition to ECIES, random padding can be a range of included paddin
|
|||||||
When ranged padding is used, random padding will be formatted using the Padding block structure from [ECIES-X25519]_ and [NTCP2]_.
|
When ranged padding is used, random padding will be formatted using the Padding block structure from [ECIES-X25519]_ and [NTCP2]_.
|
||||||
|
|
||||||
For symmetric encryption by other hops, it's necessary to know full record length (w/ padding) without asymmetric decryption.
|
For symmetric encryption by other hops, it's necessary to know full record length (w/ padding) without asymmetric decryption.
|
||||||
|
|
||||||
When/if records become variable-length, it may become necessary to include an unencrypted Data block header before each record, TBD.
|
When/if records become variable-length, it may become necessary to include an unencrypted Data block header before each record, TBD.
|
||||||
|
|
||||||
BuildReplyRecord may or may not need to match BuildRequestRecord length if both are preceded by Data block header, TBD.
|
BuildReplyRecord may or may not need to match BuildRequestRecord length if both are preceded by Data block header, TBD.
|
||||||
|
|
||||||
Reply Record Encryption for ElGamal Hops
|
Reply Record Encryption for ElGamal Hops
|
||||||
@ -516,7 +460,7 @@ Inbound tunnels:
|
|||||||
- Use 8-byte ``tunnelNonce`` given the lifetime of tunnels
|
- Use 8-byte ``tunnelNonce`` given the lifetime of tunnels
|
||||||
- Destroy tunnel before 2^(64/2 - 1) messages: 2^31 = 2,147,483,648
|
- Destroy tunnel before 2^(64/2 - 1) messages: 2^31 = 2,147,483,648
|
||||||
|
|
||||||
- Nonce limit in place to avoid Sweet32 attack on Blowfish
|
- Nonce limit in place to avoid [Sweet32]_ attack on [Blowfish]_
|
||||||
- Nonce limit unlikely to ever be reached, given this would be ~3,579,139 msgs/second for 10 minute tunnels
|
- Nonce limit unlikely to ever be reached, given this would be ~3,579,139 msgs/second for 10 minute tunnels
|
||||||
- Nonce cannot be truncated. For shorter nonce, a different method must be used with smaller state space.
|
- Nonce cannot be truncated. For shorter nonce, a different method must be used with smaller state space.
|
||||||
|
|
||||||
@ -602,7 +546,7 @@ To validate received ``tunnelNonce``, the participant checks against its Bloom f
|
|||||||
|
|
||||||
After validation, the participant:
|
After validation, the participant:
|
||||||
|
|
||||||
- Blowfish encrypts the ``tunnelNonce`` with its ``IVKey``
|
- [Blowfish]_ encrypts the ``tunnelNonce`` with its ``IVKey``
|
||||||
- Uses the encrypted ``tunnelNonce`` & its ``layerKey`` to ChaCha20 encrypt the tunnel message(s)
|
- Uses the encrypted ``tunnelNonce`` & its ``layerKey`` to ChaCha20 encrypt the tunnel message(s)
|
||||||
- Sends the tuple {``tunnelId``, encrypted ``tunnelNonce``, ciphertext} to the next hop.
|
- Sends the tuple {``tunnelId``, encrypted ``tunnelNonce``, ciphertext} to the next hop.
|
||||||
|
|
||||||
@ -634,7 +578,7 @@ For ECIES-only tunnels, the following scheme will be used:
|
|||||||
|
|
||||||
- Validate the received ``tunnelNonce`` against the Bloom filter
|
- Validate the received ``tunnelNonce`` against the Bloom filter
|
||||||
- ChaCha20 decrypt the encrypted data using the received ``tunnelNonce`` & the hop's ``layerKey``
|
- ChaCha20 decrypt the encrypted data using the received ``tunnelNonce`` & the hop's ``layerKey``
|
||||||
- Blowfish decrypt the ``tunnelNonce`` using the hop's ``IVKey`` to get the preceding ``tunnelNonce``
|
- [Blowfish]_ decrypt the ``tunnelNonce`` using the hop's ``IVKey`` to get the preceding ``tunnelNonce``
|
||||||
- ChaCha20 decrypt the encrypted data using the decrypted ``tunnelNonce`` & the preceding hop's ``layerKey``
|
- 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
|
- Repeat for each hop in the tunnel, back to the IBGW
|
||||||
|
|
||||||
@ -663,25 +607,25 @@ Security Analysis for Blowfish+ChaCha20 Tunnel Layer Encryption
|
|||||||
Switching from AES256/ECB to ChaCha20 has a number of advantages, and new security considerations.
|
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,
|
The biggest security considerations to account for, are that ChaCha20 nonces must be unique per-message,
|
||||||
for the life of the key being used, and Blowfish is susceptible to Sweet32 birthday attacks.
|
for the life of the key being used, and [Blowfish]_ is susceptible to [Sweet32]_ birthday attacks.
|
||||||
|
|
||||||
Failing to use unique nonces with the same key on different messages breaks ChaCha20.
|
Failing to use unique nonces with the same key on different messages breaks ChaCha20.
|
||||||
|
|
||||||
Nonce uniqueness is main reason for using an Blowfish, see [RFC-7539-S4]_.
|
Nonce uniqueness is main reason for using an [Blowfish]_, see [RFC-7539-S4]_.
|
||||||
|
|
||||||
Simple counters cannot be used, since they require syncing for proper decryption.
|
Simple counters cannot be used, since they require syncing for proper decryption.
|
||||||
Syncing the counter can't be guaranteed at the IBEP, without further changes to tunnel protocols.
|
Syncing the counter can't be guaranteed at the IBEP, without further changes to tunnel protocols.
|
||||||
|
|
||||||
Blowfish is only used for nonce encryption to guarantee unique nonces, and prevent non-consecutive
|
[Blowfish]_ is only used for nonce encryption to guarantee unique nonces, and prevent non-consecutive
|
||||||
hops in the same tunnel from colluding to know they are in the same tunnel.
|
hops in the same tunnel from colluding to know they are in the same tunnel.
|
||||||
|
|
||||||
The tunnel lifetime of ten minutes and nonce limit of 2^31 messages guarantees that Sweet32 attacks
|
The tunnel lifetime of ten minutes and nonce limit of 2^31 messages guarantees that [Sweet32]_ attacks
|
||||||
are ineffective against Blowfish. Exceeding the limit would require over ~3,579,139 messages/second in each tunnel.
|
are ineffective against Blowfish. Exceeding the limit would require over ~3,579,139 messages/second in each tunnel.
|
||||||
|
|
||||||
Even if 2^31 messages proves to not be a strict enough limit, we can safely reduce the limit by another power of two,
|
Even if 2^31 messages proves to not be a strict enough limit, we can safely reduce the limit by another power of two,
|
||||||
without ever realistically reaching the limit.
|
without ever realistically reaching the limit.
|
||||||
|
|
||||||
Even if a Sweet32 attack were successful, an attacker would only gain access to the ``tunnelNonce``
|
Even if a [Sweet32]_ attack were successful, an attacker would only gain access to the ``tunnelNonce``
|
||||||
for the colliding message, which doesn't break the ChaCha20 encryption. Non-consecutive hops
|
for the colliding message, which doesn't break the ChaCha20 encryption. Non-consecutive hops
|
||||||
would only be able to confirm they are participants in the same tunnel.
|
would only be able to confirm they are participants in the same tunnel.
|
||||||
|
|
||||||
@ -698,6 +642,34 @@ double-encryption.
|
|||||||
The chosen-plaintext producing a recovered IV cannot be used to perform
|
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.
|
a padding-oracle attack against AES256/CBC layer encryption, since duplicate IVs are rejected.
|
||||||
|
|
||||||
|
Justification for Blowfish
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
[Blowfish]_ is needed to symmetrically encrypt ChaCha20 nonces used in tunnel layer encryption. It was chosen for
|
||||||
|
its 64-bit block size, and ability to symmetrically encrypt without using a nonce.
|
||||||
|
|
||||||
|
A 64-bit block size is needed to generate unique nonces for ChaCha20. ChaCha20 has a maximum nonce size of 96-bits,
|
||||||
|
using the IETF variant. Nonces of smaller sizes can be used, and are padded with zeroes. However, larger nonces, like
|
||||||
|
the 128-bit AES256/CBC IV cannot safely be truncated, as 96-bit segments may be identical for two otherwise
|
||||||
|
unique IVs.
|
||||||
|
|
||||||
|
HKDF and other hashing functions cannot be used to safely truncate the received IV, since it must be possible
|
||||||
|
for Inbound Endpoints to recover the IV of preceding hops in the tunnel.
|
||||||
|
|
||||||
|
Of the 64-bit ciphers, [Blowfish]_ is the most secure, with the widest support in well-audited cryptography libraries.
|
||||||
|
|
||||||
|
Other alternatives like DES and 3DES, are more cumbersome, and weaker in comparison. Despite its comparative strength,
|
||||||
|
[Blowfish]_ is still vulnerable to [Sweet32]_ attacks. This means that in ~2^32 blocks, there will be a block collision,
|
||||||
|
allowing for recovery of the nonce from that block. Given the lifetime of tunnels, the restriction on unique received
|
||||||
|
nonces, and the limit of 2^31 messages, [Blowfish]_ would not vulnerable to [Sweet32]_ in the I2P ECIES Tunnels context.
|
||||||
|
|
||||||
|
Realistically, much fewer than 2^29 nonces will ever be seen by any tunnel, since this would be over 894,784 msgs/sec.
|
||||||
|
|
||||||
|
For comparison, Google receives ~76,000 searches per second. Even assuming 10 messages per search, a tunnel would have
|
||||||
|
to be over 100,000 msgs/sec busier than Google. Vanishingly unlikely.
|
||||||
|
|
||||||
|
Statistics from: https://www.internetlivestats.com/one-second/
|
||||||
|
|
||||||
Tunnel Message Overhead for ECIES
|
Tunnel Message Overhead for ECIES
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
@ -760,6 +732,9 @@ References
|
|||||||
.. [ECIES-X25519]
|
.. [ECIES-X25519]
|
||||||
{{ proposal_url('144') }}
|
{{ proposal_url('144') }}
|
||||||
|
|
||||||
|
.. [Tunnel-Build-Options]
|
||||||
|
{{ proposal_url('143') }}
|
||||||
|
|
||||||
.. [NTCP2]
|
.. [NTCP2]
|
||||||
https://geti2p.net/spec/ntcp2
|
https://geti2p.net/spec/ntcp2
|
||||||
|
|
||||||
@ -775,5 +750,8 @@ References
|
|||||||
.. [RFC-7539-S4]
|
.. [RFC-7539-S4]
|
||||||
https://tools.ietf.org/html/rfc7539#section-4
|
https://tools.ietf.org/html/rfc7539#section-4
|
||||||
|
|
||||||
.. [SplitMix64]
|
.. [Blowfish]
|
||||||
http://xoshiro.di.unimi.it/splitmix64.c
|
https://www.schneier.com/academic/blowfish/
|
||||||
|
|
||||||
|
.. [Sweet32]
|
||||||
|
https://sweet32.info/
|
||||||
|
Reference in New Issue
Block a user