<p>TCP and other stream based protocols do not have a 1-to-1 correlation of application level messages and IP packets. If you call <code>send()</code> 3 times, it might result in sending a single IP packet over the wire (eg, due to Nagle's algorithm which is enabled by default), it might get sent individually as 3 packets, as you would expect from a packet oriented protocol like UDP, or the messages might end up being split into several packets each because the IP layer has an MTU. </p>

<p>It is generally out of your control at the application layer. You therefore, cannot rely on reading the length from the IP header to tell you about the length of messages. You need to encode the lengths into the data stream and reconstruct the data coming in from the stream into the individual messages as understood by your protocol.</p>

<p>The reason to encode the length separately in the BOLT#8 specification is that each message must be decrypted as a single operation, because each decryption must increase the counter used in the ChaChaPoly cipher. You need to know the exact length of the message before calling the decrypt function on the encrypted payload.</p>

<p>In the BOLT#8 protocol, you send the exact lengths of the encrypted message+MAC, with no padding added. The receiver should first explicitly call <code>recv(buffer, 18, ...)</code>, decrypt the result to get <code>msg_len</code>, then call <code>recv(buffer, msg_len, ...)</code> to retrieve the encrypted message, which can then be decrypted in full. <code>recv</code> may also return fewer bytes than requested, so in both cases, the result of <code>recv</code> must be checked and if less than the expected length is read, <code>recv</code> should be called again with the remaining expected length.</p>

CC BY-SA 4.0
2019-03-12T21:22:06.417Z
2019-03-12T21:22:06.417Z
Mark H
<p>From BOLT 08 we can see that every message is sent in the following way:</p>

<pre><code>2 byte: length
16 byte: MAC 
[length] byte: Encrypted message
16 byte: MAC 
</code></pre>

<p>In reality these messages will be send over TCP/IP on the internet. The ip header specifies the length of the data package that is being sent. If we extract the length and subtract 34 byte for the header plus the two MACs we would know how long the message is.</p>

<p>Is the idea to always send a 2^16 byte ip package and fill the rest with junk data? If yes why isn't that specified in the BOLTs? If no: why encrypting the length anyway?  </p>

<p>I assume that an attacker would be able track all tcp/ip packages on the lightning port and would at least be able to deduct which messages are being sent even though the messages themselves are safe.</p>

<p>Assume the message length can indeed be deduced can't that be used together with the MAC to reconstruct the session key for that message? </p>

<security><lightning-network><privacy><data-security>
Why is the length of the transport messages on the lightning network encrypted?
Rene Pickhardt
# Why is the length of the transport messages on the lightning network encrypted?

(Asked by: username_0 on 2019-03-12)

From BOLT 08 we can see that every message is sent in the following way:

```
2 byte: length
16 byte: MAC 
[length] byte: Encrypted message
16 byte: MAC 

```

In reality these messages will be send over TCP/IP on the internet. The ip header specifies the length of the data package that is being sent. If we extract the length and subtract 34 byte for the header plus the two MACs we would know how long the message is.

Is the idea to always send a 2^16 byte ip package and fill the rest with junk data? If yes why isn't that specified in the BOLTs? If no: why encrypting the length anyway?

I assume that an attacker would be able track all tcp/ip packages on the lightning port and would at least be able to deduct which messages are being sent even though the messages themselves are safe.

Assume the message length can indeed be deduced can't that be used together with the MAC to reconstruct the session key for that message?

**Tags:** security, lightning-network, privacy, data-security


---

## 1 answers

### Answer by username_1 on 2019-03-12. Score: 10 | Accepted answer

TCP and other stream based protocols do not have a 1-to-1 correlation of application level messages and IP packets. If you call `send()` 3 times, it might result in sending a single IP packet over the wire (eg, due to Nagle's algorithm which is enabled by default), it might get sent individually as 3 packets, as you would expect from a packet oriented protocol like UDP, or the messages might end up being split into several packets each because the IP layer has an MTU.

It is generally out of your control at the application layer. You therefore, cannot rely on reading the length from the IP header to tell you about the length of messages. You need to encode the lengths into the data stream and reconstruct the data coming in from the stream into the individual messages as understood by your protocol.

The reason to encode the length separately in the BOLT#8 specification is that each message must be decrypted as a single operation, because each decryption must increase the counter used in the ChaChaPoly cipher. You need to know the exact length of the message before calling the decrypt function on the encrypted payload.

In the BOLT#8 protocol, you send the exact lengths of the encrypted message+MAC, with no padding added. The receiver should first explicitly call `recv(buffer, 18, ...)`, decrypt the result to get `msg_len`, then call `recv(buffer, msg_len, ...)` to retrieve the encrypted message, which can then be decrypted in full. `recv` may also return fewer bytes than requested, so in both cases, the result of `recv` must be checked and if less than the expected length is read, `recv` should be called again with the remaining expected length.


---

