diff --git a/Cargo.toml b/Cargo.toml index b9bce2a..7a88619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tapir-cwtch" -version = "0.1.2" +version = "0.1.3" authors = ["Sarah Jamie Lewis "] edition = "2018" license = "MIT" @@ -8,6 +8,9 @@ description = "Tapir is a small library for building p2p applications over anony repository = "https://git.openprivacy.ca/sarah/tapir-rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +onionv3 = [] + [[test]] name = "simple_setup" diff --git a/examples/simple_client.rs b/examples/simple_client.rs index a155527..697da51 100644 --- a/examples/simple_client.rs +++ b/examples/simple_client.rs @@ -1,48 +1,31 @@ -use ed25519_dalek::SecretKey; -use rand::rngs::OsRng; -use tapir_cwtch::acns::tor::authentication::HashedPassword; -use tapir_cwtch::acns::tor::TorProcess; use tapir_cwtch::applications::authentication_app::{AuthenicationApp, AUTHENTICATION_CAPABILITY}; use tapir_cwtch::connections::service::Service; use tapir_cwtch::connections::{Connection, ConnectionInterface, OutboundConnection}; use tapir_cwtch::primitives::identity::Identity; use tapir_cwtch::primitives::transcript::Transcript; +use std::sync::Arc; fn main() { - let mut auth_control_port = TorProcess::connect(9051) - .unwrap() - .authenticate(Box::new(HashedPassword::new(String::from("examplehashedpassword")))) - .unwrap(); - let mut csprng = OsRng {}; - let keypair = ed25519_dalek::Keypair::generate(&mut csprng); - match auth_control_port.add_onion_v3(SecretKey::from_bytes(&keypair.secret.to_bytes()).unwrap(), 9878, 10029) { - Ok(service_id) => { - // we authenticated! - let identity = Identity::initialize(keypair); - println!("Service Id: {}", service_id); - println!("Setup: {}", identity.hostname()); + let identity = Arc::new(Identity::initialize_ephemeral_identity()); + println!("Setup: {}", identity.hostname()); - let mut service = Service::init(identity.clone()); - - let identity = identity.clone(); - let outbound_identity = identity.clone(); - let outbound_service = |conn: Connection| { - let mut transcript = Transcript::new_transcript("tapir-transcript"); - let mut auth_app = AuthenicationApp::new(outbound_identity); - match auth_app.run_outbound(conn, &mut transcript) { - Ok(conn) => { - println!("Authenticated {} {}", conn.hostname(), conn.has_capability(&AUTHENTICATION_CAPABILITY)); - } - Err(err) => { - println!("Error: {:?}", err); - } - } - }; - match service.connect("hvdl5hckss4od2bn7zm2ho6ybak3heopfvxkbx6li3yl7avzc52aluid", outbound_service.clone()) { - _ => {} + let mut service = Service::init(identity.clone()); + let identity = identity.clone(); + let outbound_identity = identity.clone(); + let outbound_service = |conn: Connection| { + let mut transcript = Transcript::new_transcript("tapir-transcript"); + let mut auth_app = AuthenicationApp::new(outbound_identity); + match auth_app.run_outbound(conn, &mut transcript) { + Ok(conn) => { + println!("Authenticated {} {}", conn.hostname(), conn.has_capability(&AUTHENTICATION_CAPABILITY)); + } + Err(err) => { + println!("Error: {:?}", err); } - loop {} } - Err(err) => println!("{:?}", err), + }; + match service.connect("kaouzo6mkagk5vin663iqq4d2jctkkoh62avglamheohgdz5y7gu7eyd", outbound_service.clone()) { + _ => {} } + loop {} } diff --git a/examples/simple_server.rs b/examples/simple_server.rs index 67d9654..d56c51b 100644 --- a/examples/simple_server.rs +++ b/examples/simple_server.rs @@ -1,5 +1,4 @@ -use ed25519_dalek::SecretKey; -use rand::rngs::OsRng; + use tapir_cwtch::acns::tor::authentication::HashedPassword; use tapir_cwtch::acns::tor::TorProcess; use tapir_cwtch::applications::authentication_app::AuthenicationApp; @@ -7,24 +6,24 @@ use tapir_cwtch::connections::service::Service; use tapir_cwtch::connections::{Connection, ConnectionInterface, InboundConnection}; use tapir_cwtch::primitives::identity::Identity; use tapir_cwtch::primitives::transcript::Transcript; +use std::sync::Arc; fn main() { let mut auth_control_port = TorProcess::connect(9051) .unwrap() .authenticate(Box::new(HashedPassword::new(String::from("examplehashedpassword")))) .unwrap(); - let mut csprng = OsRng {}; - let keypair = ed25519_dalek::Keypair::generate(&mut csprng); - match auth_control_port.add_onion_v3(SecretKey::from_bytes(&keypair.secret.to_bytes()).unwrap(), 9878, 10029) { + let identity = Arc::new(Identity::initialize_ephemeral_identity()); + match identity.host_onion_service(&mut auth_control_port, 9878, 10029) { Ok(service_id) => { // we authenticated! - let identity = Identity::initialize(keypair); + println!("Service Id: {}", service_id); println!("Setup: {}", identity.hostname()); let service = Service::init(identity.clone()); - let identity = identity.clone(); + let inbound_service = |conn: Connection| { let mut transcript = Transcript::new_transcript("tapir-transcript"); let mut auth_app = AuthenicationApp::new(identity); diff --git a/src/primitives/identity.rs b/src/primitives/identity.rs index bb7158d..ad4e48f 100644 --- a/src/primitives/identity.rs +++ b/src/primitives/identity.rs @@ -1,3 +1,4 @@ + use crate::connections::utils::public_key_to_hostname; use ed25519_dalek::{ExpandedSecretKey, Keypair, PublicKey}; use rand::rngs::OsRng; @@ -7,6 +8,13 @@ use std::sync::Arc; use x25519_dalek::PublicKey as X25519PublicKey; use x25519_dalek::{SharedSecret, StaticSecret}; +#[cfg(any(feature = "onionv3"))] +use crate::acns::tor::{TorAuthenticated, TorProcess}; +#[cfg(any(feature = "onionv3"))] +use crate::acns::ACNError; +#[cfg(any(feature = "onionv3"))] +use ed25519_dalek::{SecretKey}; + #[derive(Serialize, Deserialize, Debug)] /// Identity - An ed25519 keypair, required for established a Tor v3 onion service and used to /// maintain a consistent cryptographic identity for a peer. @@ -14,6 +22,7 @@ pub struct Identity { keypair: Keypair, } + impl Identity { /// Initialize a persistent identity pub fn initialize(keypair: Keypair) -> Arc { @@ -55,6 +64,12 @@ impl Identity { let edwards = curve25519_dalek::edwards::CompressedEdwardsY::from_slice(edwards_pub_key.to_bytes().as_slice()); X25519PublicKey::from(edwards.decompress().unwrap().to_montgomery().to_bytes()) } + + /// helper function to authenticated safely to a Tor control port to host an onion service for this identity + #[cfg(any(feature = "onionv3"))] + pub fn host_onion_service(&self, authenticated_control_port: &mut TorProcess, virtual_port: u16, target_port: u16) -> Result { + authenticated_control_port.add_onion_v3(SecretKey::from_bytes(&self.keypair.secret.to_bytes()).unwrap(), virtual_port, target_port) + } } #[cfg(test)]