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

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

prop. 152 updates

parent 64a2c667
No related branches found
No related tags found
No related merge requests found
...@@ -6,7 +6,7 @@ ECIES Tunnels ...@@ -6,7 +6,7 @@ ECIES Tunnels
:author: chisana, zzz :author: chisana, zzz
:created: 2019-07-04 :created: 2019-07-04
:thread: http://zzz.i2p/topics/2737 :thread: http://zzz.i2p/topics/2737
:lastupdated: 2020-09-13 :lastupdated: 2020-09-15
:status: Open :status: Open
:target: 0.9.51 :target: 0.9.51
...@@ -15,14 +15,14 @@ ECIES Tunnels ...@@ -15,14 +15,14 @@ ECIES Tunnels
Overview Overview
======== ========
This document proposes for changes to Tunnel Build message encryption This document proposes changes to Tunnel Build message encryption
using crypto primitives introduced by [ECIES-X25519]_. using crypto primitives introduced by [ECIES-X25519]_.
It is a portion of the overall proposal It is a portion of the overall proposal
[Prop156]_ for converting routers from ElGamal to ECIES-X25519 keys. [Prop156]_ for converting routers from ElGamal to ECIES-X25519 keys.
For the purposes of transitioning the network from ElGamal + AES256 to ECIES + ChaCha20, For the purposes of transitioning the network from ElGamal + AES256 to ECIES + ChaCha20,
tunnels with mixed ElGamal and ECIES routers are necessary. tunnels with mixed ElGamal and ECIES routers are necessary.
Specifications for how to handle mixed tunnel hops are provided. Specifications for handling 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.
ElGamal tunnel creators will need create ephemeral X25519 keypairs per-hop, and ElGamal tunnel creators will need create ephemeral X25519 keypairs per-hop, and
...@@ -38,10 +38,16 @@ Cryptographic Primitives ...@@ -38,10 +38,16 @@ Cryptographic Primitives
No new cryptographic primitives are introduced. The primitives required to implement this proposal are: No new cryptographic primitives are introduced. The primitives required to implement this proposal are:
- ChaCha20(msg, nonce, key) - as in [RFC-7539]_ - AES-256-CBC as in [Cryptography]_
- ChaCha20Poly1305(msg, nonce, AD, key) - as in [NTCP2]_ and [ECIES-X25519]_ - STREAM ChaCha20/Poly1305 functions:
- X25519(privateKey, publicKey) - as in [NTCP2]_ and [ECIES-X25519]_ ENCRYPT(k, n, plaintext, ad) and DECRYPT(k, n, ciphertext, ad) - as in [NTCP2]_ [ECIES-X25519]_ and [RFC-7539]_
- HKDF(rootKey, sharedSecret, CONTEXT, keylen) - as in [NTCP2]_ and [ECIES-X25519]_ - X25519 DH functions - as in [NTCP2]_ and [ECIES-X25519]_
- HKDF(salt, ikm, info, n) - as in [NTCP2]_ and [ECIES-X25519]_
Other Noise functions defined elsewhere:
- MixHash(d) - as in [NTCP2]_ and [ECIES-X25519]_
- MixKey(d) - as in [NTCP2]_ and [ECIES-X25519]_
Goals Goals
...@@ -137,6 +143,64 @@ TODO: Does the current design prevent all these attacks? ...@@ -137,6 +143,64 @@ TODO: Does the current design prevent all these attacks?
Design Design
====== ======
Noise Protocol Framework
------------------------
This proposal provides the requirements based on the Noise Protocol Framework
[NOISE]_ (Revision 34, 2018-07-11).
Noise has similar properties to the Station-To-Station protocol
[STS]_, which is the basis for the [SSU]_ protocol. In Noise parlance, Alice
is the initiator, and Bob is the responder.
This proposal is based on the Noise protocol Noise_N_25519_ChaChaPoly_SHA256.
This Noise protocol uses the following primitives:
- One-Way Handshake Pattern: N
Alice does not transmit her static key to Bob (N)
- DH Function: X25519
X25519 DH with a key length of 32 bytes as specified in [RFC-7748]_.
- Cipher Function: ChaChaPoly
AEAD_CHACHA20_POLY1305 as specified in [RFC-7539]_ section 2.8.
12 byte nonce, with the first 4 bytes set to zero.
Identical to that in [NTCP2]_.
- Hash Function: SHA256
Standard 32-byte hash, already used extensively in I2P.
Additions to the Framework
``````````````````````````
None.
Handshake Patterns
------------------
Handshakes use [Noise]_ handshake patterns.
The following letter mapping is used:
- e = one-time ephemeral key
- s = static key
- p = message payload
The build request is identical to the Noise N pattern.
This is also identical to the first (Session Request) message in the XK pattern used in [NTCP2]_.
.. raw:: html
{% highlight lang='dataspec' %}
<- s
...
e es p ->
{% endhighlight %}
Request encryption Request encryption
----------------------- -----------------------
...@@ -144,8 +208,42 @@ Build request records are created by the tunnel creator and asymmetrically encry ...@@ -144,8 +208,42 @@ Build request records are created by the tunnel creator and asymmetrically encry
This asymmetric encryption of request records is currently ElGamal as defined in [Cryptography]_ This asymmetric encryption of request records is currently ElGamal as defined in [Cryptography]_
and contains a SHA-256 checksum. This design is not forward-secret. and contains a SHA-256 checksum. This design is not forward-secret.
The new design will use ECIES-X25519 ephemeral-static DH, with an HKDF, and The new design will use the one-way Noise pattern "N" with ECIES-X25519 ephemeral-static DH, with an HKDF, and
ChaCha20/Poly1305 AEAD for forward secrecy, integrity, and authentication. ChaCha20/Poly1305 AEAD for forward secrecy, integrity, and authentication.
Alice is the tunnel build requestor. Each hop in the tunnel is a Bob.
(Payload Security Properties)
.. raw:: html
{% highlight lang='text' %}
N: Authentication Confidentiality
-> e, es 0 2
Authentication: None (0).
This payload may have been sent by any party, including an active attacker.
Confidentiality: 2.
Encryption to a known recipient, forward secrecy for sender compromise
only, vulnerable to replay. This payload is encrypted based only on DHs
involving the recipient's static key pair. If the recipient's static
private key is compromised, even at a later date, this payload can be
decrypted. This message can also be replayed, since there's no ephemeral
contribution from the recipient.
"e": Alice generates a new ephemeral key pair and stores it in the e
variable, writes the ephemeral public key as cleartext into the
message buffer, and hashes the public key along with the old h to
derive a new h.
"es": A DH is performed between the Alice's ephemeral key pair and the
Bob's static key pair. The result is hashed along with the old ck to
derive a new ck and k, and n is set to zero.
{% endhighlight %}
Reply encryption Reply encryption
...@@ -158,6 +256,17 @@ and contains a SHA-256 checksum. This design is not forward-secret. ...@@ -158,6 +256,17 @@ and contains a SHA-256 checksum. This design is not forward-secret.
The new design will use ChaCha20/Poly1305 AEAD for integrity, and authentication. The new design will use ChaCha20/Poly1305 AEAD for integrity, and authentication.
Justification
-----------------
The ephemeral public key in the request does not need to be obfuscated with AES
or Elligator2. The previous hop is the only one that can see it, and that hop
knows that the next hop is ECIES.
Reply records do not need full asymmetric encryption with another DH.
Specification Specification
========================= =========================
...@@ -223,6 +332,17 @@ Request Record Unencrypted (ECIES) ...@@ -223,6 +332,17 @@ Request Record Unencrypted (ECIES)
``````````````````````````````````````` ```````````````````````````````````````
This is the proposed specification of the tunnel BuildRequestRecord for ECIES-X25519 routers. This is the proposed specification of the tunnel BuildRequestRecord for ECIES-X25519 routers.
Summary of changes:
- Remove unused 32-byte router hash
- Remove reply IV
- Change request time from hours to minutes
- Add expiration field for future variable tunnel time
- Add more space for flags
- Add Properties for additional build options
- AES-256 reply key and IV are not used for the hop's own reply record
- Unencrypted record is longer because there is less encryption overhead
The request record does not contain any explicit tunnel or reply keys. The request record does not contain any explicit tunnel or reply keys.
Those keys are derived from a KDF. See below. Those keys are derived from a KDF. See below.
...@@ -236,15 +356,18 @@ Unencrypted size: 464 bytes ...@@ -236,15 +356,18 @@ Unencrypted size: 464 bytes
{% highlight lang='dataspec' %} {% highlight lang='dataspec' %}
bytes 0-3: tunnel ID to receive messages as, nonzero bytes 0-3: tunnel ID to receive messages as, nonzero
bytes 4-35: local router identity hash bytes 4-7: next tunnel ID, nonzero
bytes 36-39: next tunnel ID, nonzero bytes 8-39: next router identity hash
bytes 40-71: next router identity hash bytes 40-71: AES-256 tunnel layer key
bytes 72-74: unused, set to 0 for compatibility bytes 72-103: AES-256 tunnel IV key
byte 75: flags bytes 104-135: AES-256 reply key
bytes 76-79: request time (in minutes since the epoch, rounded down) bytes 136-151: AES-256 reply IV
bytes 80-83: request expiration (in minutes since creation, rounded down) byte 152: flags
bytes 84-87: next message ID bytes 153-155: more flags, unused, set to 0 for compatibility
bytes 88-x: tunnel build options (Properties) bytes 156-159: request time (in minutes since the epoch, rounded down)
bytes 160-163: request expiration (in seconds since creation)
bytes 164-167: next message ID
bytes 168-x: tunnel build options (Properties)
bytes x-x: other data as implied by flags or options bytes x-x: other data as implied by flags or options
bytes x-463: random padding bytes x-463: random padding
...@@ -317,6 +440,12 @@ bytes 0-31 :: SHA-256 Hash of bytes 32-527 ...@@ -317,6 +440,12 @@ bytes 0-31 :: SHA-256 Hash of bytes 32-527
Reply Record Unencrypted (ECIES) Reply Record Unencrypted (ECIES)
````````````````````````````````````` `````````````````````````````````````
This is the proposed specification of the tunnel BuildRequestRecord for ECIES-X25519 routers.
Summary of changes:
- Add Properties for build reply options
- Unencrypted record is longer because there is less encryption overhead
ECIES replies are encrypted with ChaCha20/Poly1305. ECIES replies are encrypted with ChaCha20/Poly1305.
All fields are big-endian. All fields are big-endian.
...@@ -327,18 +456,19 @@ Unencrypted size: 512 bytes ...@@ -327,18 +456,19 @@ Unencrypted size: 512 bytes
{% highlight lang='dataspec' %} {% highlight lang='dataspec' %}
bytes 0-x: Tunnel Build Options (Properties) bytes 0-x: Tunnel Build Reply Options (Properties)
bytes x-x: other data as implied by options bytes x-x: other data as implied by options
bytes x-510: Random padding bytes x-510: Random padding
bytes 511: Reply byte bytes 511: Reply byte
{% endhighlight %} {% endhighlight %}
The tunnel build options is a Properties structure as defined in [Common]_. The tunnel build reply options is a Properties structure as defined in [Common]_.
This is for future use. No options are currently defined. This is for future use. No options are currently defined.
If the Properties structure is empty, this is two bytes 0x00 0x00. If the Properties structure is empty, this is two bytes 0x00 0x00.
Reply flags for ECIES reply records should use the following values to avoid fingerprinting: The reply byte is one of the following values
as defined in [Tunnel-Creation]_ to avoid fingerprinting:
- 0x00 (accept) - 0x00 (accept)
- 30 (TUNNEL_REJECT_BANDWIDTH) - 30 (TUNNEL_REJECT_BANDWIDTH)
...@@ -460,79 +590,40 @@ These keys are explicitly included in ElGamal BuildRequestRecords. ...@@ -460,79 +590,40 @@ These keys are explicitly included in ElGamal BuildRequestRecords.
For ECIES BuildRequestRecords, these keys are derived from the DH exchange. For ECIES BuildRequestRecords, these keys are derived from the DH exchange.
See [Prop156]_ for details of the router static ECIES keys. See [Prop156]_ for details of the router static ECIES keys.
The ``recordKey`` takes the place of the product of the ElGamal exchange. It is used
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.
.. raw:: html
{% highlight lang='dataspec' %}
// Sender generates an X25519 ephemeral keypair per ECIES hop in the VTBM (sesk, sepk)
sesk = GENERATE_PRIVATE()
sepk = DERIVE_PUBLIC(sesk)
// Each hop's X25519 static keypair (hesk, hepk) from the Router Identity KDF for Initial h
hesk = GENERATE_PRIVATE() ````````````````````````
hepk = DERIVE_PUBLIC(hesk)
// Sender performs an X25519 DH with Hop's static public key. This is standard [NOISE]_ for N with a standard protocol name.
// Each Hop, finds the record w/ their truncated identity hash,
// and extracts the Sender's ephemeral key preceding the encrypted record.
sharedSecret = DH(sesk, hepk) = DH(hesk, sepk)
// Derive a root key from the Sha256 of Sender's ephemeral key and Hop's full identity hash
rootKey = Sha256(sepk || hop_ident_hash)
keydata = HKDF(rootKey, sharedSecret, "RequestReplyGener", 96)
chainKey = keydata[0:31] // used below
recordKey = keydata[32:63] // AEAD key for Request Record encryption
replyKey = keydata[64:95] // Hop reply key
keydata = HKDF(chainKey, sharedSecret, "TunnelLayerRando", 80)
layerKey = keydata[0:31] // Tunnel layer key
layerIVkey = keydata[32:63] // Tunnel IV key
replyIV = keydata[64:79] // Reply record IV
{% endhighlight %}
``replyKey``, ``layerKey`` and ``layerIV`` must still be included inside ElGamal records,
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).
BuildRequestRecord Encryption for ECIES Hops
--------------------------------------------
.. raw:: html .. raw:: html
{% highlight lang='dataspec' %} {% highlight lang='text' %}
This is the "e" message pattern:
// Define protocol_name.
Set protocol_name = "Noise_N_25519_ChaChaPoly_SHA256"
(31 bytes, US-ASCII encoded, no NULL termination).
// See record key KDF for key generation // Define Hash h = 32 bytes
// Repeat for each ECIES hop record in the VTBM // Pad to 32 bytes. Do NOT hash it, because it is not more than 32 bytes.
(ciphertext, mac) = ChaCha20-Poly1305(msg = unencrypted record, nonce = 0, AD = Sha256(hop's recordKey), key = hop's recordKey) h = protocol_name || 0
encryptedRecord = ciphertext || MAC
For subsequent records past the initial hop, pre-emptively decrypt for each preceding hop in the tunnel Define ck = 32 byte chaining key. Copy the h data to ck.
Set chainKey = h
// If the preceding hop is ECIES: // MixHash(null prologue)
nonce = one + number of records + zero-indexed order of record in the VariableTunnelBuildMessage h = SHA256(h);
key = replyKey of preceding hop
symCiphertext = ChaCha20(msg = encryptedRecord, nonce, key)
// If the preceding hop is ElGamal: // up until here, can all be precalculated by all routers.
IV = reply IV of preceding hop
key = reply key of preceding hop
symCiphertext = AES256/CBC-Decrypt(msg = encryptedRecord, IV, key)
{% endhighlight %} {% endhighlight %}
KDFs KDF for Request Record
-------------------------------------------------------------- ````````````````````````
ElGamal tunnel creators generate an ephemeral X25519 keypair for each ElGamal tunnel creators generate an ephemeral X25519 keypair for each
ECIES hop in the tunnel, and use scheme above for encrypting their BuildRequestRecord. ECIES hop in the tunnel, and use scheme above for encrypting their BuildRequestRecord.
...@@ -547,65 +638,101 @@ This means that tunnel hops will only see encrypted records from their same encr ...@@ -547,65 +638,101 @@ 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.
**IMPORTANT**:
Ephemeral keys must be unique per ECIES hop, and per build record. Ephemeral keys must be unique per ECIES hop, and per build record.
Failing to use unique keys opens an attack vector for colluding hops to confirm they are in the same tunnel.
**IMPORTANT**: Failing to use unique keys opens an attack vector for colluding hops to confirm they are in the same tunnel.
.. raw:: html .. raw:: html
{% highlight lang='dataspec' %} {% highlight lang='dataspec' %}
// See reply key KDF for key generation // Each hop's X25519 static keypair (hesk, hepk) from the Router Identity
// Encrypting an ECIES hop request record hesk = GENERATE_PRIVATE()
AD = Sha256(hop static key || hop Identity hash) hepk = DERIVE_PUBLIC(hesk)
(ciphertext, MAC) = ChaCha20-Poly1305(msg = BuildRequestRecord, nonce = 0, AD, key = hop's recordKey)
// Encrypting an ElGamal hop request record // MixHash(hepk)
ciphertext = ElGamal-Encrypt(msg = BuildRequestRecord, key = hop's ElGamal public key) // || below means append
h = SHA256(h || hepk);
{% endhighlight %} // up until here, can all be precalculated by each router
// for all incoming build requests
// Sender generates an X25519 ephemeral keypair per ECIES hop in the VTBM (sesk, sepk)
sesk = GENERATE_PRIVATE()
sepk = DERIVE_PUBLIC(sesk)
Reply Record Encryption (ECIES) End of "e" message pattern.
--------------------------------------
The nonces must be unique per ChaCha20/ChaCha20-Poly1305 invocation using the same key. This is the "es" message pattern:
See [RFC-7539]_ Security Considerations for more information. // Noise es
// Sender performs an X25519 DH with Hop's static public key.
// Each Hop, finds the record w/ their truncated identity hash,
// and extracts the Sender's ephemeral key preceding the encrypted record.
sharedSecret = DH(sesk, hepk) = DH(hesk, sepk)
.. raw:: html // MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly parameters to encrypt/decrypt
keydata = HKDF(chainKey, sharedSecret, "", 64)
// Save for Reply Record KDF
chainKey = keydata[0:31]
{% highlight lang='dataspec' %} // AEAD parameters
k = keydata[32:64]
n = 0
plaintext = 464 byte build request record
ad = h
ciphertext = ENCRYPT(k, n, plaintext, ad)
// See reply key KDF for key generation End of "es" message pattern.
msg = reply byte || build options || random padding
(ciphertext, MAC) = ChaCha20-Poly1305(msg, nonce = 0, AD = Sha256(replyKey), key = replyKey)
// Other request/reply record encryption // MixHash(ciphertext)
// Use a unique nonce per-record // Save for Reply Record KDF
nonce = one + number of records + zero-indexed order of record in the VariableTunnelBuildMessage h = SHA256(h || ciphertext)
symCiphertext = ChaCha20(msg = multiple encrypted record, nonce, key = replyKey)
{% endhighlight %} {% endhighlight %}
While mixed tunnels are used, reply records are the same size, though the format is different. ``replyKey``, ``layerKey`` and ``layerIV`` must still be included inside ElGamal records,
and can be generated randomly.
After full transition to ECIES, random padding can be a range of included padding.
When ranged padding is used, random padding will be formatted using the Padding block structure from [ECIES-X25519]_ and [NTCP2]_. Request Record Encryption (ElGamal)
----------------------------------------
For symmetric encryption by other hops, it's necessary to know full record length (w/ padding) without asymmetric decryption. As defined in [Tunnel-Creation]_.
There are no changes to encryption for ElGamal hops.
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.
Reply Record Encryption (ECIES)
--------------------------------------
The reply record is ChaCha20/Poly1305 encrypted.
.. raw:: html
{% highlight lang='dataspec' %}
// AEAD parameters
k = chainkey from build request
n = 0
plaintext = 512 byte build reply record
ad = h from build request
ciphertext = ENCRYPT(k, n, plaintext, ad)
{% endhighlight %}
Reply Record Encryption (ElGamal) Reply Record Encryption (ElGamal)
---------------------------------------- ----------------------------------------
As defined in [Tunnel-Creation]_. As defined in [Tunnel-Creation]_.
There are no changes for how ElGamal hops encrypt their replies. There are no changes to encryption for ElGamal hops.
Security Analysis Security Analysis
...@@ -693,6 +820,9 @@ References ...@@ -693,6 +820,9 @@ References
.. [I2NP] .. [I2NP]
{{ spec_url('i2np') }} {{ spec_url('i2np') }}
.. [NOISE]
https://noiseprotocol.org/noise.html
.. [NTCP2] .. [NTCP2]
{{ spec_url('ntcp2') }} {{ spec_url('ntcp2') }}
...@@ -716,3 +846,9 @@ References ...@@ -716,3 +846,9 @@ References
.. [RFC-7539] .. [RFC-7539]
https://tools.ietf.org/html/rfc7539 https://tools.ietf.org/html/rfc7539
.. [RFC-7748]
https://tools.ietf.org/html/rfc7748
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