2nd resolve vac/raw/mix.md conflict

This commit is contained in:
Cofson
2025-07-25 16:46:56 +02:00
parent 2f3ea1de09
commit 6e995b19a8

View File

@@ -315,14 +315,6 @@ between the origin protocol and the Mix Protocol instances. This enables
selective anonymous routing
without modifying protocol semantics or internal behavior.
<<<<<<< HEAD
4. **Delta ($δ$)**: The encrypted payload, which can be of variable size.
- According to the [MixMatch](https://petsymposium.org/popets/2024/popets-2024-0050.pdf)
paper, the Nym network uses Sphinx packets of a fixed
size (2413 bytes).
- Considering this, the maximum $δ$ size can be chosen as 2413 bytes minus
the header length (which will be derived below).
=======
The following subsections describe how the Mix Protocol integrates with origin
protocols via
the Mix Entry and Exit layers, how per-message anonymity is controlled through
@@ -330,7 +322,6 @@ the `mixify` flag,
the rationale for defining Mix as a protocol rather than a transport, and the
end-to-end message
interaction flow.
>>>>>>> main
### 5.1 Integration with Origin Protocols
@@ -342,16 +333,10 @@ via the Mix Entry and Exit layers.
protocol and forwards them
to the local Mix Protocol instance.
<<<<<<< HEAD
The entire Sphinx packet header ($α$, $β$, and $γ$) can fit within a fixed size
of $32 + (r(t+1)+1)\kappa + 16 = 384$ bytes, leaving ample room for a large $δ$ of
up to $2413 - 384 = 2029$ bytes.
=======
- The **Mix Exit Layer** receives the final decrypted message from a Mix
Protocol instance and
forwards it to the appropriate origin protocol instance at the destination over
a client-only connection.
>>>>>>> main
This integration is external to the Mix Protocol and is not handled by mix nodes
themselves.
@@ -767,453 +752,6 @@ processing and behavior.
After decrypting one layer of the Sphinx packet, the node MUST inspect the
routing information.
<<<<<<< HEAD
```proto
message SphinxPacket {
bytes alpha = 1; // 32 bytes
bytes beta = 2; // 304 - 384 bytes
bytes gamma = 3; // 16 bytes
bytes delta = 4; // variable size, max 2029 bytes
}
```
### 5. Handler Function
The [handler function](https://docs.libp2p.io/concepts/fundamentals/protocols/#handler-functions)
is responsible for processing connections and messages for
the Mix protocol. It operates according to the mix node roles (_i.e.,_ sender,
intermediary mix node, or exit node) defined in
[Section 2.1](#21-mix-nodes-roles). This function is crucial for implementing
the core functionality of the mixnet protocol within the libp2p framework.
When a node receives a new stream for the `"/mix/1.0.0"` protocol, the handler
function is invoked. It performs different operations based on the node's role
in the current message path:
- **Role Determination**
The handler first determines the node's role for the incoming message. This
is typically done by examining the packet structure and the node's position
in the network.
- **Packet Processing**
Depending on the role, the handler processes the Sphinx packet differently:
- For senders, it creates and sends new Sphinx packets.
- For intermediary nodes, it processes and forwards existing packets.
- For exit nodes, it decrypts the final layer and disseminates the original message.
- **Error Handling**
It manages any errors that occur during packet processing, such as invalid
MACs or decryption failures.
- **Logging and Metrics**
The handler is also be responsible for logging important events and
collecting metrics for network analysis and debugging.
The specific implementation of the handler function for each role (_i.e.,_
sender, intermediary, and exit node) is detailed in the following subsections.
#### 5.1 Sender
1. **Convert the libp2p Message to Bytes**
Serialize the libp2p message to bytes and store the result in
`libp2p_message`. This can be done using Protocol Buffers or another
serialization method.
2. **Apply Spam Protection**
Apply the chosen spam protection mechanism to the `libp2p_message`.
This could be Proof of Work (PoW), Verifiable Delay Function (VDF),
Rate Limiting Nullifier (RLN), or other suitable approaches.
Refer to [Appendix A](#appendix-a-example-spam-protection-using-proof-of-work)
for details on the current implementation using PoW.
3. **Prepare the Message**
Prepare the `message` by combining the `libp2p_message` with any necessary data
from the spam protection mechanism. The exact format of `message` will depend
on the chosen spam protection method.
Note: The spam protection mechanism is designed as a pluggable interface,
allowing for different methods to be implemented based on network requirements.
This flexibility extends to other components such as peer discovery and incentivization,
which are not specified in detail to allow for future optimizations and adaptations.
4. **Perform Path Selection** (refer [Section 2.4](#24-node-discovery))
- Let the Ed25519 public keys of the mix nodes in the path be
$y_0,\ y_1,\ \ldots,\ y_{L-1}$.
5. **Wrap Final Message in Sphinx Packet**
Perform the following steps to wrap `message` in a Sphinx packet:
a. **Compute** **Alphas ($α_i$**, **$i=0$** to **$L-1$)**
- Select a random exponent $x$ from $\mathbb{Z}_q^*$.
- Compute initial alpha $α_0$, shared secret $s_0$, and blinding factor $b_0$:
- $α_0 = g^x$ using Curve25519 scalar multiplication.
- $s_0 = y_0^x$, where $y_0$ is the public key of the first hop.
- $b_0 = H(α_0\ |\ s_0)$, where $H$ is the SHA-256 hash function (refer
_[Section 3](#3-cryptographic-primitives-and-security-parameter)_ for details).
- For each node $i$ (from $1$ to $L-1$):
- $α_i = α_{i-1}^{b_{i-1}}$ using Curve25519 scalar multiplication.
- $s_i = y_{i}^{x\prod_{\text{j=0}}^{\text{i-1}} b_{j}}$, where $y_{i}$ is
the public key of the i-th hop.
- $b_i = H(α_i\ |\ s_i)$, where $H$ is the SHA-256 hash function.
Note that $\alpha_i$ and $s_i$ are group elements, each 32 bytes long.
b. **Compute** **Filler Strings ($\phi_i$**, **$i=0$** to **$L-1$)**
- Initialize $\phi_0$ as an empty string.
- For each $i$ (from $1$ to $L-1$):
- Derive the AES key and IV:
$`\text{φ\_aes\_key}_{i-1} = KDF(\text{"aes\_key"}\ |\ s_{i-1})`$
$`\text{φ\_iv}_{i-1} = H(\text{"iv"}\ |\ s_{i-1})`$ (truncated to 128 bits)
- Compute the filler string $\phi_i$ using $\text{AES-CTR}^\prime_i$,
which is AES-CTR encryption with the keystream starting from
index $((t+1)(r-i)+t+2)\kappa$ :
$`\phi_i = \text{AES-CTR}^\prime_i(\text{φ\_aes\_key}_{i-1},\ \text{φ\_iv}_{i-1},
\ \phi_{i-1}\ |\ 0_{(t+1)\kappa})`$,
where $0_{(t+1)\kappa}$ is the string of $0$ bits of length $(t+1)\kappa$.
Note that the length of $\phi_i$ is $(t+1)i\kappa$.
c. **Compute** **Betas and Gammas ($\beta_i$**, $\gamma_i$, **$i=0$** to **$L-1$)**
For each $i$ (from $L-1$ to $0$):
- Derive the AES key, MAC key, and IV:
$`\text{β\_aes\_key}_{i} = KDF(\text{"aes\_key"}\ |\ s_{i})`$
$`\text{mac\_key}_{i} = KDF(\text{"mac\_key"}\ |\ s_{i})`$
$`\text{β\_iv}_{i} = H(\text{"iv"}\ |\ s_{i})`$ (truncated to 128 bits)
- Generate random $`\text{delay\_i}`$, a 16-bit unsigned integer (0-65535 milliseconds).
Note that top-level applications can use other probability distributions,
such as an exponential distribution, where shorter delays are more likely
than longer delays. This can mimic real-world traffic patterns and provide
robust anonymity against traffic analysis. The trade-off lies in balancing
the need for flexible delay handling with the risk of exposing
application-specific traffic patterns.
- If $i = L-1$ (_i.e.,_ exit node):
$`\beta_i = \text{AES-CTR}(\text{β\_aes\_key}_{i},\ \text{β\_iv}_{i},\ 0_{((t+1)
(r-L)+t+2)\kappa})\ |\ \phi_{L-1}`$
- Otherwise (_i.e.,_ intermediary node):
$`\beta_i = \text{AES-CTR}(\text{β\_aes\_key}_{i},\ \text{β\_iv}_{i},\ \text
{addr}_{i+1} \ |\ \text{delay}_{i+1}\ | \ \gamma_{i+1}\ |\ {\beta_{i+1}}_
{[0\ldots(r(t+1)-t)\kappa1]})`$
Note that the length of $\beta_i$ is $(r(t+1)+1)\kappa$, $0 \leq i \leq L-1$,
where $t$ is the combined length of next hop address and delay.
- $`\gamma_i = \text{HMAC-SHA-256}(\text{mac\_key}_i,\ β_i)`$\
Note that the length of $\gamma_i$ is $\kappa$.
d. **Compute** **Deltas (**$\delta_i$, **$i=0$** to **$L-1$)**
For each $i$ (from $L-1$ to $0$):
- Derive the AES key and IV:
$`\text{δ\_aes\_key}_{i} = KDF(\text{"δ\_aes\_key"}\ |\ s_{i})`$
$`\text{δ\_iv}_{i} = H(\text{"δ\_iv"}\ |\ s_{i})`$ (truncated to 128 bits)
- If $i = L-1$ (_i.e.,_ exit node):
$`\delta_i = \text{AES-CTR}(\text{δ\_aes\_key}_{i},\ \text{δ\_iv}_{i},
\ 0_{\kappa}\ |\ m)`$, where $m$ is the `message`.
- Otherwise (_i.e.,_ intermediary node):
$`\delta_i = \text{AES-CTR}(\text{δ\_aes\_key}_{i},\ \text{δ\_iv}_{i},\ \delta_{i+1})`$
Note that the length of $\delta$ is $|m| + \kappa$.
Given that the derived size of $\delta$ is $2029$ bytes, this allows
`message` to be of length $2029-16 = 2013$ bytes. This means smaller
messages may need to be padded up to $2013$ bytes (e.g., using PKCS#7
padding).
e. **Construct Final Sphinx Packet**
- Initialize header
```pseudocode
alpha = alpha_0 // 32 bytes
beta = beta_0 // $(r(t+1)+1)\kappa$ bytes
gamma = gamma_0 // 16 bytes
```
As discussed earlier, for a maximum path length of $r = 5$, and combined
length of address and delay $t = 3\kappa = 48$ bytes, the header size is
just $384$ bytes.
- Initialize payload
`delta = delta_0 // variable size, max 2029 bytes`
For a fixed Sphinx packet size of $2413$ bytes and given the header length
of $384$ bytes, `delta` size is $2029$ bytes.
6. **Serialize the Sphinx Packet** using Protocol Buffers.
7. **Send the Serialized Packet** to the first mix node using the
`"/mix/1.0.0"` protocol.
#### 5.2 Intermediary Mix Node
Let $`x_i \in \mathbb{Z}_q^*`$ be the intermediary nodes private key
corresponding to the public key $y_i \in G^*$. It performs the following steps
to relay a message:
1. **Receive and Deserialize** the Sphinx packet using Protocol Buffers.
2. **Compute Shared Secret $s = \alpha^{x_{i}}$**.
3. **Check If Previously Seen**
a. Compute tag $H(s)$, where $H$ is the SHA-256 hash function.
b. If tag is in the previously seen list of tags, discard the message.
c. This list can be reset whenever the node rotates its private key
4. **Compute MAC**
a. Derive MAC key
$`\text{mac\_key} = KDF(\text{"mac\_key"}\ |\ s)`$
b. Check if $`\gamma = \text{HMAC-SHA-256}(\text{mac\_key},\ β)`$ . If not,
discard the message.
c. Otherwise, store tag $H(s)$ in the list of seen message tags.
5. **Decrypt One Layer**
a. Derive the AES key, MAC key, and IV:
$`\text{β\_aes\_key} = KDF(\text{"aes\_key"}\ |\ s)`$
$`\text{β\_iv} = H(\text{"iv"}\ |\ s)`$ (truncated to 128 bits)
b. Compute
$`B = \text{AES-CTR}(\text{β\_aes\_key},\ \text{β\_iv},\ \beta\ |\ 0_{(t+1)k})`$.
c. Uniquely parse prefix of $B$
If $B$ has a prefix of **$0_{((t+1)(r-L)+t+2)\kappa}$,** the current node is the
exit node (refer exit node operations below).
Otherwise, it is an intermediary node and it performs the followings steps
to relay the message.
d. **Extract Routing Information**
$`\text{next\_hop} = B_{[0\ldots(t\kappa-17)]}`$ (first $t\kappa-2$ bytes).
e. **Extract Delay**
$`\text{delay} = B_{[(t\kappa-16)\ldots(t\kappa-1)]}`$ (following $2$ bytes).
f. **Extract Gamma**
$`{\gamma}' = B_{[t\kappa\ldots(t\kappa+\kappa-1)]}`$ (following $\kappa$ bytes).
g. **Extract Beta**
$`\beta' = B_{[(t\kappa+\kappa)\ldots(r(t+1)+t+2)\kappa-1]}`$ (following
$((t+1)r + 1)\kappa$ bytes).
h. **Compute Alpha**
- Compute blinding factor $b = H(α\ |\ s)$, where $H$ is the SHA-256 hash
function.
- Compute $α^ = α^b$.
i. **Compute Delta**
- Derive the AES key and IV:
$`\text{δ\_aes\_key} = KDF(\text{"δ\_aes\_key"}\ |\ s)`$
$`\text{δ\_iv} = H(\text{"δ\_iv"}\ |\ s)$` (truncated to 128 bits)
- Compute $`\delta' = \text{AES-CTR}(\text{δ\_aes\_key},\ \text{δ\_iv},\ \delta)`$
6. **Construct Final Sphinx Packet**
a. Initialize header
```pseudocode
alpha = alpha' // 32 bytes
beta = beta' // $((t+1)r + 1)\kappa$ bytes
gamma = gamma' // 16 bytes
```
b. Initialize payload
`delta = delta' // variable size, max 2029 bytes`
7. **Serialize the Sphinx Packet** using Protocol Buffers.
8. **Introduce A Delay** of $`\text{delay}`$ milliseconds.
9. **Send the Serialized Packet** to $`\text{next\_hop}`$ using the
`"/mix/1.0.0"` protocol.
#### 5.3 Exit Node
1. **Perform _Steps i. to v. b._ Above**, similar to an intermediary node. If
$B$ has a prefix of $0_{((t+1)(r-L)+t+2)\kappa}$ (in _step 5. c._ above), the
current node is the exit node. It performs the following steps to
disseminate the message via the respective libp2p protocol.
2. **Compute Delta**
- Derive the AES key and IV:
$`\text{δ\_aes\_key} = KDF(\text{"δ\_aes\_key"}\ |\ s)`$
$`\text{δ\_iv} = H(\text{"δ\_iv"}\ |\ s)`$ (truncated to 128 bits)
- Compute $`\delta' = \text{AES-CTR}(\text{δ\_aes\_key},\ \text{δ\_iv},\ \delta)`$.
3. **Extract Message**
$m = \delta'_{[\kappa\ldots]}$ (remove first $\kappa$ bytes).
4. **Remove Any Padding** from $m$ to obtain the `message` including any
necessary spam protection data.
5. **Verify Spam Protection**
Verify the spam protection mechanism applied to the `message`.
If the verification fails, discard the `message`.
Refer to [Appendix A](#appendix-a-example-spam-protection-using-proof-of-work)
for details on the current implementation using PoW.
6. **Deserialize the extracted message** using the respective libp2p protocol's
definition.
7. **Disseminate the message** via the respective libp2p protocol (_e.g.,_
GossipSub).
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
### Normative
[Handler function](https://docs.libp2p.io/concepts/fundamentals/protocols/#handler-functions)
[libp2p](https://libp2p.io)\
[Sphinx](https://cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf)
### Informative
[PoW](https://bitcoin.org/bitcoin.pdf)\
[Sphinx packet size](https://petsymposium.org/popets/2024/popets-2024-0050.pdf)
## Appendix A. Example Spam Protection using Proof of Work
The current implementation uses a Proof of Work mechanism for spam protection.
This section details the specific steps for attaching and verifying the PoW.
### Structure
The sender appends the PoW to the serialized libp2p message, `libp2p_message`,
in a structured format, making it easy to parse and verify by the exit node.
The sender includes the PoW as follows:
 `message = <libp2p_message_bytes | timestamp | nonce>`
where:
`<libp2p_message_bytes>`: Serialized libp2p message (variable length).
`<timestamp>`: The current Unix timestamp in seconds (4 bytes).
`<nonce>`: The nonce that satisfies the PoW difficulty criterion (4 bytes).
**Nonce Size:** The nonce size should be large enough to ensure a sufficiently large
search space. It should be chosen so that the range of possible nonce values
allows for the difficulty target to be met. However, larger nonce sizes can increase
the time and computational effort required to find a valid nonce. We use
a 4-byte nonce to ensure sufficiently large search space with reasonable
computational effort.
**Difficulty Level:** The difficulty level is usually expressed as the number of
leading zeros required in the hash output. It is chosen such that the
computational effort required is significant but not prohibitive.
We recommend a reasonable difficulty level that requires around
16-18 leading zeros in the SHA-256 hash. This would roughly take
0.65 to 2.62 seconds to compute in a low-grade CPU,
capable of computing 100,000 hashes per second.
### Calculate Proof of Work (PoW)
The sender performs the following steps to compute the PoW challenge and response:
i. **Create Challenge**
Retrieves the current Unix timestamp, `timestamp`, in seconds (4 bytes).
ii. **Find A Valid Nonce**
- Initializes the `nonce` to a 4-byte value (initially zero).
- Increments the `nonce` until the SHA-256 hash of
`<libp2p_message_bytes | timestamp | nonce>` has at least
18 leading zeros.
- The final value of the `nonce` is considered valid.
### Attach the PoW to the libp2p Message
Append the 4-byte `timestamp` and the valid `nonce` to
the `libp2p_message_bytes` to form the `message`.
`message = <libp2p_message_bytes | timestamp | nonce>`
### Verify PoW
i. **Extract Timestamp and Nonce**
Split `message` into 4-byte `nonce` (last 4 bytes), 4-byte `timestamp`
(the 4 bytes before the nonce), and the serialized libp2p message
to be published, `libp2p_message_bytes` (the remaining bytes).
ii. **Verify Timestamp**
- Check the `timestamp` is within the last 5 minutes.
- If the timestamp is outside the acceptable window, the exit node
discards the message.
iii. **Verify Response**
- Compute the SHA-256 hash of the `message` and check if the hash
meets the difficulty requirement, _i.e._, has at least 18 leading zeros.
- If the hash is not valid, the exit node discards the message. Otherwise,
it follows the steps to publish the message.
=======
If this layer indicates that the next hop is the final destination, the packet
MUST be processed
as an exit. Otherwise, it MUST be processed as an intermediary.
@@ -1357,4 +895,3 @@ are fixed strings and MUST be agreed upon across implementations.
These primitives are used consistently throughout packet construction and
decryption, as described in the following sections.
>>>>>>> main