extern crate rand;
extern crate sphinxcrypto;
extern crate ecdh_wrapper;
use self::rand::Rng;
use self::rand::os::OsRng;
use ecdh_wrapper::PrivateKey;
use sphinxcrypto::server::sphinx_packet_unwrap;
use sphinxcrypto::client::{new_packet, PathHop, new_surb, new_packet_from_surb, decrypt_surb_payload};
use sphinxcrypto::constants::{MAX_HOPS, NODE_ID_SIZE, FORWARD_PAYLOAD_SIZE, RECIPIENT_ID_SIZE, SURB_ID_SIZE};
use sphinxcrypto::commands::{RoutingCommand, Delay, SURBReply, Recipient};
struct NodeParams {
pub id: [u8; NODE_ID_SIZE],
pub private_key: PrivateKey,
}
fn os_rng() -> OsRng {
OsRng::new().expect("failure to create an OS RNG")
}
fn new_node<R: Rng>(rng: &mut R) -> NodeParams {
let mut id = [0u8; NODE_ID_SIZE];
rng.fill_bytes(&mut id);
let keypair = PrivateKey::generate(rng).unwrap();
return NodeParams{
id: id,
private_key: keypair,
};
}
fn new_path_vector<R: Rng>(rng: &mut R, num_hops: u8, is_surb: bool) -> (Vec<NodeParams>, Vec<PathHop>) {
const DELAY_BASE: u32 = 123;
let mut nodes = vec![];
let mut i = 0;
while i < num_hops {
nodes.push(new_node(rng));
i += 1;
}
let mut path = vec![];
i = 0;
while i < num_hops {
let mut commands: Vec<RoutingCommand> = vec![];
if i < num_hops - 1 {
let delay = RoutingCommand::Delay(
Delay{
delay: DELAY_BASE * (i as u32 + 1),
}
);
commands.push(delay);
} else {
let mut rcpt_id = [0u8; RECIPIENT_ID_SIZE];
rng.fill_bytes(&mut rcpt_id);
let rcpt = RoutingCommand::Recipient(
Recipient{
id: rcpt_id,
}
);
commands.push(rcpt);
if is_surb {
let mut surb_id = [0u8; SURB_ID_SIZE];
rng.fill_bytes(&mut surb_id);
let surb_reply = RoutingCommand::SURBReply(
SURBReply{
id: surb_id,
}
);
commands.push(surb_reply);
}
}
let hop = PathHop {
id: nodes[i as usize].id,
public_key: nodes[i as usize].private_key.public_key(),
commands: Some(commands),
};
path.push(hop);
i += 1;
}
return (nodes, path);
}
#[test]
fn sphinx_forward_test() {
let mut payload = [0u8; FORWARD_PAYLOAD_SIZE];
let s = String::from("We must defend our own privacy if we expect to have any. \
We must come together and create systems which allow anonymous transactions to take place. \
People have been defending their own privacy for centuries with whispers, darkness, envelopes, \
closed doors, secret handshakes, and couriers. The technologies of the past did not allow for strong \
privacy, but electronic technologies do.");
let _s_len = s.len();
let string_bytes = s.into_bytes();
payload[.._s_len].copy_from_slice(&string_bytes);
let mut r = os_rng();
let is_surb = false;
let mut num_hops = 1;
while num_hops <= MAX_HOPS {
let _tuple = new_path_vector(&mut r, num_hops as u8, is_surb);
let nodes = _tuple.0;
let path = _tuple.1;
let path_c = path.clone();
let _packet_result = new_packet(&mut r, path, payload.to_vec());
let mut packet = _packet_result.unwrap();
let mut i = 0;
while i < num_hops {
let _unwrap_tuple = sphinx_packet_unwrap(&nodes[i].private_key, &mut packet);
let maybe_cmds = _unwrap_tuple.2;
let err = _unwrap_tuple.3;
let final_payload = _unwrap_tuple.0;
let cmds = maybe_cmds.unwrap();
assert!(err.is_none());
if i == nodes.len() - 1 {
assert!(cmds.len() == 1);
assert_eq!(final_payload.unwrap().as_slice(), &payload[..]);
let hop = path_c[i].to_owned().commands;
match &hop.unwrap()[0] {
RoutingCommand::Recipient(recipient) => {
let _id = recipient.id;
match cmds[0] {
RoutingCommand::Recipient(ref recipient_cmd) => {
assert_eq!(recipient_cmd.id[..], _id[..]);
},
_ => panic!("wtf"),
}
}
_ => panic!("wtf"),
}
} else {
assert!(cmds.len() == 2);
assert!(final_payload.is_none());
let _delay;
let hop = path_c[i].to_owned().commands;
match &hop.unwrap()[0] {
RoutingCommand::Delay(delay) => {
_delay = delay.delay;
match cmds[0] {
RoutingCommand::Delay(ref delay_cmd) => {
assert_eq!(delay_cmd.delay, _delay);
}
_ => panic!("wtf"),
}
}
_ => panic!("wtf"),
}
}
i += 1;
}
num_hops += 1;
}
}
#[test]
fn sphinx_surb_test() {
let mut payload = [0u8; FORWARD_PAYLOAD_SIZE];
let s = String::from("There was nothing so very remarkable in that;\
nor did Alice think it so very much out of the ordinary to hear the Rabbit \
say to itself 'Oh dear! Oh dear! I shall be too late!' ...but when the Rabbit \
actually took a watch out its waistcoat pocket, and looked at it, and then \
hurried on, Alice started to her feet.");
let _s_len = s.len();
let string_bytes = s.into_bytes();
payload[.._s_len].copy_from_slice(&string_bytes);
let mut r = os_rng();
let is_surb = true;
let mut num_hops = 1;
while num_hops <= MAX_HOPS {
let _tuple = new_path_vector(&mut r, num_hops as u8, is_surb);
let nodes = _tuple.0;
let path = _tuple.1;
let path_c = path.clone();
let (surb, surb_keys) = new_surb(&mut r, path).unwrap();
let (mut packet, _next_mix) = new_packet_from_surb(surb, payload.to_vec()).unwrap();
let mut i = 0;
while i < num_hops {
let _unwrap_tuple = sphinx_packet_unwrap(&nodes[i].private_key, &mut packet);
let option_cmds = _unwrap_tuple.2;
let err = _unwrap_tuple.3;
let final_payload_res = _unwrap_tuple.0;
let cmds = option_cmds.unwrap();
assert!(err.is_none());
assert!(cmds.len() == 2);
if i == nodes.len() - 1 {
match cmds[0] {
RoutingCommand::Recipient(ref recipient) => {
let _id = recipient.id;
let hop = path_c[i].to_owned().commands;
match &hop.unwrap()[0] {
RoutingCommand::Recipient(ref recipient_cmd) => {
assert_eq!(_id[..], recipient_cmd.id[..]);
},
_ => panic!("wtf"),
}
},
_ => panic!("wtf"),
}
let _result = decrypt_surb_payload(final_payload_res.unwrap(), surb_keys.clone());
assert!(_result.is_ok());
assert_eq!(_result.unwrap(), payload.to_vec());
}
i += 1;
}
num_hops += 1;
}
}