From 1e35d625d35ec55f5f3f8f6e014f1ce4c4954dcd Mon Sep 17 00:00:00 2001 From: Vecna Date: Sun, 26 Mar 2023 13:00:30 -0400 Subject: [PATCH] Improve trust migration/level up handling --- src/bin/lox_client.rs | 10 +++++++- src/client_lib.rs | 57 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/bin/lox_client.rs b/src/bin/lox_client.rs index be9fb00..eb7e8e3 100644 --- a/src/bin/lox_client.rs +++ b/src/bin/lox_client.rs @@ -99,8 +99,10 @@ async fn main() { }; let lox_cred = if matches.opt_present("L") { + let old_level = get_cred_trust_level(&lox_cred); + // If trust level is 0, do trust promotion, otherwise level up. - let cred = if lox_cred.trust_level == Scalar::zero() { + let cred = if old_level == 0 { let migration_cred = trust_promotion(&server_addr, &lox_cred, get_lox_pub(&lox_auth_pubkeys)).await; let cred = trust_migration( @@ -125,6 +127,12 @@ async fn main() { cred }; save_object(&cred, &lox_cred_filename); + let new_level = get_cred_trust_level(&cred); + if new_level > old_level { + println!("Old level: {}\nNew level: {}", old_level, new_level); + } else if new_level == old_level { + println!("Unable to level up. Current level: {}", new_level); + } cred } else { lox_cred diff --git a/src/client_lib.rs b/src/client_lib.rs index 991681e..5e86f55 100644 --- a/src/client_lib.rs +++ b/src/client_lib.rs @@ -1,6 +1,7 @@ mod client_net; use client_net::net_request; +use curve25519_dalek::scalar::Scalar; use lox::bridge_table::BridgeLine; use lox::bridge_table::ENC_BUCKET_BYTES; use lox::proto::*; @@ -10,6 +11,9 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use std::time::Duration; +// used for testing function +use std::io::Write; + // From https://gitlab.torproject.org/onyinyang/lox-server/-/blob/main/src/main.rs // TODO: Move this to main Lox library? #[serde_as] @@ -25,6 +29,24 @@ pub struct EncBridgeTable { etable: Vec<[u8; ENC_BUCKET_BYTES]>, } +// These two functions should only be used for testing. +// This file should probably belong to the client, not the library. +const TIME_OFFSET_FILENAME: &str = "time_offset.json"; +fn get_time_offset() -> u32 { + if std::path::Path::new(&TIME_OFFSET_FILENAME).exists() { + let infile = std::fs::File::open(&TIME_OFFSET_FILENAME).unwrap(); + serde_json::from_reader(infile).unwrap() + } else { + 0 + } +} +fn save_time_offset(secs: &u32) { + let mut outfile = + std::fs::File::create(&TIME_OFFSET_FILENAME).expect("Failed to create time_offset"); + write!(outfile, "{}", serde_json::to_string(&secs).unwrap()) + .expect("Failed to write to time_offset"); +} + /// Get today's (real or simulated) date /// /// This function is modified from the lox lib.rs @@ -58,6 +80,24 @@ pub fn get_invitation_pub(lox_auth_pubkeys: &Vec) -> &IssuerPubKey &lox_auth_pubkeys[4] } +// Helper function to get credential trust level as i8 +// (Note that this value should only be 0-4) +pub fn get_cred_trust_level(cred: &lox::cred::Lox) -> i8 { + let trust_levels: [Scalar; 5] = [ + Scalar::zero(), + Scalar::one(), + Scalar::from(2u64), + Scalar::from(3u64), + Scalar::from(4u8), + ]; + for i in 0..trust_levels.len() { + if cred.trust_level == trust_levels[i] { + return i.try_into().unwrap(); + } + } + -1 +} + // Download Lox Auth pubkeys pub async fn get_lox_auth_keys(server_addr: &str) -> Vec { let resp = net_request(server_addr.to_string() + "/pubkeys", [].to_vec()).await; @@ -99,9 +139,13 @@ pub async fn trust_promotion( lox_cred: &lox::cred::Lox, lox_pub: &IssuerPubKey, ) -> lox::cred::Migration { + // FOR TESTING ONLY + let time_offset = get_time_offset() + 60 * 60 * 24 * 31; + save_time_offset(&time_offset); + let (req, state) = // trust_promotion::request(&lox_cred, &lox_pub, today(Duration::ZERO)).unwrap(); - trust_promotion::request(&lox_cred, &lox_pub, today(Duration::from_secs(60 * 60 * 24 * 31))).unwrap(); // FOR TESTING ONLY + trust_promotion::request(&lox_cred, &lox_pub, today(Duration::from_secs(time_offset.into()))).unwrap(); // FOR TESTING ONLY let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); let encoded_resp = net_request(server_addr.to_string() + "/trustpromo", encoded_req).await; let decoded_resp: trust_promotion::Response = serde_json::from_slice(&encoded_resp).unwrap(); @@ -142,6 +186,10 @@ pub async fn level_up( lox::bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); let reachcred = bucket.1.unwrap(); + // FOR TESTING ONLY + let time_offset = get_time_offset() + 60 * 60 * 24 * 85; + save_time_offset(&time_offset); + // Use the Bucket Reachability credential to advance to the next // level let (req, state) = level_up::request( @@ -150,12 +198,7 @@ pub async fn level_up( lox_pub, reachability_pub, //today(Duration::ZERO), - - // The following line adds 31 days (from initial trust migration) - // plus 85 days for first level up. - // The server's testing code keeps track of time added as the - // program runs. This should be adapted to do that as well. - today(Duration::from_secs(60 * 60 * 24 * (31 + 85))), // FOR TESTING ONLY + today(Duration::from_secs(time_offset.into())), // FOR TESTING ONLY ) .unwrap(); let encoded_req: Vec = serde_json::to_vec(&req).unwrap();