converting peerIds and privekeys to montgomery for DH purposes

pull/19/head
Niko PLP 2 years ago
parent a27816ddb6
commit 149ddee013
  1. 3
      Cargo.lock
  2. 17
      ng-sdk-js/src/lib.rs
  3. 5
      ngcli/src/main.rs
  4. 1
      ngd/Cargo.toml
  5. 47
      ngd/src/main.rs
  6. 10
      p2p-broker/src/server_ws.rs
  7. 12
      p2p-client-ws/src/remote_ws.rs
  8. 2
      p2p-client-ws/src/remote_ws_wasm.rs
  9. 101
      p2p-net/src/broker.rs
  10. 38
      p2p-net/src/connection.rs
  11. 4
      p2p-net/src/errors.rs
  12. 66
      p2p-net/src/utils.rs
  13. 2
      p2p-repo/Cargo.toml
  14. 2
      p2p-repo/src/commit.rs
  15. 12
      p2p-repo/src/errors.rs
  16. 3
      p2p-repo/src/lib.rs
  17. 9
      p2p-repo/src/object.rs
  18. 54
      p2p-repo/src/types.rs
  19. 34
      p2p-repo/src/utils.rs

3
Cargo.lock generated

@ -2792,7 +2792,6 @@ dependencies = [
"serde_bare", "serde_bare",
"serde_bytes", "serde_bytes",
"serde_json", "serde_json",
"slice_as_array",
] ]
[[package]] [[package]]
@ -3057,6 +3056,7 @@ dependencies = [
"base64-url", "base64-url",
"blake3", "blake3",
"chacha20", "chacha20",
"curve25519-dalek 3.2.0",
"debug_print", "debug_print",
"ed25519-dalek", "ed25519-dalek",
"fastbloom-rs", "fastbloom-rs",
@ -3068,6 +3068,7 @@ dependencies = [
"serde", "serde",
"serde_bare", "serde_bare",
"serde_bytes", "serde_bytes",
"slice_as_array",
"wasm-bindgen", "wasm-bindgen",
"web-time", "web-time",
] ]

@ -22,7 +22,7 @@ use p2p_client_ws::remote_ws_wasm::ConnectionWebSocket;
use p2p_net::broker::*; use p2p_net::broker::*;
use p2p_net::connection::{ClientConfig, StartConfig}; use p2p_net::connection::{ClientConfig, StartConfig};
use p2p_net::types::{DirectPeerId, IP}; use p2p_net::types::{DirectPeerId, IP};
use p2p_net::utils::{spawn_and_log_error, Receiver, ResultSend, Sender}; use p2p_net::utils::{gen_ed_keys, spawn_and_log_error, Receiver, ResultSend, Sender};
use p2p_repo::log::*; use p2p_repo::log::*;
use p2p_repo::types::*; use p2p_repo::types::*;
use p2p_repo::utils::generate_keypair; use p2p_repo::utils::generate_keypair;
@ -207,13 +207,14 @@ pub async fn start() {
// getrandom::getrandom(&mut random_buf).unwrap(); // getrandom::getrandom(&mut random_buf).unwrap();
async fn inner_task() -> ResultSend<()> { async fn inner_task() -> ResultSend<()> {
let server_key = PubKey::Ed25519PubKey([ let server_key: PubKey = "KWdmwr4_oO62IFGfKzuyotQOixqXGNWv59CRAGvPTjM".try_into()?;
95, 155, 249, 202, 41, 105, 71, 51, 206, 126, 9, 84, 132, 92, 60, 7, 74, 179, 46, 21, log_debug!("server_key:{}", server_key);
21, 242, 171, 27, 249, 79, 76, 176, 168, 43, 83, 2,
]);
let keys = p2p_net::utils::gen_keys(); //let keys = p2p_net::utils::gen_dh_keys();
let pub_key = PubKey::Ed25519PubKey(keys.1); //let pub_key = PubKey::Ed25519PubKey(keys.1);
let keys = gen_ed_keys();
let x_from_ed = keys.1.to_dh_from_ed();
log_info!("Pub from X {}", x_from_ed);
let (client_priv_key, client_pub_key) = generate_keypair(); let (client_priv_key, client_pub_key) = generate_keypair();
let (user_priv_key, user_pub_key) = generate_keypair(); let (user_priv_key, user_pub_key) = generate_keypair();
@ -228,7 +229,7 @@ pub async fn start() {
IP::try_from(&IpAddr::from_str("127.0.0.1").unwrap()).unwrap(), IP::try_from(&IpAddr::from_str("127.0.0.1").unwrap()).unwrap(),
None, None,
keys.0, keys.0,
pub_key, keys.1,
server_key, server_key,
StartConfig::Client(ClientConfig { StartConfig::Client(ClientConfig {
user: user_pub_key, user: user_pub_key,

@ -599,13 +599,14 @@ mod test {
use async_std::task; use async_std::task;
use p2p_broker::server_ws::*; use p2p_broker::server_ws::*;
use p2p_net::utils::{gen_keys, Sensitive, U8Array}; use p2p_net::utils::{gen_dh_keys, Sensitive, U8Array};
use p2p_net::WS_PORT; use p2p_net::WS_PORT;
use p2p_repo::log::*;
use p2p_repo::types::PubKey; use p2p_repo::types::PubKey;
#[async_std::test] #[async_std::test]
pub async fn test_remote_cnx() -> Result<(), Box<dyn std::error::Error>> { pub async fn test_remote_cnx() -> Result<(), Box<dyn std::error::Error>> {
let keys = gen_keys(); let keys = gen_dh_keys();
// log_debug!("Public key of node: {:?}", keys.1); // log_debug!("Public key of node: {:?}", keys.1);
// log_debug!("Private key of node: {:?}", keys.0.as_slice()); // log_debug!("Private key of node: {:?}", keys.0.as_slice());
let pubkey = PubKey::Ed25519PubKey(keys.1); let pubkey = PubKey::Ed25519PubKey(keys.1);

@ -19,7 +19,6 @@ log = "0.4"
env_logger = "0.10" env_logger = "0.10"
clap = { version = "4.3.4", features = ["derive","env","string"] } clap = { version = "4.3.4", features = ["derive","env","string"] }
base64-url = "2.0.0" base64-url = "2.0.0"
slice_as_array = "1.1.0"
serde_json = "1.0" serde_json = "1.0"
regex = "1.8.4" regex = "1.8.4"
lazy_static = "1.4.0" lazy_static = "1.4.0"

@ -6,8 +6,6 @@
// at your option. All files in the project carrying such // at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
#[macro_use]
extern crate slice_as_array;
pub mod types; pub mod types;
@ -26,14 +24,14 @@ use p2p_net::utils::is_public_ip;
use p2p_net::utils::is_public_ipv4; use p2p_net::utils::is_public_ipv4;
use p2p_net::utils::is_public_ipv6; use p2p_net::utils::is_public_ipv6;
use p2p_net::utils::{ use p2p_net::utils::{
gen_keys, is_ipv4_global, is_ipv4_private, is_ipv6_global, is_ipv6_private, keys_from_bytes, gen_dh_keys, is_ipv4_global, is_ipv4_private, is_ipv6_global, is_ipv6_private, keypair_from_ed,
Dual25519Keys, Sensitive, U8Array, keys_from_bytes, Dual25519Keys, Sensitive, U8Array,
}; };
use p2p_net::{WS_PORT, WS_PORT_REVERSE_PROXY}; use p2p_net::{WS_PORT, WS_PORT_REVERSE_PROXY};
use p2p_repo::log::*; use p2p_repo::log::*;
use p2p_repo::{ use p2p_repo::{
types::{PrivKey, PubKey}, types::{PrivKey, PubKey},
utils::{generate_keypair, keypair_from_ed, sign, verify}, utils::{decode_key, generate_keypair, sign, verify},
}; };
use serde_json::{from_str, to_string_pretty}; use serde_json::{from_str, to_string_pretty};
use std::fs::{read_to_string, write}; use std::fs::{read_to_string, write};
@ -46,13 +44,6 @@ use addr::psl::List;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
fn decode_key(key_string: &String) -> Result<[u8; 32], ()> {
let vec = base64_url::decode(key_string).map_err(|_| log_err!("key has invalid content"))?;
Ok(*slice_as_array!(&vec, [u8; 32])
.ok_or(())
.map_err(|_| log_err!("key has invalid content array"))?)
}
//For windows: {846EE342-7039-11DE-9D20-806E6F6E6963} //For windows: {846EE342-7039-11DE-9D20-806E6F6E6963}
//For the other OSes: en0 lo ... //For the other OSes: en0 lo ...
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -384,7 +375,7 @@ async fn main_inner() -> Result<(), ()> {
log_err!("provided --key option will not be used as a key file is already present"); log_err!("provided --key option will not be used as a key file is already present");
gen_broker_keys(Some(key_from_file.unwrap())) gen_broker_keys(Some(key_from_file.unwrap()))
} else { } else {
let res = decode_key(key_string) let res = decode_key(key_string.as_str())
.map_err(|_| log_err!("provided key is invalid. cannot start"))?; .map_err(|_| log_err!("provided key is invalid. cannot start"))?;
if args.save_key { if args.save_key {
@ -853,13 +844,8 @@ async fn main_inner() -> Result<(), ()> {
); );
return Err(()); return Err(());
} }
let vec = base64_url::decode(parts[1]) let pub_key_array = decode_key(parts[1])
.map_err(|_| log_err!("The PEERID provided in the --forward option is invalid"))?; .map_err(|_| log_err!("The PEERID provided in the --forward option is invalid"))?;
let pub_key_array = *slice_as_array!(vec.as_slice(), [u8; 32])
.ok_or(())
.map_err(|_| {
log_err!("PEERID provided in the --forward option, has invalid array")
})?;
let peer_id = PubKey::Ed25519PubKey(pub_key_array); let peer_id = PubKey::Ed25519PubKey(pub_key_array);
let server_type = if parts[0].len() > 0 { let server_type = if parts[0].len() > 0 {
@ -944,7 +930,7 @@ async fn main_inner() -> Result<(), ()> {
// let pub_key = PubKey::Ed25519PubKey(keys.1); // let pub_key = PubKey::Ed25519PubKey(keys.1);
// let (ed_priv_key, ed_pub_key) = generate_keypair(); // let (ed_priv_key, ed_pub_key) = generate_keypair();
// let duals = Dual25519Keys::generate(); //let duals = Dual25519Keys::generate();
// let eds = keypair_from_ed(duals.ed25519_priv, duals.ed25519_pub); // let eds = keypair_from_ed(duals.ed25519_priv, duals.ed25519_pub);
// let test_vector: Vec<u8> = vec![71, 51, 206, 126, 9, 84, 132]; // let test_vector: Vec<u8> = vec![71, 51, 206, 126, 9, 84, 132];
// let sig = sign(eds.0, eds.1, &test_vector).unwrap(); // let sig = sign(eds.0, eds.1, &test_vector).unwrap();
@ -955,15 +941,22 @@ async fn main_inner() -> Result<(), ()> {
let (privkey, pubkey) = keys_from_bytes(keys[1]); let (privkey, pubkey) = keys_from_bytes(keys[1]);
let priv_key_array = *slice_as_array!(privkey.as_slice(), [u8; 32]) //let duals = Dual25519Keys::from_sensitive(privkey);
.ok_or(()) //let eds = keypair_from_ed(duals.ed25519_priv, duals.ed25519_pub);
.map_err(|_| log_err!("Private key of peer has invalid array"))?; //let xpriv = duals.x25519_priv;
let priv_key = PrivKey::Ed25519PrivKey(priv_key_array); //let xpub = PubKey::X25519PubKey(duals.x25519_public);
let priv_key_ser = serde_bare::to_vec(&priv_key).unwrap();
let prix_key_encoded = base64_url::encode(&priv_key_ser); // let priv_key: PrivKey = privkey
// .as_slice()
// .try_into()
// .map_err(|_| log_err!("Private key of peer has invalid array"))?;
log_info!("PeerId of node: {}", pubkey); log_info!("PeerId of node: {}", pubkey);
debug_println!("Private key of peer: {}", prix_key_encoded); //let privkey_: PrivKey = xpriv.to_owned().try_into().unwrap();
//debug_println!("Private key of peer: {}", privkey_.to_string());
//let x_from_ed = eds.1.to_dh_from_ed();
//log_info!("Pub from X {}", x_from_ed);
match config.unwrap() { match config.unwrap() {
DaemonConfig::V0(v0) => { DaemonConfig::V0(v0) => {

@ -517,7 +517,15 @@ pub async fn accept(tcp: TcpStream, peer_priv_key: Sensitive<[u8; 32]>) {
log_debug!("websocket accepted"); log_debug!("websocket accepted");
let cws = ConnectionWebSocket {}; let cws = ConnectionWebSocket {};
let base = cws.accept(peer_priv_key, ws.unwrap()).await.unwrap(); let base = cws
.accept(
remote_bind_address,
local_bind_address,
peer_priv_key,
ws.unwrap(),
)
.await
.unwrap();
let res = BROKER let res = BROKER
.write() .write()

@ -60,7 +60,7 @@ impl IConnect for ConnectionWebSocket {
Err(NetError::ConnectionError) Err(NetError::ConnectionError)
} }
Ok((mut websocket, _)) => { Ok((mut websocket, _)) => {
cnx.start_read_loop(peer_privk, Some(remote_peer)); cnx.start_read_loop(None, peer_privk, Some(remote_peer));
let s = cnx.take_sender(); let s = cnx.take_sender();
let r = cnx.take_receiver(); let r = cnx.take_receiver();
let mut shutdown = cnx.set_shutdown(); let mut shutdown = cnx.set_shutdown();
@ -90,12 +90,18 @@ impl IAccept for ConnectionWebSocket {
type Socket = WebSocketStream<TcpStream>; type Socket = WebSocketStream<TcpStream>;
async fn accept( async fn accept(
&self, &self,
remote_bind_address: BindAddress,
local_bind_address: BindAddress,
peer_privk: Sensitive<[u8; 32]>, peer_privk: Sensitive<[u8; 32]>,
socket: Self::Socket, socket: Self::Socket,
) -> Result<ConnectionBase, NetError> { ) -> Result<ConnectionBase, NetError> {
let mut cnx = ConnectionBase::new(ConnectionDir::Server, TransportProtocol::WS); let mut cnx = ConnectionBase::new(ConnectionDir::Server, TransportProtocol::WS);
cnx.start_read_loop(peer_privk, None); cnx.start_read_loop(
Some((local_bind_address, remote_bind_address)),
peer_privk,
None,
);
let s = cnx.take_sender(); let s = cnx.take_sender();
let r = cnx.take_receiver(); let r = cnx.take_receiver();
let mut shutdown = cnx.set_shutdown(); let mut shutdown = cnx.set_shutdown();
@ -272,7 +278,7 @@ mod test {
21, 242, 171, 27, 249, 79, 76, 176, 168, 43, 83, 2, 21, 242, 171, 27, 249, 79, 76, 176, 168, 43, 83, 2,
]); ]);
let keys = p2p_net::utils::gen_keys(); let keys = p2p_net::utils::gen_dh_keys();
let pub_key = PubKey::Ed25519PubKey(keys.1); let pub_key = PubKey::Ed25519PubKey(keys.1);
let (client_priv_key, client_pub_key) = generate_keypair(); let (client_priv_key, client_pub_key) = generate_keypair();

@ -51,7 +51,7 @@ impl IConnect for ConnectionWebSocket {
NetError::ConnectionError NetError::ConnectionError
})?; })?;
cnx.start_read_loop(peer_privk, Some(remote_peer)); cnx.start_read_loop(None, peer_privk, Some(remote_peer));
let mut shutdown = cnx.set_shutdown(); let mut shutdown = cnx.set_shutdown();
spawn_and_log_error(ws_loop( spawn_and_log_error(ws_loop(

@ -63,6 +63,7 @@ pub static BROKER: Lazy<Arc<RwLock<Broker>>> = Lazy::new(|| Arc::new(RwLock::new
pub struct Broker { pub struct Broker {
direct_connections: HashMap<IP, DirectConnection>, direct_connections: HashMap<IP, DirectConnection>,
peers: HashMap<DirectPeerId, BrokerPeerInfo>, peers: HashMap<DirectPeerId, BrokerPeerInfo>,
/// (local,remote) -> ConnectionBase
incoming_anonymous_connections: HashMap<(BindAddress, BindAddress), ConnectionBase>, incoming_anonymous_connections: HashMap<(BindAddress, BindAddress), ConnectionBase>,
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
listeners: HashMap<String, ListenerInfo>, listeners: HashMap<String, ListenerInfo>,
@ -338,7 +339,7 @@ impl Broker {
pub async fn accept( pub async fn accept(
&mut self, &mut self,
mut connection: ConnectionBase, connection: ConnectionBase,
remote_bind_address: BindAddress, remote_bind_address: BindAddress,
local_bind_address: BindAddress, local_bind_address: BindAddress,
) -> Result<(), NetError> { ) -> Result<(), NetError> {
@ -346,43 +347,67 @@ impl Broker {
return Err(NetError::Closing); return Err(NetError::Closing);
} }
//self.incoming_anonymous_connections if self
.incoming_anonymous_connections
// let join = connection.take_shutdown(); .insert((local_bind_address, remote_bind_address), connection)
.is_some()
// let connected = if core.is_some() { {
// let dc = DirectConnection { log_err!(
// ip, "internal error. duplicate connection {:?} {:?}",
// interface: core.clone().unwrap(), local_bind_address,
// remote_peer_id, remote_bind_address
// tp: connection.transport_protocol(), );
// cnx: connection, }
// }; Ok(())
// self.direct_connections.insert(ip, dc); }
// PeerConnection::Core(ip)
// } else { pub async fn attach_peer_id(
// PeerConnection::Client(connection) &mut self,
// }; remote_bind_address: BindAddress,
// let bpi = BrokerPeerInfo { local_bind_address: BindAddress,
// lastPeerAdvert: None, remote_peer_id: PubKey,
// connected, core: Option<String>,
// }; ) -> Result<(), NetError> {
// self.peers.insert(remote_peer_id, bpi); log_debug!("ATTACH PEER_ID {}", remote_peer_id);
let mut connection = self
// async fn watch_close( .incoming_anonymous_connections
// mut join: Receiver<NetError>, .remove(&(local_bind_address, remote_bind_address))
// remote_peer_id: DirectPeerId, .ok_or(NetError::InternalError)?;
// ) -> ResultSend<()> { let join = connection.take_shutdown();
// async move { let ip = remote_bind_address.ip;
// let res = join.next().await; let connected = if core.is_some() {
// log_info!("SOCKET IS CLOSED {:?} {:?}", res, &remote_peer_id); let dc = DirectConnection {
// log_info!("REMOVED"); ip,
// BROKER.write().await.remove(&remote_peer_id); interface: core.clone().unwrap(),
// } remote_peer_id,
// .await; tp: connection.transport_protocol(),
// Ok(()) cnx: connection,
// } };
// spawn_and_log_error(watch_close(join, remote_peer_id)); self.direct_connections.insert(ip, dc);
PeerConnection::Core(ip)
} else {
PeerConnection::Client(connection)
};
let bpi = BrokerPeerInfo {
lastPeerAdvert: None,
connected,
};
self.peers.insert(remote_peer_id, bpi);
async fn watch_close(
mut join: Receiver<NetError>,
remote_peer_id: DirectPeerId,
) -> ResultSend<()> {
async move {
let res = join.next().await;
log_info!("SOCKET IS CLOSED {:?} {:?}", res, &remote_peer_id);
log_info!("REMOVED");
BROKER.write().await.remove(&remote_peer_id);
}
.await;
Ok(())
}
spawn_and_log_error(watch_close(join, remote_peer_id));
Ok(()) Ok(())
} }

@ -17,6 +17,7 @@ use std::sync::Arc;
use crate::actor::{Actor, SoS}; use crate::actor::{Actor, SoS};
use crate::actors::*; use crate::actors::*;
use crate::broker::BROKER;
use crate::errors::NetError; use crate::errors::NetError;
use crate::errors::ProtocolError; use crate::errors::ProtocolError;
use crate::types::*; use crate::types::*;
@ -63,6 +64,8 @@ pub trait IAccept: Send + Sync {
type Socket; type Socket;
async fn accept( async fn accept(
&self, &self,
remote_bind_address: BindAddress,
local_bind_address: BindAddress,
peer_privk: Sensitive<[u8; 32]>, peer_privk: Sensitive<[u8; 32]>,
socket: Self::Socket, socket: Self::Socket,
) -> Result<ConnectionBase, NetError>; ) -> Result<ConnectionBase, NetError>;
@ -100,6 +103,8 @@ pub struct NoiseFSM {
dir: ConnectionDir, dir: ConnectionDir,
sender: Sender<ConnectionCommand>, sender: Sender<ConnectionCommand>,
bind_addresses: Option<(BindAddress, BindAddress)>,
actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>, actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>,
noise_handshake_state: Option<HandshakeState<X25519, ChaCha20Poly1305, Blake2b>>, noise_handshake_state: Option<HandshakeState<X25519, ChaCha20Poly1305, Blake2b>>,
@ -149,6 +154,7 @@ pub enum StartConfig {
impl NoiseFSM { impl NoiseFSM {
pub fn new( pub fn new(
bind_addresses: Option<(BindAddress, BindAddress)>,
tp: TransportProtocol, tp: TransportProtocol,
dir: ConnectionDir, dir: ConnectionDir,
actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>, actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>,
@ -163,6 +169,7 @@ impl NoiseFSM {
FSMstate::Noise0 FSMstate::Noise0
}, },
dir, dir,
bind_addresses,
actors, actors,
sender, sender,
noise_handshake_state: None, noise_handshake_state: None,
@ -276,9 +283,9 @@ impl NoiseFSM {
noise_xk(), noise_xk(),
true, true,
&[], &[],
Some(self.from.take().unwrap()), Some(from_ed_priv_to_dh_priv(self.from.take().unwrap())),
None, None,
Some(*self.to.unwrap().slice()), Some(*self.to.unwrap().to_dh_from_ed().slice()),
None, None,
); );
@ -304,7 +311,7 @@ impl NoiseFSM {
noise_xk(), noise_xk(),
false, false,
&[], &[],
Some(self.from.take().unwrap()), Some(from_ed_priv_to_dh_priv(self.from.take().unwrap())),
None, None,
None, None,
None, None,
@ -400,8 +407,21 @@ impl NoiseFSM {
if !handshake.completed() { if !handshake.completed() {
return Err(ProtocolError::NoiseHandshakeFailed); return Err(ProtocolError::NoiseHandshakeFailed);
} }
let peer_id = PubKey::Ed25519PubKey(handshake.get_rs().unwrap());
self.to = Some(PubKey::Ed25519PubKey(handshake.get_rs().unwrap())); self.to = Some(peer_id);
let (local_bind_address, remote_bind_address) =
self.bind_addresses.ok_or(ProtocolError::BrokerError)?;
BROKER
.write()
.await
.attach_peer_id(
remote_bind_address,
local_bind_address,
peer_id,
None,
)
.await
.map_err(|_| ProtocolError::BrokerError)?;
let ciphers = handshake.get_ciphers(); let ciphers = handshake.get_ciphers();
self.noise_cipher_state_enc = Some(ciphers.1); self.noise_cipher_state_enc = Some(ciphers.1);
@ -739,7 +759,12 @@ impl ConnectionBase {
} }
} }
pub fn start_read_loop(&mut self, from: Sensitive<[u8; 32]>, to: Option<PubKey>) { pub fn start_read_loop(
&mut self,
bind_addresses: Option<(BindAddress, BindAddress)>,
from: Sensitive<[u8; 32]>,
to: Option<PubKey>,
) {
let (sender_tx, sender_rx) = mpsc::unbounded(); let (sender_tx, sender_rx) = mpsc::unbounded();
let (receiver_tx, receiver_rx) = mpsc::unbounded(); let (receiver_tx, receiver_rx) = mpsc::unbounded();
self.sender = Some(sender_rx); self.sender = Some(sender_rx);
@ -748,6 +773,7 @@ impl ConnectionBase {
self.receiver_tx = Some(receiver_tx); self.receiver_tx = Some(receiver_tx);
let fsm = Arc::new(Mutex::new(NoiseFSM::new( let fsm = Arc::new(Mutex::new(NoiseFSM::new(
bind_addresses,
self.tp, self.tp,
self.dir.clone(), self.dir.clone(),
Arc::clone(&self.actors), Arc::clone(&self.actors),

@ -29,7 +29,8 @@ pub enum NetError {
ConnectionError, ConnectionError,
SerializationError, SerializationError,
ProtocolError, ProtocolError,
ConnectionDenied, AccessDenied,
InternalError,
Closing, Closing,
} //MAX 50 NetErrors } //MAX 50 NetErrors
@ -104,6 +105,7 @@ impl From<p2p_repo::errors::NgError> for ProtocolError {
match e { match e {
p2p_repo::errors::NgError::InvalidSignature => ProtocolError::InvalidSignature, p2p_repo::errors::NgError::InvalidSignature => ProtocolError::InvalidSignature,
p2p_repo::errors::NgError::SerializationError => ProtocolError::SerializationError, p2p_repo::errors::NgError::SerializationError => ProtocolError::SerializationError,
_ => ProtocolError::OtherError,
} }
} }
} }

@ -51,6 +51,15 @@ where
pub type Sender<T> = mpsc::UnboundedSender<T>; pub type Sender<T> = mpsc::UnboundedSender<T>;
pub type Receiver<T> = mpsc::UnboundedReceiver<T>; pub type Receiver<T> = mpsc::UnboundedReceiver<T>;
pub fn keypair_from_ed(secret: SecretKey, public: PublicKey) -> (Sensitive<[u8; 32]>, PubKey) {
let ed_priv_key = secret.to_bytes();
let ed_pub_key = public.to_bytes();
//let priv_key = PrivKey::Ed25519PrivKey(ed_priv_key);
let pub_key = PubKey::Ed25519PubKey(ed_pub_key);
let priv_key = Sensitive::<[u8; 32]>::from_slice(&ed_priv_key);
(priv_key, pub_key)
}
pub fn keys_from_bytes(secret_key: [u8; 32]) -> (Sensitive<[u8; 32]>, PubKey) { pub fn keys_from_bytes(secret_key: [u8; 32]) -> (Sensitive<[u8; 32]>, PubKey) {
let sk = SecretKey::from_bytes(&secret_key).unwrap(); let sk = SecretKey::from_bytes(&secret_key).unwrap();
let pk: PublicKey = (&sk).into(); let pk: PublicKey = (&sk).into();
@ -61,12 +70,23 @@ pub fn keys_from_bytes(secret_key: [u8; 32]) -> (Sensitive<[u8; 32]>, PubKey) {
(priv_key, pub_key) (priv_key, pub_key)
} }
pub fn gen_keys() -> (Sensitive<[u8; 32]>, [u8; 32]) { pub fn gen_dh_keys() -> (Sensitive<[u8; 32]>, [u8; 32]) {
let pri = noise_rust_crypto::X25519::genkey(); let pri = noise_rust_crypto::X25519::genkey();
let publ = noise_rust_crypto::X25519::pubkey(&pri); let publ = noise_rust_crypto::X25519::pubkey(&pri);
(pri, publ) (pri, publ)
} }
pub fn gen_ed_keys() -> (Sensitive<[u8; 32]>, PubKey) {
let mut ed25519_priv = Sensitive::<[u8; 32]>::new();
getrandom::getrandom(&mut *ed25519_priv).expect("getrandom failed");
//TODO FIXME do not create a SecretKey or call into() on it, as this is not using Sensitive<>
let secret = SecretKey::from_bytes(&ed25519_priv.as_slice()).unwrap();
let ed25519_pub: PublicKey = (&secret).into();
(ed25519_priv, PubKey::Ed25519PubKey(ed25519_pub.to_bytes()))
}
pub struct Dual25519Keys { pub struct Dual25519Keys {
pub x25519_priv: Sensitive<[u8; 32]>, pub x25519_priv: Sensitive<[u8; 32]>,
pub x25519_public: [u8; 32], pub x25519_public: [u8; 32],
@ -74,22 +94,56 @@ pub struct Dual25519Keys {
pub ed25519_pub: PublicKey, pub ed25519_pub: PublicKey,
} }
pub fn from_ed_priv_to_dh_priv(private: Sensitive<[u8; 32]>) -> Sensitive<[u8; 32]> {
let ed25519_priv = SecretKey::from_bytes(&private.as_slice()).unwrap();
let exp: ExpandedSecretKey = (&ed25519_priv).into();
let exp_bytes = exp.to_bytes();
let mut bits = Sensitive::<[u8; 32]>::from_slice(&exp_bytes[0..32]);
bits[0] &= 248;
bits[31] &= 127;
bits[31] |= 64;
bits
}
impl Dual25519Keys { impl Dual25519Keys {
pub fn generate() -> Self { pub fn generate() -> Self {
let mut x25519_priv = Sensitive::<[u8; 32]>::new(); let mut x25519_priv = Sensitive::<[u8; 32]>::new();
getrandom::getrandom(&mut *x25519_priv).expect("getrandom failed"); getrandom::getrandom(&mut *x25519_priv).expect("getrandom failed");
let ed25519_priv = SecretKey::from_bytes(&x25519_priv.as_slice()).unwrap(); let ed25519_priv = SecretKey::from_bytes(&x25519_priv.as_slice()).unwrap();
let exp: ExpandedSecretKey = (&ed25519_priv).into();
let exp_bytes = exp.to_bytes();
let ed25519_pub: PublicKey = (&ed25519_priv).into();
let mut bits = Sensitive::<[u8; 32]>::from_slice(&exp_bytes[0..32]);
bits[0] &= 248;
bits[31] &= 127;
bits[31] |= 64;
let x25519_public = noise_rust_crypto::X25519::pubkey(&bits);
Self {
x25519_priv: bits,
x25519_public,
ed25519_priv,
ed25519_pub,
}
}
pub fn from_sensitive(sensitive: Sensitive<[u8; 32]>) -> Self {
let ed25519_priv = SecretKey::from_bytes(&sensitive.as_slice()).unwrap();
let exp: ExpandedSecretKey = (&ed25519_priv).into();
let exp_bytes = exp.to_bytes();
let ed25519_pub: PublicKey = (&ed25519_priv).into(); let ed25519_pub: PublicKey = (&ed25519_priv).into();
x25519_priv[0] &= 248; let mut bits = Sensitive::<[u8; 32]>::from_slice(&exp_bytes[0..32]);
x25519_priv[31] &= 127; bits[0] &= 248;
x25519_priv[31] |= 64; bits[31] &= 127;
bits[31] |= 64;
let x25519_public = noise_rust_crypto::X25519::pubkey(&x25519_priv); let x25519_public = noise_rust_crypto::X25519::pubkey(&bits);
Self { Self {
x25519_priv, x25519_priv: bits,
x25519_public, x25519_public,
ed25519_priv, ed25519_priv,
ed25519_pub, ed25519_pub,

@ -25,6 +25,8 @@ futures = "0.3.24"
base64-url = "2.0.0" base64-url = "2.0.0"
web-time = "0.2.0" web-time = "0.2.0"
wasm-bindgen = "0.2" wasm-bindgen = "0.2"
slice_as_array = "1.1.0"
curve25519-dalek = "3.2.0"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
debug_print = "1.0.0" debug_print = "1.0.0"

@ -82,6 +82,7 @@ impl CommitV0 {
// sign commit // sign commit
let kp = match (author_privkey, author_pubkey) { let kp = match (author_privkey, author_pubkey) {
(PrivKey::Ed25519PrivKey(sk), PubKey::Ed25519PubKey(pk)) => [sk, pk].concat(), (PrivKey::Ed25519PrivKey(sk), PubKey::Ed25519PubKey(pk)) => [sk, pk].concat(),
(_, _) => panic!("cannot sign with Montgomery key"),
}; };
let keypair = Keypair::from_bytes(kp.as_slice())?; let keypair = Keypair::from_bytes(kp.as_slice())?;
let sig_bytes = keypair.sign(content_ser.as_slice()).to_bytes(); let sig_bytes = keypair.sign(content_ser.as_slice()).to_bytes();
@ -246,6 +247,7 @@ impl Commit {
let content_ser = serde_bare::to_vec(&c.content).unwrap(); let content_ser = serde_bare::to_vec(&c.content).unwrap();
let pubkey = match c.content.author { let pubkey = match c.content.author {
PubKey::Ed25519PubKey(pk) => pk, PubKey::Ed25519PubKey(pk) => pk,
_ => panic!("author cannot have a Montgomery key"),
}; };
let pk = PublicKey::from_bytes(&pubkey)?; let pk = PublicKey::from_bytes(&pubkey)?;
let sig_bytes = match c.sig { let sig_bytes = match c.sig {

@ -11,11 +11,23 @@
//! Errors //! Errors
use core::fmt;
use std::error::Error;
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
#[repr(u16)] #[repr(u16)]
pub enum NgError { pub enum NgError {
InvalidSignature, InvalidSignature,
SerializationError, SerializationError,
InvalidKey,
}
impl Error for NgError {}
impl fmt::Display for NgError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
} }
impl From<serde_bare::error::Error> for NgError { impl From<serde_bare::error::Error> for NgError {

@ -20,6 +20,9 @@ pub mod kcv_store;
pub mod site; pub mod site;
#[macro_use]
extern crate slice_as_array;
pub mod log { pub mod log {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]

@ -80,6 +80,7 @@ impl Object {
(PubKey::Ed25519PubKey(pubkey), SymKey::ChaCha20Key(secret)) => { (PubKey::Ed25519PubKey(pubkey), SymKey::ChaCha20Key(secret)) => {
[pubkey, secret].concat() [pubkey, secret].concat()
} }
(_, _) => panic!("cannot sign with Montgomery key"),
}; };
blake3::derive_key("NextGraph Data BLAKE3 key", key_material.as_slice()) blake3::derive_key("NextGraph Data BLAKE3 key", key_material.as_slice())
} }
@ -575,6 +576,14 @@ mod test {
/// Maximum data that can fit in object.content /// Maximum data that can fit in object.content
const MAX_DATA_PAYLOAD_SIZE: usize = 2097112; const MAX_DATA_PAYLOAD_SIZE: usize = 2097112;
#[test]
pub fn test_pubkey_from_str() {
let pubkey = PubKey::Ed25519PubKey([1u8; 32]);
let str = pubkey.to_string();
let server_key: PubKey = str.as_str().try_into().unwrap();
assert_eq!(server_key, pubkey);
}
/// Test JPEG file /// Test JPEG file
#[test] #[test]
pub fn test_jpg() { pub fn test_jpg() {

@ -13,6 +13,8 @@
//! //!
//! Corresponds to the BARE schema //! Corresponds to the BARE schema
use crate::errors::NgError;
use crate::utils::{decode_key, dh_pubkey_from_ed_slice};
use core::fmt; use core::fmt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_bare::to_vec; use serde_bare::to_vec;
@ -61,7 +63,7 @@ impl SymKey {
pub type Ed25519PubKey = [u8; 32]; pub type Ed25519PubKey = [u8; 32];
/// Curve25519 public key Montgomery form /// Curve25519 public key Montgomery form
pub type Mo25519PubKey = [u8; 32]; pub type X25519PubKey = [u8; 32];
/// Curve25519 private key /// Curve25519 private key
pub type Ed25519PrivKey = [u8; 32]; pub type Ed25519PrivKey = [u8; 32];
@ -70,24 +72,46 @@ pub type Ed25519PrivKey = [u8; 32];
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum PubKey { pub enum PubKey {
Ed25519PubKey(Ed25519PubKey), Ed25519PubKey(Ed25519PubKey),
X25519PubKey(X25519PubKey),
} }
impl PubKey { impl PubKey {
pub fn slice(&self) -> &[u8; 32] { pub fn slice(&self) -> &[u8; 32] {
match self { match self {
PubKey::Ed25519PubKey(o) => o, PubKey::Ed25519PubKey(o) | PubKey::X25519PubKey(o) => o,
} }
} }
pub fn to_dh_from_ed(&self) -> PubKey {
match self {
PubKey::Ed25519PubKey(ed) => dh_pubkey_from_ed_slice(ed),
_ => panic!(
"cannot convert a Montgomery key to Montgomery. it is already one. check your code"
),
}
}
pub fn dh_from_ed_slice(slice: &[u8]) -> PubKey {
dh_pubkey_from_ed_slice(slice)
}
} }
impl fmt::Display for PubKey { impl fmt::Display for PubKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
PubKey::Ed25519PubKey(d) => write!(f, "{}", base64_url::encode(d)), PubKey::Ed25519PubKey(d) | PubKey::X25519PubKey(d) => {
write!(f, "{}", base64_url::encode(d))
}
} }
} }
} }
impl TryFrom<&str> for PubKey {
type Error = NgError;
fn try_from(str: &str) -> Result<Self, NgError> {
let key = decode_key(str).map_err(|_| NgError::InvalidKey)?;
Ok(PubKey::Ed25519PubKey(key))
}
}
/// Private key /// Private key
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum PrivKey { pub enum PrivKey {
@ -102,6 +126,30 @@ impl PrivKey {
} }
} }
impl From<[u8; 32]> for PrivKey {
fn from(buf: [u8; 32]) -> Self {
let priv_key = PrivKey::Ed25519PrivKey(buf);
priv_key
}
}
impl TryFrom<&[u8]> for PrivKey {
type Error = NgError;
fn try_from(buf: &[u8]) -> Result<Self, NgError> {
let priv_key_array = *slice_as_array!(buf, [u8; 32]).ok_or(NgError::InvalidKey)?;
let priv_key = PrivKey::Ed25519PrivKey(priv_key_array);
Ok(priv_key)
}
}
impl fmt::Display for PrivKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let priv_key_ser = serde_bare::to_vec(self).unwrap();
let prix_key_encoded = base64_url::encode(&priv_key_ser);
write!(f, "{}", prix_key_encoded)
}
}
/// Ed25519 signature /// Ed25519 signature
pub type Ed25519Sig = [[u8; 32]; 2]; pub type Ed25519Sig = [[u8; 32]; 2];

@ -10,13 +10,22 @@
// according to those terms. // according to those terms.
use crate::errors::*; use crate::errors::*;
use crate::log::*;
use crate::types::*; use crate::types::*;
use curve25519_dalek::edwards::{CompressedEdwardsY, EdwardsPoint};
use ed25519_dalek::*; use ed25519_dalek::*;
use futures::channel::mpsc; use futures::channel::mpsc;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use web_time::{SystemTime, UNIX_EPOCH}; use web_time::{SystemTime, UNIX_EPOCH};
pub fn decode_key(key_string: &str) -> Result<[u8; 32], ()> {
let vec = base64_url::decode(key_string).map_err(|_| log_err!("key has invalid content"))?;
Ok(*slice_as_array!(&vec, [u8; 32])
.ok_or(())
.map_err(|_| log_err!("key has invalid content array"))?)
}
pub fn generate_null_keypair() -> (PrivKey, PubKey) { pub fn generate_null_keypair() -> (PrivKey, PubKey) {
let master_key: [u8; 32] = [0; 32]; let master_key: [u8; 32] = [0; 32];
let sk = SecretKey::from_bytes(&master_key).unwrap(); let sk = SecretKey::from_bytes(&master_key).unwrap();
@ -44,22 +53,13 @@ pub fn generate_null_keypair() -> (PrivKey, PubKey) {
(priv_key, pub_key) (priv_key, pub_key)
} }
pub fn keypair_from_ed(secret: SecretKey, public: PublicKey) -> (PrivKey, PubKey) { pub fn dh_pubkey_from_ed_slice(public: &[u8]) -> PubKey {
// log_debug!( let mut bits: [u8; 32] = [0u8; 32];
// "private key: ({}) {:?}", bits.copy_from_slice(public);
// keypair.secret.as_bytes().len(), let compressed = CompressedEdwardsY(bits);
// keypair.secret.as_bytes() let ed_point: EdwardsPoint = compressed.decompress().unwrap();
// ); let mon_point = ed_point.to_montgomery();
// log_debug!( PubKey::X25519PubKey(mon_point.to_bytes())
// "public key: ({}) {:?}",
// keypair.public.as_bytes().len(),
// keypair.public.as_bytes()
// );
let ed_priv_key = secret.to_bytes();
let ed_pub_key = public.to_bytes();
let priv_key = PrivKey::Ed25519PrivKey(ed_priv_key);
let pub_key = PubKey::Ed25519PubKey(ed_pub_key);
(priv_key, pub_key)
} }
pub fn sign( pub fn sign(
@ -69,6 +69,7 @@ pub fn sign(
) -> Result<Sig, NgError> { ) -> Result<Sig, NgError> {
let kp = match (author_privkey, author_pubkey) { let kp = match (author_privkey, author_pubkey) {
(PrivKey::Ed25519PrivKey(sk), PubKey::Ed25519PubKey(pk)) => [sk, pk].concat(), (PrivKey::Ed25519PrivKey(sk), PubKey::Ed25519PubKey(pk)) => [sk, pk].concat(),
(_, _) => panic!("cannot sign with Montgomery keys"),
}; };
let keypair = Keypair::from_bytes(kp.as_slice())?; let keypair = Keypair::from_bytes(kp.as_slice())?;
let sig_bytes = keypair.sign(content.as_slice()).to_bytes(); let sig_bytes = keypair.sign(content.as_slice()).to_bytes();
@ -82,6 +83,7 @@ pub fn sign(
pub fn verify(content: &Vec<u8>, sig: Sig, pub_key: PubKey) -> Result<(), NgError> { pub fn verify(content: &Vec<u8>, sig: Sig, pub_key: PubKey) -> Result<(), NgError> {
let pubkey = match pub_key { let pubkey = match pub_key {
PubKey::Ed25519PubKey(pk) => pk, PubKey::Ed25519PubKey(pk) => pk,
_ => panic!("cannot verify with Montgomery keys"),
}; };
let pk = PublicKey::from_bytes(&pubkey)?; let pk = PublicKey::from_bytes(&pubkey)?;
let sig_bytes = match sig { let sig_bytes = match sig {

Loading…
Cancel
Save