Examples + Fixing up Auth Interface to consume Connection
This commit is contained in:
parent
96ae0b1352
commit
d41663a3fe
|
@ -29,4 +29,5 @@ byteorder = "1.3.4"
|
|||
socks = "0.3.3"
|
||||
integer-encoding = "2.1.1"
|
||||
secretbox = "0.1.2"
|
||||
subtle = "2.3.0"
|
||||
subtle = "2.3.0"
|
||||
hashbrown = "0.9.1"
|
|
@ -0,0 +1,48 @@
|
|||
use tapir::acns::tor::authentication::HashedPassword;
|
||||
use ed25519_dalek::SecretKey;
|
||||
use tapir::primitives::identity::Identity;
|
||||
use tapir::connections::{OutboundConnection, Connection, InboundConnection, ConnectionInterface};
|
||||
use tapir::primitives::transcript::Transcript;
|
||||
use tapir::applications::authentication_app::{AuthenicationApp, AuthenticationCapability};
|
||||
use tapir::connections::service::Service;
|
||||
use rand::rngs::OsRng;
|
||||
use tapir::acns::tor::TorProcess;
|
||||
|
||||
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 mut service = Service::init(identity.clone());
|
||||
|
||||
let identity = identity.clone();
|
||||
let outbound_identity = identity.clone();
|
||||
let outbound_service = |mut conn: Connection<OutboundConnection>| {
|
||||
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(&AuthenticationCapability));
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
}
|
||||
}
|
||||
};
|
||||
match service.connect("lzry2bfjkdzlx64aksxw5jpz6qdnvjoekpkzjqclpd4wz25dbv2pasid", outbound_service.clone()) {
|
||||
_ => {}
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
Err(err) => println!("{:?}", err),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
use tapir::acns::tor::authentication::HashedPassword;
|
||||
use ed25519_dalek::SecretKey;
|
||||
use tapir::primitives::identity::Identity;
|
||||
use tapir::connections::{OutboundConnection, Connection, InboundConnection, ConnectionInterface};
|
||||
use tapir::primitives::transcript::Transcript;
|
||||
use tapir::applications::authentication_app::AuthenicationApp;
|
||||
use tapir::connections::service::Service;
|
||||
use rand::rngs::OsRng;
|
||||
use tapir::acns::tor::TorProcess;
|
||||
|
||||
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 service = Service::init(identity.clone());
|
||||
|
||||
let identity = identity.clone();
|
||||
let inbound_service = |mut conn: Connection<InboundConnection>| {
|
||||
let mut transcript = Transcript::new_transcript("tapir-transcript");
|
||||
let mut auth_app = AuthenicationApp::new(identity);
|
||||
match auth_app.run_inbound(conn, &mut transcript) {
|
||||
Ok(conn) => {
|
||||
println!("Authenticated Inbound Connection from {}", conn.hostname())
|
||||
}
|
||||
_ => {
|
||||
println!("Failed Inbound Authentication")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut service = service.listen(10029, inbound_service.clone()).unwrap_or_else(|_| panic!());
|
||||
|
||||
loop {}
|
||||
}
|
||||
Err(err) => println!("{:?}", err),
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use crate::applications::authentication_app::AuthenticationAppError::NotAuthenticatedError;
|
||||
use crate::connections::utils::public_key_to_hostname;
|
||||
use crate::connections::{Connection, ConnectionInterface, InboundConnection, OutboundConnection};
|
||||
use crate::connections::{Connection, ConnectionInterface, InboundConnection, OutboundConnection, Capability};
|
||||
use crate::primitives::identity::Identity;
|
||||
use crate::primitives::transcript::Transcript;
|
||||
use ed25519_dalek::PublicKey;
|
||||
|
@ -8,7 +8,6 @@ use integer_encoding::VarInt;
|
|||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use sha3::Digest;
|
||||
use std::io::Error;
|
||||
use std::sync::Arc;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
|
@ -21,6 +20,8 @@ pub enum AuthenticationAppError {
|
|||
NotAuthenticatedError,
|
||||
}
|
||||
|
||||
pub const AuthenticationCapability : Capability = Capability("AuthenticationCapability");
|
||||
|
||||
struct AuthenticationSession<Direction> {
|
||||
long_term_identity: Arc<Identity>,
|
||||
ephemeral_identity: Identity,
|
||||
|
@ -35,7 +36,7 @@ struct AuthenticationSession<Direction> {
|
|||
conn: Connection<Direction>,
|
||||
}
|
||||
|
||||
impl<Direction> AuthenticationSession<Direction> {
|
||||
impl<Direction> AuthenticationSession<Direction> where Direction:Clone {
|
||||
pub fn new_outbound(mut conn: Connection<OutboundConnection>, long_term_identity: Arc<Identity>) -> AuthenticationSession<OutboundConnection> {
|
||||
let ephemeral_identity = Identity::initialize_ephemeral_identity();
|
||||
let mut auth_session = AuthenticationSession {
|
||||
|
@ -96,7 +97,7 @@ impl<Direction> AuthenticationSession<Direction> {
|
|||
}
|
||||
|
||||
/// check the challenge from the remote
|
||||
fn check_remote_challenge(&mut self) -> Result<(), AuthenticationAppError> {
|
||||
fn check_remote_challenge(&mut self) -> Result<Connection<Direction>, AuthenticationAppError> {
|
||||
match self.conn.send_encrypted(self.generate_challenge_message()) {
|
||||
Ok(()) => {
|
||||
let remote_challenge = self.conn.expect_encrypted();
|
||||
|
@ -104,7 +105,9 @@ impl<Direction> AuthenticationSession<Direction> {
|
|||
cmp_challenge.extend_from_slice(self.challenge.as_slice());
|
||||
cmp_challenge.extend_from_slice(public_key_to_hostname(&self.remote_long_term_identity).as_bytes());
|
||||
if remote_challenge.ct_eq(cmp_challenge.as_slice()).unwrap_u8() == 1 {
|
||||
return Ok(());
|
||||
self.conn.set_hostname(&public_key_to_hostname(&self.remote_long_term_identity));
|
||||
self.conn.set_capability(&AuthenticationCapability);
|
||||
return Ok(self.conn.try_clone());
|
||||
}
|
||||
self.conn.shutdown();
|
||||
Err(NotAuthenticatedError)
|
||||
|
@ -115,7 +118,7 @@ impl<Direction> AuthenticationSession<Direction> {
|
|||
}
|
||||
|
||||
impl AuthenticationSession<OutboundConnection> {
|
||||
pub fn generate_challenge(&mut self, transcript: &mut Transcript) -> Result<(), AuthenticationAppError> {
|
||||
pub fn generate_challenge(&mut self, transcript: &mut Transcript) -> Result<Connection<OutboundConnection>, AuthenticationAppError> {
|
||||
let l2e = self.long_term_identity.edh(self.remote_ephemeral_identity);
|
||||
let e2l = self.ephemeral_identity.edh(self.remote_long_term_identity);
|
||||
let e2e = self.ephemeral_identity.edh(self.remote_ephemeral_identity);
|
||||
|
@ -140,7 +143,7 @@ impl AuthenticationSession<OutboundConnection> {
|
|||
}
|
||||
|
||||
impl AuthenticationSession<InboundConnection> {
|
||||
pub fn generate_challenge(&mut self, transcript: &mut Transcript) -> Result<(), AuthenticationAppError> {
|
||||
pub fn generate_challenge(&mut self, transcript: &mut Transcript) -> Result<Connection<InboundConnection>, AuthenticationAppError> {
|
||||
let l2e = self.long_term_identity.edh(self.remote_ephemeral_identity);
|
||||
let e2l = self.ephemeral_identity.edh(self.remote_long_term_identity);
|
||||
let e2e = self.ephemeral_identity.edh(self.remote_ephemeral_identity);
|
||||
|
@ -177,13 +180,13 @@ impl AuthenicationApp {
|
|||
AuthenicationApp { identity }
|
||||
}
|
||||
|
||||
pub fn run_outbound(&mut self, conn: &mut Connection<OutboundConnection>, transcript: &mut Transcript) -> Result<(), AuthenticationAppError> {
|
||||
let mut auth_session = AuthenticationSession::<OutboundConnection>::new_outbound(conn.try_clone(), self.identity.clone());
|
||||
pub fn run_outbound(&mut self, conn: Connection<OutboundConnection>, transcript: &mut Transcript) -> Result<Connection<OutboundConnection>, AuthenticationAppError> {
|
||||
let mut auth_session = AuthenticationSession::<OutboundConnection>::new_outbound(conn, self.identity.clone());
|
||||
auth_session.generate_challenge(transcript)
|
||||
}
|
||||
|
||||
pub fn run_inbound(&mut self, conn: &mut Connection<InboundConnection>, transcript: &mut Transcript) -> Result<(), AuthenticationAppError> {
|
||||
let mut auth_session = AuthenticationSession::<InboundConnection>::new_inbound(conn.try_clone(), self.identity.clone());
|
||||
pub fn run_inbound(&mut self, conn: Connection<InboundConnection>, transcript: &mut Transcript) -> Result<Connection<InboundConnection>, AuthenticationAppError> {
|
||||
let mut auth_session = AuthenticationSession::<InboundConnection>::new_inbound(conn, self.identity.clone());
|
||||
auth_session.generate_challenge(transcript)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use secretbox::CipherType::Salsa20;
|
|||
use secretbox::SecretBox;
|
||||
use std::io::{Error, Read, Write};
|
||||
use std::net::{Shutdown, TcpStream};
|
||||
use hashbrown::HashSet;
|
||||
|
||||
/// Connections provides an interface for manage sets of connections on top of a particular
|
||||
/// ACN.
|
||||
|
@ -21,22 +22,41 @@ pub struct InboundConnection(());
|
|||
#[derive(Clone)]
|
||||
pub struct OutboundConnection(());
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Capability(pub &'static str);
|
||||
|
||||
|
||||
pub struct Connection<Direction> {
|
||||
conn: TcpStream,
|
||||
direction: Direction,
|
||||
key: Vec<u8>,
|
||||
hostname: String,
|
||||
capabilities: HashSet<Capability>
|
||||
}
|
||||
|
||||
pub trait ConnectionInterface {
|
||||
fn set_hostname(&mut self, hostname: &String);
|
||||
fn hostname(&self) -> String;
|
||||
fn enable_encryption(&mut self, key: Vec<u8>);
|
||||
fn send(&mut self, amsg: &String) -> Result<(), Error>;
|
||||
fn send_encrypted(&mut self, msg: Vec<u8>) -> Result<(), Error>;
|
||||
fn expect_encrypted(&mut self) -> Vec<u8>;
|
||||
fn expect(&mut self) -> Result<Vec<u8>, Error>;
|
||||
fn shutdown(&mut self);
|
||||
|
||||
fn set_capability(&mut self, capability: &Capability);
|
||||
fn has_capability(&self, capability: &Capability) -> bool;
|
||||
}
|
||||
|
||||
impl<Direction> ConnectionInterface for Connection<Direction> {
|
||||
fn set_hostname(&mut self, hostname: &String) {
|
||||
self.hostname = hostname.clone()
|
||||
}
|
||||
|
||||
fn hostname(&self) -> String {
|
||||
self.hostname.clone()
|
||||
}
|
||||
|
||||
fn enable_encryption(&mut self, key: Vec<u8>) {
|
||||
self.key = key
|
||||
}
|
||||
|
@ -111,6 +131,14 @@ impl<Direction> ConnectionInterface for Connection<Direction> {
|
|||
_ => {} // If anything bad happens we will know soon enough...
|
||||
}
|
||||
}
|
||||
|
||||
fn set_capability(&mut self, capability: &Capability) {
|
||||
self.capabilities.insert(capability.clone());
|
||||
}
|
||||
|
||||
fn has_capability(&self, capability: &Capability) -> bool {
|
||||
self.capabilities.contains(capability)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Direction> Connection<Direction>
|
||||
|
@ -122,6 +150,8 @@ where
|
|||
conn,
|
||||
direction: InboundConnection(()),
|
||||
key: vec![],
|
||||
hostname: String::new(),
|
||||
capabilities: HashSet::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +160,8 @@ where
|
|||
conn,
|
||||
direction: OutboundConnection(()),
|
||||
key: vec![],
|
||||
hostname: String::new(),
|
||||
capabilities: HashSet::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +170,8 @@ where
|
|||
conn: self.conn.try_clone().unwrap(),
|
||||
direction: self.direction.clone(),
|
||||
key: self.key.clone(),
|
||||
hostname: self.hostname.clone(),
|
||||
capabilities: self.capabilities.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue