Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for RNG propagation #86

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ blake2 = "0.8.0" # cannot be updated due to outdated dependency inside lioness
byteorder = "1.3.2"
subtle = "2.3.0"


[dev-dependencies]
mockall = "0.10.2"
criterion = "0.3"
rand_chacha = "0.2.2"

[[bench]]
name = "benchmarks"
Expand Down
9 changes: 6 additions & 3 deletions src/crypto/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ impl PrivateKey {
// honestly, this method shouldn't really exist, but right now we have no decent
// rng propagation in the library
pub fn new() -> Self {
let mut rng = OsRng;
Self::new_with_rng(&mut rng)
Self::new_with_rng(&mut OsRng)
}

pub fn new_with_rng<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
Expand Down Expand Up @@ -148,7 +147,11 @@ impl PartialEq for PublicKey {
impl Eq for PublicKey {}

pub fn keygen() -> (PrivateKey, PublicKey) {
let private_key = PrivateKey::new();
keygen_with_rng(&mut OsRng)
}

pub fn keygen_with_rng<R: RngCore + CryptoRng>(rng: &mut R) -> (PrivateKey, PublicKey) {
let private_key = PrivateKey::new_with_rng(rng);
let public_key = PublicKey::from(&private_key);
(private_key, public_key)
}
12 changes: 11 additions & 1 deletion src/header/delays.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

use crate::constants::DELAY_LENGTH;
use byteorder::{BigEndian, ByteOrder};
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};
use rand_distr::{Distribution, Exp};
use std::{borrow::Borrow, time::Duration};

Expand Down Expand Up @@ -111,11 +113,19 @@ pub fn generate_from_nanos(number: usize, average_delay: u64) -> Vec<Delay> {
}

pub fn generate_from_average_duration(number: usize, average_delay: Duration) -> Vec<Delay> {
generate_from_average_duration_with_rng(number, average_delay, &mut OsRng)
}

pub fn generate_from_average_duration_with_rng<R: RngCore + CryptoRng>(
number: usize,
average_delay: Duration,
rng: &mut R,
) -> Vec<Delay> {
let exp = Exp::new(1.0 / average_delay.as_nanos() as f64).unwrap();

std::iter::repeat(())
.take(number)
.map(|_| Delay::new_from_nanos(exp.sample(&mut rand::thread_rng()).round() as u64))
.map(|_| Delay::new_from_nanos(exp.sample(rng).round() as u64))
.collect()
}

Expand Down
15 changes: 14 additions & 1 deletion src/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ use crate::{Error, ErrorKind, Result};
use crypto::{EphemeralSecret, PrivateKey, SharedSecret};
use curve25519_dalek::scalar::Scalar;
use keys::RoutingKeys;
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};

pub mod delays;
pub mod filler;
Expand Down Expand Up @@ -54,15 +56,26 @@ impl SphinxHeader {
route: &[Node],
delays: &[Delay],
destination: &Destination,
) -> (Self, Vec<PayloadKey>) {
Self::new_with_rng(initial_secret, route, delays, destination, &mut OsRng)
}

pub fn new_with_rng<R: RngCore + CryptoRng>(
initial_secret: &EphemeralSecret,
route: &[Node],
delays: &[Delay],
destination: &Destination,
rng: &mut R,
) -> (Self, Vec<PayloadKey>) {
let key_material = keys::KeyMaterial::derive(route, initial_secret);
let filler_string = Filler::new(&key_material.routing_keys[..route.len() - 1]);
let routing_info = routing::EncapsulatedRoutingInformation::new(
let routing_info = routing::EncapsulatedRoutingInformation::new_with_rng(
route,
destination,
delays,
&key_material.routing_keys,
filler_string,
rng,
);

// encapsulate header.routing information, compute MACs
Expand Down
21 changes: 14 additions & 7 deletions src/header/routing/destination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::header::routing::nodes::EncryptedRoutingInformation;
use crate::header::routing::{RoutingFlag, Version, ENCRYPTED_ROUTING_INFO_SIZE, FINAL_HOP};
use crate::route::{Destination, DestinationAddressBytes, SURBIdentifier};
use crate::utils;
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};

// this is going through the following transformations:
/*
Expand Down Expand Up @@ -63,11 +63,15 @@ impl FinalRoutingInformation {
ENCRYPTED_ROUTING_INFO_SIZE - (FILLER_STEP_SIZE_INCREASE * (route_len - 1))
}

pub(super) fn add_padding(self, route_len: usize) -> PaddedFinalRoutingInformation {
pub(super) fn add_padding<R: RngCore + CryptoRng>(
self,
route_len: usize,
rng: &mut R,
) -> PaddedFinalRoutingInformation {
// paper uses 0 bytes for this, however, we use random instead so that we would not be affected by the
// attack on sphinx described by Kuhn et al.
let padding = utils::bytes::random(
&mut OsRng,
rng,
ENCRYPTED_ROUTING_INFO_SIZE
- (FILLER_STEP_SIZE_INCREASE * (route_len - 1))
- FINAL_NODE_META_INFO_LENGTH,
Expand Down Expand Up @@ -157,6 +161,7 @@ mod test_encapsulating_final_routing_information_and_mac {
random_node,
},
};
use rand::rngs::OsRng;

#[test]
fn it_returns_mac_on_correct_data() {
Expand All @@ -174,6 +179,7 @@ mod test_encapsulating_final_routing_information_and_mac {
routing_keys.last().unwrap(),
filler,
route.len(),
&mut OsRng,
);

let expected_mac = HeaderIntegrityMac::compute(
Expand All @@ -191,6 +197,7 @@ mod test_encapsulating_final_routing_information_and_mac {
mod test_encapsulating_final_routing_information {
use super::*;
use crate::test_utils::fixtures::{destination_fixture, filler_fixture, routing_keys_fixture};
use rand::rngs::OsRng;

#[test]
fn it_produces_result_of_length_filler_plus_padded_concatenated_destination_and_identifier_and_flag_for_route_of_length_5(
Expand All @@ -201,7 +208,7 @@ mod test_encapsulating_final_routing_information {
let destination = destination_fixture();

let final_routing_header = FinalRoutingInformation::new(&destination, route_len)
.add_padding(route_len)
.add_padding(route_len, &mut OsRng)
.encrypt(final_keys.stream_cipher_key, route_len)
.combine_with_filler(filler, route_len);

Expand All @@ -222,7 +229,7 @@ mod test_encapsulating_final_routing_information {
let destination = destination_fixture();

let final_routing_header = FinalRoutingInformation::new(&destination, route_len)
.add_padding(route_len)
.add_padding(route_len, &mut OsRng)
.encrypt(final_keys.stream_cipher_key, route_len)
.combine_with_filler(filler, route_len);

Expand All @@ -243,7 +250,7 @@ mod test_encapsulating_final_routing_information {
let destination = destination_fixture();

let final_routing_header = FinalRoutingInformation::new(&destination, route_len)
.add_padding(route_len)
.add_padding(route_len, &mut OsRng)
.encrypt(final_keys.stream_cipher_key, route_len)
.combine_with_filler(filler, route_len);

Expand All @@ -264,7 +271,7 @@ mod test_encapsulating_final_routing_information {
let destination = destination_fixture();

FinalRoutingInformation::new(&destination, route_len)
.add_padding(route_len)
.add_padding(route_len, &mut OsRng)
.encrypt(final_keys.stream_cipher_key, route_len)
.combine_with_filler(filler, route_len);
}
Expand Down
21 changes: 18 additions & 3 deletions src/header/routing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use crate::header::routing::destination::FinalRoutingInformation;
use crate::header::routing::nodes::{EncryptedRoutingInformation, RoutingInformation};
use crate::route::{Destination, Node, NodeAddressBytes};
use crate::{Error, ErrorKind, Result};
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};

pub const TRUNCATED_ROUTING_INFO_SIZE: usize =
ENCRYPTED_ROUTING_INFO_SIZE - (NODE_META_INFO_SIZE + HEADER_INTEGRITY_MAC_SIZE);
Expand Down Expand Up @@ -80,6 +82,17 @@ impl EncapsulatedRoutingInformation {
delays: &[Delay],
routing_keys: &[RoutingKeys],
filler: Filler,
) -> Self {
Self::new_with_rng(route, destination, delays, routing_keys, filler, &mut OsRng)
}

pub fn new_with_rng<R: RngCore + CryptoRng>(
route: &[Node],
destination: &Destination,
delays: &[Delay],
routing_keys: &[RoutingKeys],
filler: Filler,
rng: &mut R,
) -> Self {
assert_eq!(route.len(), routing_keys.len());
assert_eq!(delays.len(), route.len());
Expand All @@ -90,7 +103,7 @@ impl EncapsulatedRoutingInformation {
};

let encapsulated_destination_routing_info =
Self::for_final_hop(destination, final_keys, filler, route.len());
Self::for_final_hop(destination, final_keys, filler, route.len(), rng);

Self::for_forward_hops(
encapsulated_destination_routing_info,
Expand All @@ -100,15 +113,16 @@ impl EncapsulatedRoutingInformation {
)
}

fn for_final_hop(
fn for_final_hop<R: RngCore + CryptoRng>(
dest: &Destination,
routing_keys: &RoutingKeys,
filler: Filler,
route_len: usize,
rng: &mut R,
) -> Self {
// personal note: I like how this looks so much.
FinalRoutingInformation::new(dest, route_len)
.add_padding(route_len) // add padding to obtain correct destination length
.add_padding(route_len, rng) // add padding to obtain correct destination length
.encrypt(routing_keys.stream_cipher_key, route_len) // encrypt with the key of final node (in our case service provider)
.combine_with_filler(filler, route_len) // add filler to get header of correct length
.encapsulate_with_mac(routing_keys.header_integrity_hmac_key) // combine the previous data with a MAC on the header (also calculated with the SPs key)
Expand Down Expand Up @@ -304,6 +318,7 @@ mod encapsulating_forward_routing_information {
routing_keys.last().unwrap(),
filler,
route.len(),
&mut OsRng,
);

let destination_routing_info_copy = destination_routing_info.clone();
Expand Down
25 changes: 23 additions & 2 deletions src/packet/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{
route::{Destination, Node},
Result, SphinxPacket,
};
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};

pub const DEFAULT_PAYLOAD_SIZE: usize = 1024;

Expand Down Expand Up @@ -34,10 +36,29 @@ impl<'a> SphinxPacketBuilder<'a> {
route: &[Node],
destination: &Destination,
delays: &[Delay],
) -> Result<SphinxPacket> {
self.build_packet_with_rng(message, route, destination, delays, &mut OsRng)
}

pub fn build_packet_with_rng<R: RngCore + CryptoRng, M: AsRef<[u8]>>(
&self,
message: M,
route: &[Node],
destination: &Destination,
delays: &[Delay],
rng: &mut R,
) -> Result<SphinxPacket> {
let (header, payload_keys) = match self.initial_secret.as_ref() {
Some(initial_secret) => SphinxHeader::new(initial_secret, route, delays, destination),
None => SphinxHeader::new(&EphemeralSecret::new(), route, delays, destination),
Some(initial_secret) => {
SphinxHeader::new_with_rng(initial_secret, route, delays, destination, rng)
}
None => SphinxHeader::new_with_rng(
&EphemeralSecret::new_with_rng(rng),
route,
delays,
destination,
rng,
),
};

// no need to check if plaintext has correct length as this check is already performed in payload encapsulation
Expand Down
Loading