#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate hex;
extern crate sphinxcrypto;
extern crate ecdh_wrapper;
use std::fs::File;
use std::io::Read;
use ecdh_wrapper::PrivateKey;
use sphinxcrypto::server::sphinx_packet_unwrap;
use sphinxcrypto::commands::RoutingCommand;
use sphinxcrypto::client::decrypt_surb_payload;
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct HexNodeParams {
ID: String,
PrivateKey: String,
}
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct HexPathHop {
ID: String,
PublicKey: String,
Commands: Vec<String>,
}
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct HexSphinxTest {
Nodes: Vec<HexNodeParams>,
Path: Vec<HexPathHop>,
Packets: Vec<String>,
Payload: String,
Surb: String,
SurbKeys: String,
}
#[test]
fn sphinx_vector_test() {
let mut file = File::open("sphinx_vectors.json").unwrap();
let mut vectors = String::new();
file.read_to_string(&mut vectors).unwrap();
let tests: Vec<HexSphinxTest> = serde_json::from_str(&vectors).unwrap();
let mut i = 0;
while i < tests.len() {
let mut j = 0;
let mut packet: Vec<u8> = Vec::new();
packet.extend(hex::decode(&tests[i].Packets[0]).unwrap());
while j < tests[i].Nodes.len() {
let node_keypair = PrivateKey::from_bytes(&hex::decode(&tests[i].Nodes[j].PrivateKey).unwrap()).unwrap();
let (payload, _tag, commands, err) = sphinx_packet_unwrap(&node_keypair, &mut packet);
assert!(err.is_none());
if j == tests[i].Path.len()-1 {
if tests[i].Surb.len() > 0 {
let commands = commands.unwrap();
assert_eq!(2, commands.len());
assert_eq!(commands[0].to_vec(), hex::decode(&tests[i].Path[j].Commands[0]).unwrap());
assert_eq!(commands[1].to_vec(), hex::decode(&tests[i].Path[j].Commands[1]).unwrap());
let plaintext = decrypt_surb_payload(payload.unwrap(), hex::decode(&tests[i].SurbKeys).unwrap()).unwrap();
assert_eq!(plaintext, hex::decode(&tests[i].Payload).unwrap());
} else {
let commands = commands.unwrap();
assert_eq!(1, commands.len());
assert_eq!(commands[0].to_vec(), hex::decode(&tests[i].Path[j].Commands[0]).unwrap());
assert_eq!(payload.unwrap(), hex::decode(&tests[i].Payload).unwrap());
}
} else {
let commands = commands.unwrap();
assert_eq!(packet, hex::decode(&tests[i].Packets[j+1]).unwrap());
assert_eq!(2, commands.len());
assert_eq!(commands[0].to_vec(), hex::decode(&tests[i].Path[j].Commands[0]).unwrap());
if let RoutingCommand::NextHop(n) = &commands[1] {
assert_eq!(hex::decode(&tests[i].Path[j+1].ID).unwrap(), n.id);
} else {
panic!("next hop command not found");
}
}
j += 1;
}
i += 1;
}
}