<p>In the new P2P transport protocol proposed in BIP324, after the handshake (which among other things establishes encryption keys), packets have the following structure:</p>
<ul>
<li>A 3-byte <strong>length descriptor</strong> (encrypted with FSChaCha20)</li>
<li>An arbitrary-length <strong>ciphertext</strong> which is the encryption of a plaintext (encrypted with FSChaCha20Poly1305, which expands the data by 16 bytes in the process by adding a <a href="https://datatracker.ietf.org/doc/html/rfc8439#section-2.5" rel="nofollow noreferrer">Poly1305</a> authentication tag); the plaintext consists of:
<ul>
<li>A 1-byte <strong>header</strong> (which is used for signalling decoy data)</li>
<li>A variable-length <strong>contents</strong> (whose length is described by the length descriptor). The contents consists of:
<ul>
<li>A 1-byte or 13-byte <strong>message type</strong> (e.g. version, verack, tx, inv, ...).</li>
<li>A variable-length <strong>payload</strong> (the actual data sent in the message).</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>So if you want everything flattened out, you get:</p>
<ul>
<li>3-byte encrypted length descriptor</li>
<li>1-byte encrypted header</li>
<li>1-byte or 13-byte encrypted message type</li>
<li>variable length encrypted payload</li>
<li>16-byte Poly1305 authentication tag</li>
</ul>
<p>However, only 2 separate encryption algorithm invocations are used per packet:</p>
<ul>
<li>The 3-byte length is encrypted using <a href="https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#rekeying-wrappers-fschacha20poly1305-and-fschacha20" rel="nofollow noreferrer">FSChaCha20</a>, which is a variant of the <a href="https://datatracker.ietf.org/doc/html/rfc8439#section-2.4" rel="nofollow noreferrer">ChaCha20 stream cipher</a> that rekeys every 224 messages.</li>
<li>The header, message type, and payload are all encrypted together at once using <a href="https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#rekeying-wrappers-fschacha20poly1305-and-fschacha20" rel="nofollow noreferrer">FSChaCha20Poly1305</a>, which is a variant of the <a href="https://datatracker.ietf.org/doc/html/rfc8439#section-2.8" rel="nofollow noreferrer">ChaCha20Poly1305 AEAD</a> which rekeys every 224 messages.</li>
</ul>

CC BY-SA 4.0
2023-08-20T15:05:25.830Z
So, I have a new question: Why the command field isn't directly encrypted with the length through ChaCha20 ?
Loopite
CC BY-SA 4.0
2023-08-20T15:28:12.687Z
@Loopite Because we want as much as possible to be covered by the Poly1305 authentication tag (as that allows modifications in flight to be detected). Only the length isn't, because we need to know the length of a packet before we can decrypt/authenticate the packet. It would have been possible in theory to have a separate authentication tag for just the length, but that'd come at fairly high cost (an additional 16 bytes per packet), and not actually achieve anything (see footnote 23 in the BIP).
Pieter Wuille
CC BY-SA 4.0
2024-10-13T08:08:07.983Z
Yeah but why didn't you encrypt all the message (with length) with AEAD-ChaCha20Poly1305 then ? You'd still know the length by the way by decrypting it with ChaCha20 and then decrypt ALL the message (with the length again) with ChaCha20. You can also check the tag now by the way... This avoids encrypting 2 sections and now encrypts just one. This also protects the length by the tag.
Loopite
CC BY-SA 4.0
2024-10-13T12:49:36.447Z
@Loopite I personally believe that may work, but it is much harder to argue for its security, as it means using the same key/cipher for the length data (which has very weak privacy guarantees anyway, but no mac) as the actual payload (which has strong privacy guarantees, but also a mac). This is the reason why the OpenSSH chacha20-poly1305 uses two separate ciphers for length and data, and BIP324 inherited that design.
Pieter Wuille
CC BY-SA 4.0
2023-08-20T13:37:17.377Z
2023-08-20T14:06:51.890Z
2023-08-20T14:06:51.890Z
Pieter Wuille
<p>I recently saw the <a href="https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki" rel="nofollow noreferrer">BIP 324</a> proposal. It shows us there can be some privacy enhancement by using ECDH secrets and encryption algorithms such as ChaCha20 and AEAD-ChaCha20-Poly1305. The proposal includes:</p>
<ul>
<li>The length decriptor size is reduced to 3 Bytes.</li>
<li>The command could be expressed as an ID (1 Byte) OR as characters (13 Bytes, by including the 0x00 byte selector).</li>
</ul>
<ol>
<li>However, I don't fully understand <strong>the order</strong> in data will be structured. Can it be explained ?</li>
<li>What algorithm will be applied to which data structure ? Because I can suppose the ChaCha20 is used in order to encrypt the payload size and AEAD-ChaCha20-Poly1305 to encrypt payload.</li>
</ol>

CC BY-SA 4.0
2023-08-20T13:17:47.210Z
What do you mean with "the order"?
Pieter Wuille
CC BY-SA 4.0
2023-08-20T13:23:44.043Z
I mean the structure of sent data. For example: CommandId (1 Byte) + Size (4 Bytes)...
Loopite
<network><encryption><raw-data><p2p><bip324-p2p-encryption>
BIP324 encrypted packet structure
Loopite
# BIP324 encrypted packet structure

(Asked by: username_0 on 2023-08-20)

I recently saw the [BIP 324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki) proposal. It shows us there can be some privacy enhancement by using ECDH secrets and encryption algorithms such as ChaCha20 and AEAD-ChaCha20-Poly1305. The proposal includes:

* The length decriptor size is reduced to 3 Bytes.
* The command could be expressed as an ID (1 Byte) OR as characters (13 Bytes, by including the 0x00 byte selector).

1. However, I don't fully understand **the order** in data will be structured. Can it be explained ?
2. What algorithm will be applied to which data structure ? Because I can suppose the ChaCha20 is used in order to encrypt the payload size and AEAD-ChaCha20-Poly1305 to encrypt payload.

**Tags:** network, encryption, raw-data, p2p, bip324-p2p-encryption

> **Comments:**
> **username_1**: What do you mean with "the order"?  
> **username_0**: I mean the structure of sent data. For example: CommandId (1 Byte) + Size (4 Bytes)...  

---

## 1 answers

### Answer by username_1 on 2023-08-20. Score: 5 | Accepted answer

In the new P2P transport protocol proposed in BIP324, after the handshake (which among other things establishes encryption keys), packets have the following structure:

* A 3-byte **length descriptor** (encrypted with FSChaCha20)
* An arbitrary-length **ciphertext** which is the encryption of a plaintext (encrypted with FSChaCha20Poly1305, which expands the data by 16 bytes in the process by adding a [Poly1305](https://datatracker.ietf.org/doc/html/rfc8439#section-2.5) authentication tag); the plaintext consists of:
  + A 1-byte **header** (which is used for signalling decoy data)
  + A variable-length **contents** (whose length is described by the length descriptor). The contents consists of:
    - A 1-byte or 13-byte **message type** (e.g. version, verack, tx, inv, ...).
    - A variable-length **payload** (the actual data sent in the message).

So if you want everything flattened out, you get:

* 3-byte encrypted length descriptor
* 1-byte encrypted header
* 1-byte or 13-byte encrypted message type
* variable length encrypted payload
* 16-byte Poly1305 authentication tag

However, only 2 separate encryption algorithm invocations are used per packet:

* The 3-byte length is encrypted using [FSChaCha20](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#rekeying-wrappers-fschacha20poly1305-and-fschacha20), which is a variant of the [ChaCha20 stream cipher](https://datatracker.ietf.org/doc/html/rfc8439#section-2.4) that rekeys every 224 messages.
* The header, message type, and payload are all encrypted together at once using [FSChaCha20Poly1305](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#rekeying-wrappers-fschacha20poly1305-and-fschacha20), which is a variant of the [ChaCha20Poly1305 AEAD](https://datatracker.ietf.org/doc/html/rfc8439#section-2.8) which rekeys every 224 messages.

> **Comments:**
> **username_0**: So, I have a new question: Why the command field isn't directly encrypted with the length through ChaCha20 ?  
> **username_1**: @username_0 Because we want as much as possible to be covered by the Poly1305 authentication tag (as that allows modifications in flight to be detected). Only the length isn't, because we need to know the length of a packet before we can decrypt/authenticate the packet. It would have been possible in theory to have a separate authentication tag for just the length, but that'd come at fairly high cost (an additional 16 bytes per packet), and not actually achieve anything (see footnote 23 in the BIP).  
> **username_0**: Yeah but why didn't you encrypt all the message (with length) with AEAD-ChaCha20Poly1305 then ? You'd still know the length by the way by decrypting it with ChaCha20 and then decrypt ALL the message (with the length again) with ChaCha20. You can also check the tag now by the way... This avoids encrypting 2 sections and now encrypts just one. This also protects the length by the tag.  
> **username_1**: @username_0 I personally believe that may work, but it is much harder to argue for its security, as it means using the same key/cipher for the length data (which has very weak privacy guarantees anyway, but no mac) as the actual payload (which has strong privacy guarantees, but also a mac). This is the reason why the OpenSSH chacha20-poly1305 uses two separate ciphers for length and data, and BIP324 inherited that design.  

---

