2024-02-05 09:04:02 +01:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import random
|
|
|
|
|
from dataclasses import dataclass
|
2024-06-26 14:22:16 +09:00
|
|
|
from typing import List
|
2024-02-05 09:04:02 +01:00
|
|
|
|
|
|
|
|
from cryptography.hazmat.primitives.asymmetric.x25519 import (
|
|
|
|
|
X25519PrivateKey,
|
|
|
|
|
X25519PublicKey,
|
|
|
|
|
)
|
2024-06-26 14:22:16 +09:00
|
|
|
from pysphinx.sphinx import Node as SphinxNode
|
2024-02-05 09:04:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class MixnetConfig:
|
2024-06-26 14:22:16 +09:00
|
|
|
node_configs: List[NodeConfig]
|
|
|
|
|
membership: MixMembership
|
2024-02-08 15:39:50 +09:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
2024-06-26 14:22:16 +09:00
|
|
|
class NodeConfig:
|
|
|
|
|
private_key: X25519PrivateKey
|
|
|
|
|
conn_degree: int # Connection Degree (default: 6)
|
|
|
|
|
transmission_rate_per_sec: int # Global Transmission Rate
|
2024-02-08 15:39:50 +09:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
2024-06-26 14:22:16 +09:00
|
|
|
class MixMembership:
|
|
|
|
|
nodes: List[NodePublicInfo]
|
2024-02-08 15:39:50 +09:00
|
|
|
|
2024-06-26 14:22:16 +09:00
|
|
|
def generate_route(
|
|
|
|
|
self, num_hops: int, last_mix: NodePublicInfo
|
|
|
|
|
) -> list[NodePublicInfo]:
|
2024-02-05 09:04:02 +01:00
|
|
|
"""
|
|
|
|
|
Generate a mix route for a Sphinx packet.
|
|
|
|
|
The pre-selected mix_destination is used as a last mix node in the route,
|
|
|
|
|
so that associated packets can be merged together into a original message.
|
|
|
|
|
"""
|
2024-06-26 14:22:16 +09:00
|
|
|
route = [self.choose() for _ in range(num_hops - 1)]
|
|
|
|
|
route.append(last_mix)
|
2024-02-05 09:04:02 +01:00
|
|
|
return route
|
|
|
|
|
|
2024-06-26 14:22:16 +09:00
|
|
|
def choose(self) -> NodePublicInfo:
|
2024-02-05 09:04:02 +01:00
|
|
|
"""
|
2024-06-26 14:22:16 +09:00
|
|
|
Choose a mix node as a mix destination that will reconstruct a message from Sphinx packets.
|
2024-02-05 09:04:02 +01:00
|
|
|
"""
|
2024-06-26 14:22:16 +09:00
|
|
|
return random.choice(self.nodes)
|
2024-02-05 09:04:02 +01:00
|
|
|
|
|
|
|
|
|
2024-02-08 15:39:50 +09:00
|
|
|
@dataclass
|
2024-06-26 14:22:16 +09:00
|
|
|
class NodePublicInfo:
|
|
|
|
|
private_key: X25519PrivateKey
|
2024-02-05 09:04:02 +01:00
|
|
|
|
|
|
|
|
def encryption_public_key(self) -> X25519PublicKey:
|
2024-06-26 14:22:16 +09:00
|
|
|
return self.private_key.public_key()
|
2024-02-05 09:04:02 +01:00
|
|
|
|
2024-06-26 14:22:16 +09:00
|
|
|
def sphinx_node(self) -> SphinxNode:
|
|
|
|
|
return SphinxNode(self.private_key, bytes(32))
|