diff --git a/crates/lox-wasm/Cargo.toml b/crates/lox-wasm/Cargo.toml index 5af794d..7cf14be 100644 --- a/crates/lox-wasm/Cargo.toml +++ b/crates/lox-wasm/Cargo.toml @@ -17,5 +17,5 @@ serde = "1" serde-wasm-bindgen = "0.4.5" console_error_panic_hook = "0.1.7" - +time = "0.2" rand = { version = "0.7", features = ["wasm-bindgen"] } diff --git a/crates/lox-wasm/index.js b/crates/lox-wasm/index.js index f04ad5b..3c70961 100644 --- a/crates/lox-wasm/index.js +++ b/crates/lox-wasm/index.js @@ -1,31 +1,54 @@ -import init, { open_invite, handle_new_lox_credential, set_panic_hook } from "./pkg/lox_wasm.js"; +import init, { open_invite, handle_new_lox_credential, trust_promotion, handle_trust_promotion, set_panic_hook } from "./pkg/lox_wasm.js"; let pubkeys = await request_pubkeys(); -console.log(pubkeys); -let requested = await init().then(() => { +let requested_invite = await init().then(() => { set_panic_hook(); - let requested = request_open_invite().then((token) => { + let requested_invite = request_open_invite().then((token) => { return open_invite(token); }); - return requested; + return requested_invite; }); -console.log("Got request and state "+requested); +console.log("Got request and state: "+requested_invite); let open_lox_cred = await init().then(() => { set_panic_hook(); - let cred = request_new_lox_credential(requested).then((response) => { - return handle_new_lox_credential(requested, response, pubkeys); + let cred = request_new_lox_credential(requested_invite).then((response) => { + return handle_new_lox_credential(requested_invite, response, pubkeys); }); return cred; }); -console.log("Got Lox Credential and BridgeLine "+open_lox_cred); -function request_new_lox_credential(requested) { +let requested_trust_promo = trust_promotion(open_lox_cred, pubkeys); + +let trust_promo_cred = await init().then(() => { + set_panic_hook(); + let cred = request_trust_promo_cred(requested_trust_promo).then((response)=> { + return handle_trust_promotion(requested_trust_promo, response); + }); + return cred; + }); + + let reachability_cred = await request_reachability(); + +function request_new_lox_credential(requested_invite) { + return new Promise((fulfill, reject) => { + let req = JSON.parse(requested_invite); + loxServerPostRequest("/openreq", req.request).then((response) => { + console.log("Got new Open Invite Lox Credential: " + JSON.stringify(response)); + fulfill(JSON.stringify(response)); + return; + }).catch(() => { + console.log("Error requesting new Lox credential from server"); + reject(); + }); + }); +} + +function request_trust_promo_cred(requested) { return new Promise((fulfill, reject) => { let req = JSON.parse(requested); - console.log("Request? "+JSON.stringify(req.request)); - loxServerPostRequest("/openreq", req.request).then((response) => { - console.log("Got new Lox Credential: " + JSON.stringify(response)); + loxServerPostRequest("/trustpromo", req.request).then((response) => { + console.log("Got new Trust Promotion Lox Credential: " + JSON.stringify(response)); fulfill(JSON.stringify(response)); return; }).catch(() => { @@ -61,6 +84,19 @@ function request_pubkeys() { }); } +function request_reachability() { + return new Promise((fulfill, reject) => { + loxServerGetRequest("/reachability").then((response) => { + console.log("Got reachability Cred: " + JSON.stringify(response)); + fulfill(JSON.stringify(response)); + return; + }).catch(() => { + console.log("Error requesting bucket reachability credential from Lox server"); + reject(); + }); + }); +} + function loxServerGetRequest(data) { return new Promise((fulfill, reject) => { const xhr = new XMLHttpRequest(); diff --git a/crates/lox-wasm/src/lib.rs b/crates/lox-wasm/src/lib.rs index 6f7f55a..41f0dbe 100644 --- a/crates/lox-wasm/src/lib.rs +++ b/crates/lox-wasm/src/lib.rs @@ -1,4 +1,6 @@ -use lox::proto::open_invite; +use lox::cred::Lox; +use lox::bridge_table::BridgeLine; +use lox::proto::{open_invite, trust_promotion}; use lox::{IssuerPubKey, OPENINV_LENGTH}; use serde::{Deserialize, Serialize}; use serde_json; @@ -8,9 +10,15 @@ use std::panic; use wasm_bindgen::prelude::*; #[derive(Deserialize, Serialize)] -struct ReqState { - request: lox::proto::open_invite::Request, - state: lox::proto::open_invite::State, +struct OpenReqState { + request: open_invite::Request, + state: open_invite::State, +} + +#[derive(Deserialize, Serialize)] +struct TrustReqState { + request: trust_promotion::Request, + state: trust_promotion::State, } #[derive(Debug, Deserialize, Serialize)] @@ -24,8 +32,8 @@ struct PubKeys { #[derive(Debug, Deserialize, Serialize)] struct Credential { - lox_credential: String, - bridgeline: String, + lox_credential: Lox, + bridgeline: BridgeLine, } #[wasm_bindgen] @@ -49,7 +57,7 @@ pub fn open_invite(invite: &[u8]) -> Result { Err(e) => return Err(JsValue::from(e.to_string())), }; let (request, state) = open_invite::request(&token); - let req_state = ReqState { + let req_state = OpenReqState { request: request, state: state, }; @@ -68,7 +76,7 @@ pub fn handle_new_lox_credential( open_lox_response: String, lox_pub: String, ) -> Result { - let req_state: ReqState = serde_json::from_str(&open_lox_result).unwrap(); + let req_state: OpenReqState = serde_json::from_str(&open_lox_result).unwrap(); let deserialized_state = req_state.state; let deserialized_response = serde_json::from_str(&open_lox_response).unwrap(); let pubkeys: PubKeys = serde_json::from_str(&lox_pub).unwrap(); @@ -84,20 +92,79 @@ pub fn handle_new_lox_credential( } }; let lox_cred = Credential { - lox_credential: serde_json::to_string(&lox_cred.0).unwrap(), - bridgeline: serde_json::to_string(&lox_cred.1).unwrap(), + lox_credential: lox_cred.0, + bridgeline: lox_cred.1, }; unsafe { log(&format!( "Got new Lox Credential: {}", - lox_cred.lox_credential + serde_json::to_string(&lox_cred.lox_credential).unwrap() )); - log(&format!("Got new bridgeline: {}", lox_cred.bridgeline)); + log(&format!("Got new bridgeline: {}", serde_json::to_string(&lox_cred.bridgeline).unwrap())); } Ok(serde_json::to_string(&lox_cred).unwrap()) } + +#[wasm_bindgen] +pub fn trust_promotion(open_lox_cred: String, lox_pub: String) -> String { + let lox_cred: Credential = serde_json::from_str(&open_lox_cred).unwrap(); + let pubkeys: PubKeys = serde_json::from_str(&lox_pub).unwrap(); + let (request, state) = trust_promotion::request(&lox_cred.lox_credential, &pubkeys.lox_pub, today()).unwrap(); + let req_state = TrustReqState { + request: request, + state: state, + }; + unsafe { + log(&format!( + "Formatted open invite request: {}", + serde_json::to_string(&req_state).unwrap() + )); + } + serde_json::to_string(&req_state).unwrap() +} + + +#[wasm_bindgen] +pub fn handle_trust_promotion( + trust_promo_request: String, + trust_promo_response: String, +) -> Result { + let req_state: TrustReqState = serde_json::from_str(&trust_promo_request).unwrap(); + let deserialized_state = req_state.state; + let deserialized_response = serde_json::from_str(&trust_promo_response).unwrap(); + let migration_cred = match trust_promotion::handle_response( + deserialized_state, + deserialized_response, + ) { + Ok(migration_cred) => migration_cred, + Err(e) => { + log(&format!("Error: {:?}", e.to_string())); + return Err(JsValue::from(e.to_string())); + } + }; + unsafe { + log(&format!( + "Got new Migration Credential: {}", + serde_json::to_string(&migration_cred).unwrap() + )); + } + Ok(serde_json::to_string(&migration_cred).unwrap()) +} + + + // This should also check the pubkey fn validate(invite: &[u8]) -> Result<[u8; OPENINV_LENGTH], TryFromSliceError> { invite.try_into() } + +/// Get today's (real or simulated) date +fn today() -> u32 { + // We will not encounter negative Julian dates (~6700 years ago) + // or ones larger than 32 bits + (time::OffsetDateTime::now_utc().date()) + .julian_day() + .try_into() + .unwrap() + } \ No newline at end of file