ZmnSCPxj [ARCHIVE] on Nostr: 📅 Original date posted:2023-06-29 🗒️ Summary of this message: Noise ...
📅 Original date posted:2023-06-29
🗒️ Summary of this message: Noise encryption can be compromised by analyzing the sizes of IP packets, allowing eavesdroppers to figure out payment routing. A solution is to ensure all packet sizes are the same.
📝 Original message:
Good morning all,
Recently, it has been pointed out that even with Noise encryption, a third-party eavesdropper can make a good guess of what messages are being sent between LN nodes by checking the sizes of IP packets transmitted between them.
This potentially allows an eavesdropper to figure out how payments are being routed across the network.
A solution of this is to make sure that all packet sizes are the same.
We can note that the BOLT8 spec builds on top of TCP.
Thus, the "view" of the receiver is that it is receiving a stream of bytes, even though the reality is that the underlying IP is packetized.
Most implementations have an object or equivalent software construction which handles encryption of messages for BOLT8 tunnels.
We can make this object a "buffer" in addition to a tunnel encrypter.
The interface to this object would then have "send BOLT8 message" and "flush" entry points.
The object would have an internal buffer of a fixed size, which it fills with ciphertext from the "send BOLT8 message" interface.
If the buffer fills, the object then uses the POSIX `send` API to send it as a packet.
This makes packets sent fixed size.
The "flush" entry point looks at how filled the buffer is, and adds a `pong` message to pad it out until the entire buffer is full (there is an edge case where the buffer is just filled enough that the mandatory 2-byte message length and the 2-byte message ID will already overflow the buffer, which it should handle correctly).
(Since it inserts `pong` messages, it cannot be a simple buffer; it has to modify the encryptor state with the `pong` message inserted in the stream of BOLT8 messages)
This allows, for example, a sequence of `update_add_htlc`s followed by a `commitment_signed` to be potentially put in a single fixed-size packet, or sequence of fixed-size packets.
Then the implementation has to call the "flush" entrypoint so that the counterparty can receive the entire tail end of the `commitment_signed`.
For robustness against internal bugs / defensive programming, the object could have an individual randomized timer where it periodically does "flush" on itself, in case the implementation does not properly "flush" when it starts waiting for a response from the counterparty.
This papers over such bugs, and makes those bugs performance bugs instead of interop bugs.
I would suggest that the buffer size be matched to the packet size of `update_add_htlc`, as that is expected to fit in a single IP packet for best latency.
Regards,
ZmnSCPxj
🗒️ Summary of this message: Noise encryption can be compromised by analyzing the sizes of IP packets, allowing eavesdroppers to figure out payment routing. A solution is to ensure all packet sizes are the same.
📝 Original message:
Good morning all,
Recently, it has been pointed out that even with Noise encryption, a third-party eavesdropper can make a good guess of what messages are being sent between LN nodes by checking the sizes of IP packets transmitted between them.
This potentially allows an eavesdropper to figure out how payments are being routed across the network.
A solution of this is to make sure that all packet sizes are the same.
We can note that the BOLT8 spec builds on top of TCP.
Thus, the "view" of the receiver is that it is receiving a stream of bytes, even though the reality is that the underlying IP is packetized.
Most implementations have an object or equivalent software construction which handles encryption of messages for BOLT8 tunnels.
We can make this object a "buffer" in addition to a tunnel encrypter.
The interface to this object would then have "send BOLT8 message" and "flush" entry points.
The object would have an internal buffer of a fixed size, which it fills with ciphertext from the "send BOLT8 message" interface.
If the buffer fills, the object then uses the POSIX `send` API to send it as a packet.
This makes packets sent fixed size.
The "flush" entry point looks at how filled the buffer is, and adds a `pong` message to pad it out until the entire buffer is full (there is an edge case where the buffer is just filled enough that the mandatory 2-byte message length and the 2-byte message ID will already overflow the buffer, which it should handle correctly).
(Since it inserts `pong` messages, it cannot be a simple buffer; it has to modify the encryptor state with the `pong` message inserted in the stream of BOLT8 messages)
This allows, for example, a sequence of `update_add_htlc`s followed by a `commitment_signed` to be potentially put in a single fixed-size packet, or sequence of fixed-size packets.
Then the implementation has to call the "flush" entrypoint so that the counterparty can receive the entire tail end of the `commitment_signed`.
For robustness against internal bugs / defensive programming, the object could have an individual randomized timer where it periodically does "flush" on itself, in case the implementation does not properly "flush" when it starts waiting for a response from the counterparty.
This papers over such bugs, and makes those bugs performance bugs instead of interop bugs.
I would suggest that the buffer size be matched to the packet size of `update_add_htlc`, as that is expected to fit in a single IP packet for best latency.
Regards,
ZmnSCPxj