Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sphinx-packet"
version = "0.4.0"
version = "0.5.0"
authors = ["Ania Piotrowska <ania@nymtech.net>", "Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -16,6 +16,9 @@ ctr = "0.9.2"
bs58 = "0.5.1"
x25519-dalek = { version = "2.0.1", features = ["static_secrets", "getrandom", "zeroize"] }

# for legacy compat
curve25519-dalek = { version = "4.1.3" }

hmac = "0.12.1"
digest = "0.10.7"
rand = "0.8.5"
Expand All @@ -28,11 +31,13 @@ chacha = "0.3.0"
blake2 = "0.8.0" # cannot be updated due to outdated dependency inside lioness
byteorder = "1.5.0"
subtle = "2.4.1"
zeroize = "1.7.0"



[dev-dependencies]
criterion = "0.5.1"
rand_chacha = "0.3.1"

[[bench]]
name = "benchmarks"
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,21 @@ of this library

added additional public methods on the `Version`

#### v0.3.2

added version method to allow constructing SURBs with legacy headers

#### v0.4.0

removed processing and creation of packets with undefined operations

#### v0.5.0

- temporarily restored processing and creation of packets with undefined operations as additional breaking changes had
to be added to v0.3.2 release
- removed `RoutingKeys` in favour of `ExpandedSharedSecret` and added `ReplyTag`
- type adjustments

### Benchmarks

To run benchmarks, use:
Expand Down
10 changes: 8 additions & 2 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ use sha2::Sha256;
pub const SECURITY_PARAMETER: usize = 16; // k in the Sphinx paper. Measured in bytes; 128 bits.
pub const MAX_PATH_LENGTH: usize = 5; // r in the Sphinx paper
pub const BLINDING_FACTOR_SIZE: usize = 2 * SECURITY_PARAMETER;
pub const ROUTING_KEYS_LENGTH: usize = crypto::STREAM_CIPHER_KEY_SIZE

/// Output of the h𝜏 hash function / random oracle
pub const REPLAY_TAG_SIZE: usize = 2 * SECURITY_PARAMETER;

pub const EXPANDED_SHARED_SECRET_LENGTH: usize = crypto::STREAM_CIPHER_KEY_SIZE
+ INTEGRITY_MAC_KEY_SIZE
+ PAYLOAD_KEY_SIZE
+ BLINDING_FACTOR_SIZE;
+ BLINDING_FACTOR_SIZE
+ REPLAY_TAG_SIZE;

pub const HKDF_INPUT_SEED: &[u8; 97] = b"Dwste mou enan moxlo arketa makru kai ena upomoxlio gia na ton topothetisw kai tha kinisw thn gh.";
pub const STREAM_CIPHER_OUTPUT_LENGTH: usize =
(NODE_META_INFO_SIZE + HEADER_INTEGRITY_MAC_SIZE) * (MAX_PATH_LENGTH + 1);
Expand Down
99 changes: 49 additions & 50 deletions src/header/filler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,23 @@

use crate::constants::{HEADER_INTEGRITY_MAC_SIZE, MAX_PATH_LENGTH, NODE_META_INFO_SIZE};
use crate::crypto;
use crate::header::keys::RoutingKeys;
use crate::header::shared_secret::ExpandedSharedSecret;
use crate::{constants, utils};

pub const FILLER_STEP_SIZE_INCREASE: usize = NODE_META_INFO_SIZE + HEADER_INTEGRITY_MAC_SIZE;

#[derive(Debug, PartialEq, Eq)]
pub struct Filler {
value: Vec<u8>,
}
pub struct Filler(Vec<u8>);

impl Filler {
pub fn new(routing_keys: &[RoutingKeys]) -> Self {
assert!(routing_keys.len() <= MAX_PATH_LENGTH);
let filler_value = routing_keys
pub(crate) fn new(expanded_shared_secrets: &[ExpandedSharedSecret]) -> Self {
assert!(expanded_shared_secrets.len() <= MAX_PATH_LENGTH);
let filler_value = expanded_shared_secrets
.iter()
.map(|node_routing_keys| node_routing_keys.stream_cipher_key) // we only want the cipher key
.map(|ess| ess.stream_cipher_key()) // we only want the cipher key
.map(|cipher_key| {
crypto::generate_pseudorandom_bytes(
&cipher_key,
cipher_key,
&crypto::STREAM_CIPHER_INIT_VECTOR,
constants::STREAM_CIPHER_OUTPUT_LENGTH,
)
Expand All @@ -45,9 +43,7 @@ impl Filler {
Self::filler_step(filler_string_accumulator, i, pseudorandom_bytes)
},
);
Self {
value: filler_value,
}
Self(filler_value)
}

fn filler_step(
Expand Down Expand Up @@ -75,41 +71,44 @@ impl Filler {

filler_string_accumulator
}
}

pub fn get_value(self) -> Vec<u8> {
self.value
impl From<Vec<u8>> for Filler {
fn from(raw_bytes: Vec<u8>) -> Self {
Self(raw_bytes)
}
}

pub(crate) fn from_raw(raw_value: Vec<u8>) -> Self {
Filler { value: raw_value }
impl From<Filler> for Vec<u8> {
fn from(filler: Filler) -> Self {
filler.0
}
}

#[cfg(test)]
mod test_creating_pseudorandom_bytes {
use crate::header::keys;

use super::*;
use crate::header::shared_secret::ExpandSecret;
use x25519_dalek::{PublicKey, StaticSecret};

#[test]
fn with_no_keys_it_generates_empty_filler_string() {
let routing_keys: Vec<RoutingKeys> = vec![];
let filler_string = Filler::new(&routing_keys);
let expanded_shared_secret: Vec<_> = vec![];
let filler_string = Filler::new(&expanded_shared_secret);

assert_eq!(0, filler_string.value.len());
assert_eq!(0, filler_string.0.len());
}

#[test]
fn with_1_key_it_generates_filler_of_length_1_times_3_times_security_parameter() {
let shared_keys = [PublicKey::from(&StaticSecret::random())];
let routing_keys: Vec<_> = shared_keys
let expanded_shared_secret: Vec<_> = shared_keys
.iter()
.map(|&key| keys::RoutingKeys::derive(key))
.map(|&key| key.expand_shared_secret())
.collect();
let filler_string = Filler::new(&routing_keys);
let filler_string = Filler::new(&expanded_shared_secret);

assert_eq!(FILLER_STEP_SIZE_INCREASE, filler_string.value.len());
assert_eq!(FILLER_STEP_SIZE_INCREASE, filler_string.0.len());
}

#[test]
Expand All @@ -119,12 +118,12 @@ mod test_creating_pseudorandom_bytes {
PublicKey::from(&StaticSecret::random()),
PublicKey::from(&StaticSecret::random()),
];
let routing_keys: Vec<_> = shared_keys
let expanded_shared_secret: Vec<_> = shared_keys
.iter()
.map(|&key| keys::RoutingKeys::derive(key))
.map(|&key| key.expand_shared_secret())
.collect();
let filler_string = Filler::new(&routing_keys);
assert_eq!(3 * FILLER_STEP_SIZE_INCREASE, filler_string.value.len());
let filler_string = Filler::new(&expanded_shared_secret);
assert_eq!(3 * FILLER_STEP_SIZE_INCREASE, filler_string.0.len());
}

#[test]
Expand All @@ -133,43 +132,43 @@ mod test_creating_pseudorandom_bytes {
let shared_keys: Vec<_> = std::iter::repeat_n((), constants::MAX_PATH_LENGTH + 1)
.map(|_| PublicKey::from(&StaticSecret::random()))
.collect();
let routing_keys: Vec<_> = shared_keys
let expanded_shared_secrets: Vec<_> = shared_keys
.iter()
.map(|&key| keys::RoutingKeys::derive(key))
.map(|&key| key.expand_shared_secret())
.collect();
Filler::new(&routing_keys);
Filler::new(&expanded_shared_secrets);
}
}

#[cfg(test)]
mod test_new_filler_bytes {
use super::*;
use crate::test_utils::fixtures::routing_keys_fixture;
use crate::test_utils::fixtures::expanded_shared_secret_fixture;

#[test]
fn it_retusn_filler_bytes_of_correct_length_for_3_routing_keys() {
let routing_key_1 = routing_keys_fixture();
let routing_key_2 = routing_keys_fixture();
let routing_key_3 = routing_keys_fixture();
let routing_keys = [routing_key_1, routing_key_2, routing_key_3];
let filler = Filler::new(&routing_keys);
fn it_retusn_filler_bytes_of_correct_length_for_3_expanded_shared_secret() {
let routing_key_1 = expanded_shared_secret_fixture();
let routing_key_2 = expanded_shared_secret_fixture();
let routing_key_3 = expanded_shared_secret_fixture();
let expanded_shared_secret = [routing_key_1, routing_key_2, routing_key_3];
let filler = Filler::new(&expanded_shared_secret);
assert_eq!(
FILLER_STEP_SIZE_INCREASE * (routing_keys.len()),
filler.get_value().len()
FILLER_STEP_SIZE_INCREASE * (expanded_shared_secret.len()),
filler.0.len()
)
}

#[test]
fn it_retusn_filler_bytes_of_correct_length_for_4_routing_keys() {
let routing_key_1 = routing_keys_fixture();
let routing_key_2 = routing_keys_fixture();
let routing_key_3 = routing_keys_fixture();
let routing_key_4 = routing_keys_fixture();
let routing_keys = [routing_key_1, routing_key_2, routing_key_3, routing_key_4];
let filler = Filler::new(&routing_keys);
fn it_retusn_filler_bytes_of_correct_length_for_4_expanded_shared_secret() {
let routing_key_1 = expanded_shared_secret_fixture();
let routing_key_2 = expanded_shared_secret_fixture();
let routing_key_3 = expanded_shared_secret_fixture();
let routing_key_4 = expanded_shared_secret_fixture();
let expanded_shared_secret = [routing_key_1, routing_key_2, routing_key_3, routing_key_4];
let filler = Filler::new(&expanded_shared_secret);
assert_eq!(
FILLER_STEP_SIZE_INCREASE * (routing_keys.len()),
filler.get_value().len()
FILLER_STEP_SIZE_INCREASE * (expanded_shared_secret.len()),
filler.0.len()
)
}
}
Expand Down
Loading
Loading