commit 1beab45cfeeda132b387d97ad6b1625d603c978a
parent 0e4f2d265bafc654a11593b0f8a2eb44793289cd
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Mon, 28 Jul 2025 19:39:43 +0200
notes on chacha
Diffstat:
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/draft-schanzen-cake.xml b/draft-schanzen-cake.xml
@@ -129,18 +129,18 @@
</t>
<dl>
<dt>inititator:</dt><dd>See client in <xref target="RFC9147"/> Section 2.</dd>
- <dt>receiver:</dt><dd>See server in <xref target="RFC9147"/> Section 2.</dd>
+ <dt>responder:</dt><dd>See server in <xref target="RFC9147"/> Section 2.</dd>
<dt>epoch:</dt><dd>See <xref target="RFC9147"/> Section 2.</dd>
<dt>IATS:</dt>
<dd>Initiator Application Traffic Secret Key</dd>
- <dt>RATS:</dt> <dd>Receiver Application Traffic Secret Key</dd>
+ <dt>RATS:</dt> <dd>Responder Application Traffic Secret Key</dd>
<dt>ES:</dt> <dd>Early Secret Key</dd>
<dt>ETS:</dt> <dd>Early Traffic Secret Key</dd>
<dt>HS:</dt> <dd>Handshake Secret Key</dd>
<dt>MS:</dt> <dd>Main Secret Key</dd>
<dt>ES:</dt> <dd>Early Secret Key</dd>
<dt>IHTS:</dt> <dd>Initiator Handshake Secret Key</dd>
- <dt>RHTS:</dt> <dd>Receiver Handshake Secret Key</dd>
+ <dt>RHTS:</dt> <dd>Responder Handshake Secret Key</dd>
<dt>H(D):</dt> <dd>A 512-bit hash over D. The hash function is TBD (Blake2b or SHA-512).</dd>
<dt>T(M):</dt> <dd>means the transcript as a concatenation of received/sent messages starting from and including the InitiatorHello pk_e until and including M. Note that the transcript refers to everything that is seen on the wire, including potentially encrypted messages or fields and metadata.</dd>
<dt>'{}K'</dt> <dd>indicates encryption with a handshake traffic key K and <xref target="RFC8439"/>, the ChaCha20-Poly1305 Authenticated Encryption with Associated Data (AEAD) construction.</dd>
@@ -164,7 +164,7 @@
We assume that the peers have semi-static (as opposed to ephemeral) key pairs. Let (pk<sub>A</sub>,sk<sub>A</sub>) be the key pair of peer PID<sub>A</sub> and (pk<sub>B</sub>,sk<sub>B</sub>) the key pair of peer PID<sub>B</sub>.
</t>
<t>
- For any secure handshake protocol, we have to dermine an initiator and a receiver in the protocol. We use <tt>GNUNET_CRYPTO_hash_cmp</tt> to determine which peer is the receiver R and which peer the initiator I:
+ For any secure handshake protocol, we have to dermine an initiator and a responder in the protocol. We use <tt>GNUNET_CRYPTO_hash_cmp</tt> to determine which peer is the responder R and which peer the initiator I:
</t>
<sourcecode>
<![CDATA[
@@ -186,7 +186,7 @@ else
</t>
<t>
Below is a swimlane of the protocol messages.
- On the left and right side of the swimlanes the secrets known to the Initiator and Receiver are
+ On the left and right side of the swimlanes the secrets known to the Initiator and Responder are
shown respectively.
If a private key of a key pair is known it is implied that the public key is also known.
Messages in brackets are optional.
@@ -194,7 +194,7 @@ else
</t>
<figure anchor="figure_swimlane" title="Overview over the Handshake Protocol Flow.">
<artwork name="" type="" align="left" alt=""><![CDATA[
- Initiator Receiver
+ Initiator Responder
sk_I | | sk_R
sk_e | |
r_I | |
@@ -219,7 +219,7 @@ ss_R | |
| | ss_R
| | ss_I
| | ss_e
- | ReceiverHello: |
+ | ResponderHello: |
| c_e |
| r_R |
| {svcinfo_R,c_I}RHTS |
@@ -247,21 +247,21 @@ ss_e | |
</figure>
<t>
Notice how we do not need any acknowledgement messages until after finished<sub>I</sub> (after 1.5 RTT).
- The InitiatorHello message is a single flight that is implicitly ack'ed with ReceiverHello.
- ReceiverHello is a single flight that is implicitly ack'ed with finished<sub>I</sub>.
+ The InitiatorHello message is a single flight that is implicitly ack'ed with ResponderHello.
+ ResponderHello is a single flight that is implicitly ack'ed with finished<sub>I</sub>.
finished<sub>I</sub> requires an explicit ack; at this time R and I have already established a secure channel
and R can use an EncryptedMessage to send the ack.
- The reason why this works is because CAKE groups the messages in row 3 of Table 1 in <xref target="RFC9147" section="5.7"/> into a single message (ReceiverHello).
+ The reason why this works is because CAKE groups the messages in row 3 of Table 1 in <xref target="RFC9147" section="5.7"/> into a single message (ResponderHello).
Hence the only message that is sent without any expected response (and consequently requiring an explicit
ACK) is finished<sub>I</sub> (and KeyUpdate).
N<sub>I</sub> is a nonce generated by the initiator.
- N<sub>R</sub> is a nonce generated by the receiver.
+ N<sub>R</sub> is a nonce generated by the responder.
</t>
<t>
The Initiator creates the InitiatorHello message which includes the encrypted tuple (pk<sub>I</sub>,svcinfo_I).
The fields are encrypted using a key derived from the ETS according to <xref target="figure_swimlane"/>
and <xref target="figure_key_schedule"/>.
- The so-called Receiver KEM Challenge c<sub>R</sub> and the nonce r<sub>I</sub> are computed as:
+ The so-called Responder KEM Challenge c<sub>R</sub> and the nonce r<sub>I</sub> are computed as:
</t>
<ol>
<li>(ss<sub>R</sub>,c<sub>R</sub>) <- Encaps(pk<sub>R</sub>). Reciver KEM Challenge.</li>
@@ -273,7 +273,7 @@ ss_e | |
<ol>
<li>Verify that the message type is CORE_INITIATOR_HELLO. See Message Header.</li>
<li>Verify that H(pk_R) matches R's pk_R.</li>
- <li>(ss<sub>R</sub>,c<sub>R</sub>) <- Decaps(sk<sub>R</sub>, c<sub>R</sub>). Response to Receiver KEM Challenge.</li>
+ <li>(ss<sub>R</sub>,c<sub>R</sub>) <- Decaps(sk<sub>R</sub>, c<sub>R</sub>). Response to Responder KEM Challenge.</li>
<li>(ss<sub>e</sub>,c<sub>e</sub>) <- Encaps(pk<sub>e</sub>). Ephemeral shared secret.</li>
<li>Generate ETS from <xref target="key_schedule"/> and decrypt pk<sub>I</sub>. pk<sub>I</sub> and svcinfo_I may be processed now.</li>
<li>(ss<sub>I</sub>,c<sub>I</sub>) <- Encaps(pk<sub>I</sub>). Initiator KEM Challenge.</li>
@@ -282,10 +282,10 @@ ss_e | |
<t>
The ETS, the Handshake and Master Secrets are generated according to <xref target="figure_key_schedule"/>.
Note that IATS cannot be derived (yet) at this point.
- R may now generate its ReceiverHello message:
+ R may now generate its ResponderHello message:
</t>
<ol>
- <li>r<sub>R</sub> <- RandomUInt64(). Receiver nonce.</li>
+ <li>r<sub>R</sub> <- RandomUInt64(). Responder nonce.</li>
<li>Encrypt svcinfo_R and c<sub>I</sub> (Initiator KEM Challenge) using RHTS.</li>
<li>Create finished<sub>R</sub> as per <xref target="cake_hs_proto"/>.</li>
<li>Encrypt finished<sub>R</sub> with RHTS.</li>
@@ -295,7 +295,7 @@ ss_e | |
I processes the message received by R:
</t>
<ol>
- <li>Verify that the message type is CORE_RECEIVER_HELLO. See Message Header</li>
+ <li>Verify that the message type is CORE_Responder_HELLO. See Message Header</li>
<li>ss<sub>e</sub> <- Decaps(sk<sub>e</sub>,c<sub>e</sub>). Ephemeral shared secret.</li>
<li>Generate IHTS and RHTS from <xref target="key_schedule"/> and decrypt svcinfo_R, c<sub>I</sub> and finished<sub>R</sub>.</li>
<li>ss<sub>I</sub> <- Decaps(sk<sub>I</sub>,c<sub>I</sub>). Response to KEM Challenge</li>
@@ -313,12 +313,12 @@ ss_e | |
However, we only have a single message that contains such a payload: InitiatorHello.
Epoch 2 is reserved for payload encrypted with a key derived from *HTS.
But we only have a single message that contains a payload encrypted with a key
- derived from RHTS: ReceiverHello.
+ derived from RHTS: ResponderHello.
We also only have a single message that contains a payload encrypted with a key
derived from IHTS: finished<sub>I</sub>.
Consequently, we do not need any signalling of Epochs until we encrypt data using
*ATS secrets.
- The optional application data that may already be sent by the receiver after its first
+ The optional application data that may already be sent by the responder after its first
handshake message or by the initiator after its second handshake message, are
already wrapped inside an EncryptedMessage and have both Epoch and sequence numbers set.
</t>
@@ -369,7 +369,7 @@ HKDF-Extract(ss_I,.) = Master Secret (MS)
</t>
<t>
Notice that from the very beginning ss<sub>R</sub> is required for the key schedule.
- This means that R must be able to solve the Receiver KEM Challenge c<sub>R</sub>.
+ This means that R must be able to solve the Responder KEM Challenge c<sub>R</sub>.
Similarly, the master secret (MS) requires knowledge of ss<sub>I</sub>.
This means that I must be able to solve the Initiator KEM Challenge c<sub>I</sub>.
The KEM Challenges provide the underlying public key authentication mechanism.
@@ -385,7 +385,7 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
]]></artwork>
</figure>
<t>
- After a successful initial handshake, both initiator and receiver may
+ After a successful initial handshake, both initiator and responder may
update the application traffic secrets ([A,I]ATS) and generate new keys.
Let [I,R]ATS<sub>0</sub> be the initial secrets with index 0.
The next secret is derived as:
@@ -467,7 +467,7 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
</t>
<ul>
<li>InitiatorHello</li>
- <li>ReceiverHello</li>
+ <li>ResponderHello</li>
<li>HandshakeFinished</li>
<li>EncryptedMessage</li>
</ul>
@@ -520,12 +520,12 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
<!-- FIXME: Discuss IV. We may be able to use data from HKDF-Expand for that -->
</t>
</section>
- <section anchor="receiver_hello" numbered="true" toc="default">
- <name>ReceiverHello Message</name>
+ <section anchor="responder_hello" numbered="true" toc="default">
+ <name>ResponderHello Message</name>
<t>
- The ReceiverHello:
+ The ResponderHello:
</t>
- <figure anchor="figure_recvhello" title="The Wire Format of the ReceiverHello.">
+ <figure anchor="figure_recvhello" title="The Wire Format of the ResponderHello.">
<artwork name="" type="" align="left" alt=""><![CDATA[
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
@@ -542,7 +542,7 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
<t>
The protected fields after the nonce are encrypted using a key derived from AHTS.
The finished<sub>R</sub> is encrypted individually.
- This is because the transcript of the ReceiverHello to generate the
+ This is because the transcript of the ResponderHello to generate the
finished<sub>R</sub> must end before it.
</t>
</section>
@@ -604,7 +604,7 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
the peer <bcp14>MUST</bcp14> check if this is a KeyUpdate.
A KeyUpdate message indicates that the sender has switched its traffic secrets
according to the key schedule in <xref target="key_schedule"/>.
- If any bit in the UpdateRequested field is set, this means that the receiver
+ If any bit in the UpdateRequested field is set, this means that the responder
of the KeyUpdate <bcp14>MUST</bcp14> send its own KeyUpdate message.
Any bytes following the UpdateRequested field are updated services info
svcinfo (<xref target="svcinfo"/>).
@@ -641,12 +641,14 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
</t>
<t>
We must discuss ChaCha20 vs XChaCha20.
- For XChaCha20 (currently implemented) we can use fresh nonces when the key is re-used.
+ For XChaCha20 we can use fresh nonces when the key is re-used.
With ChaCha20, we should increment the nonce.
We could probably increment both. Incrementing may allow us to derive a starting nonce from
the key schedule.
We can get away with ChaCha20 (TLS, IETF) and its 32-bit internal counter because our
messages are <= 2<sup>16</sup>-1 bytes and the counter cannot overflow.
+ But, XChaCha20 is the generally recommended cipher for any use case by the libsodium author as well.
+ The only downside seems to be that XChaCha20 is practically not specified anywhere (although it can be trivially defined in this document based on HChaCha) and only really implemented in libsodium.
</t>
<t>
We must define which hash function is to be used for H. It should probably have 512 bit output.
@@ -657,9 +659,9 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12)
We may want to use our HPKE Elligator KEM <xref target="LSD0011"/>.
</t>
<t>
- The Initiator/Receiver selection logic may require a timed fallback: The designates Initiator may never initiate (NAT, already has sufficient connections, learns about receiver later than receiver about initiator etc.).
+ The Initiator/Responder selection logic may require a timed fallback: The designates Initiator may never initiate (NAT, already has sufficient connections, learns about responder later than responder about initiator etc.).
- This may result in edge cases where the Initiator initiates a handshake and the Receiver also initiates a handshake at the same time switching roles.
+ This may result in edge cases where the Initiator initiates a handshake and the Responder also initiates a handshake at the same time switching roles.
In such cases we may simply do both key exchanges. If both succeed, we drop the key exchange that was not initiated by the designated initiator on both peers. Otherwise we use the successful key exchange and the roles are swapped.
</t>