This specification contains all details of Sphinx packet data structures and algorithms for constructing/unwrapping Sphinx packets.
Please note that this specification is exactly the same as what defined in the Sphinx paper below and what implemented by Nym: https://github.com/nymtech/sphinx.
Therefore, this document covers only an overview of Sphinx packet construction with easy-to-understand diagrams. For more details, please see the executable specification written in Python.
A diagram below describes how a Sphinx header is constructed.
A Sphinx header contains encapsulated routing information.
Given a mix route with three mix nodes $m_1, m_2, m_3$, and a mix destination $m_D$, a routing information of each $m_2, m_3, m_D$ is encapsulated in a Sphinx packet as below.
RoutingInfo
or PaddedFinalRoutingInfo
) is encrypted by XOR operation with a pseudo-random bytes generated by AES128-CTR using a private key of $m_l$ and a constant nonce.In the Header Construction diagram, two zero fillers (encrypted; colored) are appended to the EncryptedPaddedFinalRoutingInfo
to make it have the same size as EncryptedRoutingInfo
(300 bytes).
Also, when constructing a RoutingInfo
of $m_3$ (that will be used by $m_2$), the last filler is truncated. And, the remaining filler in the RoutingInfo
is encrypted again with a stream key of $m_2$ to build a new EncryptedRoutingInfo
(300 bytes).
That is, the filler is for preventing adversaries from distinguishing packets emitted from different mix layers (i.e. packet-layer undistinguishability).
The diagram below shows how fillers can be constructed and encrypted. The zero-filler
is a 60-byte x00
byte array.
Because an additional XOR is used separately with AES128-CTR for encryption, the truncated filler can be easily recovered when a mix node decrypts a EncryptedRoutingInfo
. For example,
EncryptedRoutingInfo
, and decrypts it using XOR with the same pseudo-random bytes that was used when the EncryptedRoutingInfo
was created.