Just use priv/pubkey as Node ID in the mock mix message encoding (#912)
* Just use priv/pubkey as Node ID in the mock mix message encoding * do not convert private key to public key in mix service
This commit is contained in:
parent
1c62ced9ea
commit
7b984a4e29
@ -3,21 +3,20 @@ use crate::{Error, MixMessage};
|
||||
//
|
||||
/// A mock implementation of the Sphinx encoding.
|
||||
|
||||
const PRIVATE_KEY_SIZE: usize = 32;
|
||||
const PUBLIC_KEY_SIZE: usize = 32;
|
||||
const NODE_ID_SIZE: usize = 32;
|
||||
|
||||
const PADDED_PAYLOAD_SIZE: usize = 2048;
|
||||
const PAYLOAD_PADDING_SEPARATOR: u8 = 0x01;
|
||||
const PAYLOAD_PADDING_SEPARATOR_SIZE: usize = 1;
|
||||
const MAX_LAYERS: usize = 5;
|
||||
pub const MESSAGE_SIZE: usize = PUBLIC_KEY_SIZE * MAX_LAYERS + PADDED_PAYLOAD_SIZE;
|
||||
pub const MESSAGE_SIZE: usize = NODE_ID_SIZE * MAX_LAYERS + PADDED_PAYLOAD_SIZE;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MockMixMessage;
|
||||
|
||||
impl MixMessage for MockMixMessage {
|
||||
type PublicKey = [u8; PUBLIC_KEY_SIZE];
|
||||
type PrivateKey = [u8; PRIVATE_KEY_SIZE];
|
||||
type PublicKey = [u8; NODE_ID_SIZE];
|
||||
type PrivateKey = [u8; NODE_ID_SIZE];
|
||||
const DROP_MESSAGE: &'static [u8] = &[0; MESSAGE_SIZE];
|
||||
|
||||
/// The length of the encoded message is fixed to [`MESSAGE_SIZE`] bytes.
|
||||
@ -25,7 +24,9 @@ impl MixMessage for MockMixMessage {
|
||||
/// The payload is zero-padded to the end.
|
||||
///
|
||||
fn build_message(payload: &[u8], public_keys: &[Self::PublicKey]) -> Result<Vec<u8>, Error> {
|
||||
if public_keys.is_empty() || public_keys.len() > MAX_LAYERS {
|
||||
// In this mock, we don't encrypt anything. So, we use public key as just a node ID.
|
||||
let node_ids = public_keys;
|
||||
if node_ids.is_empty() || node_ids.len() > MAX_LAYERS {
|
||||
return Err(Error::InvalidNumberOfLayers);
|
||||
}
|
||||
if payload.len() > PADDED_PAYLOAD_SIZE - PAYLOAD_PADDING_SEPARATOR_SIZE {
|
||||
@ -34,11 +35,11 @@ impl MixMessage for MockMixMessage {
|
||||
|
||||
let mut message: Vec<u8> = Vec::with_capacity(MESSAGE_SIZE);
|
||||
|
||||
public_keys.iter().for_each(|public_key| {
|
||||
message.extend(public_key);
|
||||
node_ids.iter().for_each(|node_id| {
|
||||
message.extend(node_id);
|
||||
});
|
||||
// If there is any remaining layers, fill them with zeros.
|
||||
(0..MAX_LAYERS - public_keys.len()).for_each(|_| message.extend(&[0; PUBLIC_KEY_SIZE]));
|
||||
(0..MAX_LAYERS - node_ids.len()).for_each(|_| message.extend(&[0; NODE_ID_SIZE]));
|
||||
|
||||
// Append payload with padding
|
||||
message.extend(payload);
|
||||
@ -58,16 +59,15 @@ impl MixMessage for MockMixMessage {
|
||||
return Err(Error::InvalidMixMessage);
|
||||
}
|
||||
|
||||
let public_key =
|
||||
x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::from(*private_key))
|
||||
.to_bytes();
|
||||
if message[0..PUBLIC_KEY_SIZE] != public_key {
|
||||
// In this mock, we don't decrypt anything. So, we use private key as just a node ID.
|
||||
let node_id = private_key;
|
||||
if &message[0..NODE_ID_SIZE] != node_id {
|
||||
return Err(Error::MsgUnwrapNotAllowed);
|
||||
}
|
||||
|
||||
// If this is the last layer
|
||||
if message[PUBLIC_KEY_SIZE..PUBLIC_KEY_SIZE * 2] == [0; PUBLIC_KEY_SIZE] {
|
||||
let padded_payload = &message[PUBLIC_KEY_SIZE * MAX_LAYERS..];
|
||||
if message[NODE_ID_SIZE..NODE_ID_SIZE * 2] == [0; NODE_ID_SIZE] {
|
||||
let padded_payload = &message[NODE_ID_SIZE * MAX_LAYERS..];
|
||||
// remove the payload padding
|
||||
match padded_payload
|
||||
.iter()
|
||||
@ -81,9 +81,9 @@ impl MixMessage for MockMixMessage {
|
||||
}
|
||||
|
||||
let mut new_message: Vec<u8> = Vec::with_capacity(MESSAGE_SIZE);
|
||||
new_message.extend(&message[PUBLIC_KEY_SIZE..PUBLIC_KEY_SIZE * MAX_LAYERS]);
|
||||
new_message.extend(&[0; PUBLIC_KEY_SIZE]);
|
||||
new_message.extend(&message[PUBLIC_KEY_SIZE * MAX_LAYERS..]); // padded payload
|
||||
new_message.extend(&message[NODE_ID_SIZE..NODE_ID_SIZE * MAX_LAYERS]);
|
||||
new_message.extend(&[0; NODE_ID_SIZE]);
|
||||
new_message.extend(&message[NODE_ID_SIZE * MAX_LAYERS..]); // padded payload
|
||||
Ok((new_message, false))
|
||||
}
|
||||
}
|
||||
@ -94,31 +94,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn message() {
|
||||
let private_keys = [
|
||||
x25519_dalek::StaticSecret::random(),
|
||||
x25519_dalek::StaticSecret::random(),
|
||||
x25519_dalek::StaticSecret::random(),
|
||||
];
|
||||
let public_keys = private_keys
|
||||
.iter()
|
||||
.map(|k| x25519_dalek::PublicKey::from(k).to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
let node_ids = (0..3).map(|i| [i; NODE_ID_SIZE]).collect::<Vec<_>>();
|
||||
let payload = [7; 10];
|
||||
let message = MockMixMessage::build_message(&payload, &public_keys).unwrap();
|
||||
let message = MockMixMessage::build_message(&payload, &node_ids).unwrap();
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (message, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &private_keys[0].to_bytes()).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[0]).unwrap();
|
||||
assert!(!is_fully_unwrapped);
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (message, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &private_keys[1].to_bytes()).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[1]).unwrap();
|
||||
assert!(!is_fully_unwrapped);
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (unwrapped_payload, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &private_keys[2].to_bytes()).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[2]).unwrap();
|
||||
assert!(is_fully_unwrapped);
|
||||
assert_eq!(unwrapped_payload, payload);
|
||||
}
|
||||
|
@ -337,7 +337,9 @@ pub fn new_mix_configs(listening_addresses: Vec<Multiaddr>) -> Vec<TestMixSettin
|
||||
.iter()
|
||||
.map(|(backend, private_key)| Node {
|
||||
address: backend.listening_address.clone(),
|
||||
public_key: x25519_dalek::PublicKey::from(private_key).to_bytes(),
|
||||
// We use private key as a public key because the `MockMixMessage` doesn't differentiate between them.
|
||||
// TODO: Convert private key to public key properly once the real MixMessage is implemented.
|
||||
public_key: private_key.to_bytes(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -20,7 +20,6 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1", features = ["macros", "sync"] }
|
||||
tokio-stream = "0.1"
|
||||
tracing = "0.1"
|
||||
x25519-dalek = { version = "2", features = ["getrandom", "static_secrets"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -228,10 +228,9 @@ pub struct MixConfig<BackendSettings> {
|
||||
|
||||
impl<BackendSettings> MixConfig<BackendSettings> {
|
||||
fn membership(&self) -> Membership<MockMixMessage> {
|
||||
let public_key = x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::from(
|
||||
self.message_blend.cryptographic_processor.private_key,
|
||||
))
|
||||
.to_bytes();
|
||||
// We use private key as a public key because the `MockMixMessage` doesn't differentiate between them.
|
||||
// TODO: Convert private key to public key properly once the real MixMessage is implemented.
|
||||
let public_key = self.message_blend.cryptographic_processor.private_key;
|
||||
Membership::new(self.membership.clone(), public_key)
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,9 @@ fn mix_nodes(configs: &[GeneralMixConfig]) -> Vec<Node<<MockMixMessage as MixMes
|
||||
.iter()
|
||||
.map(|config| Node {
|
||||
address: config.backend.listening_address.clone(),
|
||||
public_key: x25519_dalek::PublicKey::from(&config.private_key).to_bytes(),
|
||||
// We use private key as a public key because the `MockMixMessage` doesn't differentiate between them.
|
||||
// TODO: Convert private key to public key properly once the real MixMessage is implemented.
|
||||
public_key: config.private_key.to_bytes(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user