Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Vecna 2024-01-14 17:50:52 -05:00
commit 0041116e65
27 changed files with 718 additions and 301 deletions

109
Cargo.lock generated
View File

@ -147,9 +147,9 @@ dependencies = [
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.5" version = "0.21.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
@ -244,9 +244,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.7" version = "4.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -254,9 +254,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.7" version = "4.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -856,9 +856,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.27" version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -984,9 +984,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.65" version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1055,6 +1055,7 @@ dependencies = [
"hyper", "hyper",
"julianday", "julianday",
"lox-library", "lox-library",
"lox-zkp",
"lox_utils", "lox_utils",
"prometheus", "prometheus",
"prometheus-client", "prometheus-client",
@ -1065,9 +1066,9 @@ dependencies = [
"serde_json", "serde_json",
"serde_with", "serde_with",
"sled", "sled",
"thiserror",
"time", "time",
"tokio", "tokio",
"zkp",
] ]
[[package]] [[package]]
@ -1082,6 +1083,7 @@ dependencies = [
"ed25519-dalek", "ed25519-dalek",
"hex_fmt", "hex_fmt",
"lazy_static", "lazy_static",
"lox-zkp",
"prometheus", "prometheus",
"rand 0.8.5", "rand 0.8.5",
"serde", "serde",
@ -1091,7 +1093,6 @@ dependencies = [
"subtle", "subtle",
"thiserror", "thiserror",
"time", "time",
"zkp",
] ]
[[package]] [[package]]
@ -1105,12 +1106,25 @@ dependencies = [
"julianday", "julianday",
"lazy_static", "lazy_static",
"lox-library", "lox-library",
"lox-zkp",
"lox_utils", "lox_utils",
"rand 0.7.3", "rand 0.7.3",
"serde_json", "serde_json",
"time", "time",
"wasm-bindgen", "wasm-bindgen",
"zkp", ]
[[package]]
name = "lox-zkp"
version = "0.8.0"
source = "git+https://gitlab.torproject.org/onyinyang/lox-zkp#10a8379081f079fc09669640f29c255897b3b454"
dependencies = [
"curve25519-dalek",
"merlin",
"rand 0.8.5",
"serde",
"serde_derive",
"thiserror",
] ]
[[package]] [[package]]
@ -1460,9 +1474,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.66" version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -1513,9 +1527,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.32" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1862,18 +1876,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.192" version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.192" version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2044,9 +2058,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.32" version = "2.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2068,18 +2082,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.49" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.49" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2088,9 +2102,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
@ -2108,9 +2122,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]
@ -2317,9 +2331,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.88" version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -2327,9 +2341,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.88" version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
@ -2354,9 +2368,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.88" version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -2364,9 +2378,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.88" version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2377,9 +2391,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.88" version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]] [[package]]
name = "wasm-streams" name = "wasm-streams"
@ -2529,16 +2543,3 @@ dependencies = [
"quote", "quote",
"syn", "syn",
] ]
[[package]]
name = "zkp"
version = "0.8.0"
source = "git+https://gitlab.torproject.org/onyinyang/lox-zkp#7dc7562ecdac3a6c7c7ecc31cace192174d34778"
dependencies = [
"curve25519-dalek",
"merlin",
"rand 0.8.5",
"serde",
"serde_derive",
"thiserror",
]

View File

@ -7,34 +7,35 @@ rust-version = "1.65.0"
license = "MIT" license = "MIT"
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home" homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
description = "Tool for receving Tor bridges from rdsys and distributing them to users" description = "Tool for receving Tor bridges from rdsys and distributing them to users"
keywords = ["tor", "lox", "bridges","censorship-resistance"] keywords = ["tor", "lox", "bridges","anti-censorship", "distributor"]
categories = ["web-programming::http-server"] categories = ["web-programming::http-server"]
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-distributor" repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-distributor"
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/lox-distributor/README.md" readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
julianday = "1.2.0" julianday = "1.2.0"
base64 = "0.21.5" base64 = "0.21.6"
hyper = { version = "0.14.27", features = ["server"] } hyper = { version = "0.14.28", features = ["deprecated", "backports","server"] }
hex_fmt = "0.3" hex_fmt = "0.3"
futures = "0.3.29" futures = "0.3.29"
time = "0.3.30" time = "0.3.31"
tokio = { version = "1", features = ["full", "macros", "signal"] } tokio = { version = "1", features = ["full", "macros", "signal"] }
rand = "0.8.5" rand = "0.8.5"
reqwest = { version = "0.11", features = ["json", "stream"]} reqwest = { version = "0.11", features = ["json", "stream"]}
serde = { version = "1.0", features = ["derive", "rc"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_with = "3.4.0" serde_with = "3.4.0"
zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp" } lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
lox-library = { path = "../lox-library", version = "0.1.0"} lox-library = { path = "../lox-library", version = "0.1.0"}
lox_utils = { path = "../lox-utils", version = "0.1.0"} lox_utils = { path = "../lox-utils", version = "0.1.0"}
rdsys_backend = { path = "../rdsys-backend-api", version = "0.2"} rdsys_backend = { path = "../rdsys-backend-api", version = "0.2"}
clap = { version = "4.4.7", features = ["derive"] } clap = { version = "4.4.14", features = ["derive"] }
serde_json = "1.0.108" serde_json = "1.0.108"
prometheus = "0.13.3" prometheus = "0.13.3"
sled = "0.34.7" sled = "0.34.7"
prometheus-client = "0.22.0" prometheus-client = "0.22.0"
thiserror = "1"
[dependencies.chrono] [dependencies.chrono]
version = "0.4.31" version = "0.4.31"

View File

@ -1,4 +1,3 @@
use std::fs::OpenOptions;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::metrics::Metrics; use crate::metrics::Metrics;
@ -6,6 +5,18 @@ use crate::{lox_context, DbConfig};
use chrono::{naive::Days, DateTime, Local, NaiveDateTime, Utc}; use chrono::{naive::Days, DateTime, Local, NaiveDateTime, Utc};
use lox_library::{BridgeAuth, BridgeDb}; use lox_library::{BridgeAuth, BridgeDb};
use sled::IVec; use sled::IVec;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum LoxDBError {
//failed to get last db entry
#[error("Failed to read last database entry")]
ReadFailure(#[from] sled::Error),
//no last db entries
#[error("No database entries stored")]
DatabaseEmpty,
}
// Database of Lox Distributor State // Database of Lox Distributor State
pub struct DB { pub struct DB {
@ -42,7 +53,7 @@ impl DB {
// If roll_back_date is empty, opens the most recent entry in the lox database or if none exists, creates a // If roll_back_date is empty, opens the most recent entry in the lox database or if none exists, creates a
// new database. If roll_back_date is not empty, use the specified date to roll back to a previous lox-context // new database. If roll_back_date is not empty, use the specified date to roll back to a previous lox-context
// either exactly the entry at the roll_back_date or within 24 hours from thhe roll_back_date. // either exactly the entry at the roll_back_date or within 24 hours from the roll_back_date.
pub fn open_new_or_existing_db( pub fn open_new_or_existing_db(
db_config: DbConfig, db_config: DbConfig,
roll_back_date: Option<String>, roll_back_date: Option<String>,
@ -52,8 +63,11 @@ impl DB {
let (lox_db, context) = match sled::open(db_config.db_path) { let (lox_db, context) = match sled::open(db_config.db_path) {
Ok(lox_db) => { Ok(lox_db) => {
// Check if the lox_db already exists // Check if the lox_db already exists
if lox_db.was_recovered() { if lox_db.was_recovered() && !lox_db.is_empty() {
context = read_lox_context_from_db(lox_db.clone(), roll_back_date); context = match read_lox_context_from_db(lox_db.clone(), roll_back_date) {
Ok(ctx) => ctx,
Err(e) => panic!("Unable to read lox database {:?}", e),
};
context.metrics = metrics; context.metrics = metrics;
//Otherwise, create a new Lox context //Otherwise, create a new Lox context
} else { } else {
@ -81,7 +95,7 @@ impl DB {
fn read_lox_context_from_db( fn read_lox_context_from_db(
lox_db: sled::Db, lox_db: sled::Db,
roll_back_date: Option<String>, roll_back_date: Option<String>,
) -> lox_context::LoxServerContext { ) -> Result<lox_context::LoxServerContext, LoxDBError> {
let context: lox_context::LoxServerContext; let context: lox_context::LoxServerContext;
// Check if there is a roll back date and try to choose the appropriate context // Check if there is a roll back date and try to choose the appropriate context
// to rollback to, otherwise, take the last saved context // to rollback to, otherwise, take the last saved context
@ -119,11 +133,9 @@ fn read_lox_context_from_db(
} }
} }
// Use the last entry to populate the Lox context if no rollback date is set (which should be most common) // Use the last entry to populate the Lox context if no rollback date is set (which should be most common)
None => { None => context = use_last_context(lox_db)?,
context = use_last_context(lox_db);
} }
} Ok(context)
context
} }
fn compute_startdate_string(date_range_end: String) -> Option<DateTime<Utc>> { fn compute_startdate_string(date_range_end: String) -> Option<DateTime<Utc>> {
@ -134,11 +146,15 @@ fn compute_startdate_string(date_range_end: String) -> Option<DateTime<Utc>> {
} }
// Use the last context that was entered into the database // Use the last context that was entered into the database
fn use_last_context(lox_db: sled::Db) -> lox_context::LoxServerContext { fn use_last_context(lox_db: sled::Db) -> Result<lox_context::LoxServerContext, LoxDBError> {
let ivec_context = lox_db.last().unwrap().unwrap(); match lox_db.last()? {
Some(ivec_context) => {
let ivec_date: String = String::from_utf8(ivec_context.0.to_vec()).unwrap(); let ivec_date: String = String::from_utf8(ivec_context.0.to_vec()).unwrap();
println!("Using last context with date: {:?}", ivec_date); println!("Using last context with date: {:?}", ivec_date);
serde_json::from_slice(&ivec_context.1).unwrap() Ok(serde_json::from_slice(&ivec_context.1).unwrap())
}
None => Err(LoxDBError::DatabaseEmpty),
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,22 +1,22 @@
use hyper::{body::Bytes, header::HeaderValue, Body, Response}; use hyper::{body::Bytes, header::HeaderValue, Body, Response};
use lox_library::{ use lox_library::{
bridge_table::{BridgeLine, EncryptedBucket, MAX_BRIDGES_PER_BUCKET}, bridge_table::{BridgeLine, EncryptedBucket, MAX_BRIDGES_PER_BUCKET},
proto::{ proto::{
blockage_migration, check_blockage, issue_invite, level_up, migration, open_invite, blockage_migration, check_blockage, issue_invite, level_up, migration, open_invite,
redeem_invite, trust_promotion, redeem_invite, trust_promotion,
}, },
BridgeAuth, BridgeDb, ExceededMaxBridgesError, IssuerPubKey, BridgeAuth, BridgeDb, IssuerPubKey, OpenInvitationError,
}; };
use rdsys_backend::proto::{Resource, ResourceState}; use rdsys_backend::proto::{Resource, ResourceState};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use lox_zkp::ProofError;
use serde_json::json;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::HashMap,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use zkp::ProofError;
use crate::metrics::Metrics; use crate::metrics::Metrics;
use crate::resource_parser::{parse_into_bridgelines, sort_for_parsing}; use crate::resource_parser::{parse_into_bridgelines, sort_for_parsing};
@ -365,7 +365,7 @@ impl LoxServerContext {
// Generates a Lox invitation if fewer than MAX_BRIDGES_PER_DAY have been // Generates a Lox invitation if fewer than MAX_BRIDGES_PER_DAY have been
// requested on a given day // requested on a given day
fn gen_invite(&self) -> Result<lox_utils::Invite, ExceededMaxBridgesError> { fn gen_invite(&self) -> Result<lox_utils::Invite, OpenInvitationError> {
let mut obj = self.db.lock().unwrap(); let mut obj = self.db.lock().unwrap();
match obj.invite() { match obj.invite() {
Ok(invite) => { Ok(invite) => {
@ -450,12 +450,16 @@ impl LoxServerContext {
Ok(resp) => prepare_header(resp), Ok(resp) => prepare_header(resp),
Err(e) => { Err(e) => {
println!("Error parsing Invite to JSON"); println!("Error parsing Invite to JSON");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
}, },
Err(e) => { Err(e) => {
println!("Error parsing Invite to JSON"); println!("Error generating open invitation");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -468,7 +472,9 @@ impl LoxServerContext {
Ok(resp) => prepare_header(resp), Ok(resp) => prepare_header(resp),
Err(e) => { Err(e) => {
println!("Error parsing encrypted bridgetable to JSON"); println!("Error parsing encrypted bridgetable to JSON");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -480,7 +486,9 @@ impl LoxServerContext {
Ok(resp) => prepare_header(resp), Ok(resp) => prepare_header(resp),
Err(e) => { Err(e) => {
println!("Error parsing Pubkeys to JSON"); println!("Error parsing Pubkeys to JSON");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -500,7 +508,11 @@ impl LoxServerContext {
pub fn verify_and_send_open_cred(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_open_cred(self, request: Bytes) -> Response<Body> {
let req = match serde_json::from_slice(&request) { let req = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.open_inv(req) { match self.open_inv(req) {
Ok(resp) => { Ok(resp) => {
@ -510,7 +522,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Open Invitation request, Proof Error"); println!("Invalid Open Invitation request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -519,7 +533,11 @@ impl LoxServerContext {
pub fn verify_and_send_trust_promo(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_trust_promo(self, request: Bytes) -> Response<Body> {
let req: trust_promotion::Request = match serde_json::from_slice(&request) { let req: trust_promotion::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.trust_promo(req) { match self.trust_promo(req) {
Ok(resp) => { Ok(resp) => {
@ -529,7 +547,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Trust Promotion request, Proof Error"); println!("Invalid Trust Promotion request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -538,7 +558,11 @@ impl LoxServerContext {
pub fn verify_and_send_trust_migration(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_trust_migration(self, request: Bytes) -> Response<Body> {
let req: migration::Request = match serde_json::from_slice(&request) { let req: migration::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.trust_migration(req) { match self.trust_migration(req) {
Ok(resp) => { Ok(resp) => {
@ -548,7 +572,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Trust Migration request, Proof Error"); println!("Invalid Trust Migration request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -557,7 +583,11 @@ impl LoxServerContext {
pub fn verify_and_send_level_up(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_level_up(self, request: Bytes) -> Response<Body> {
let req: level_up::Request = match serde_json::from_slice(&request) { let req: level_up::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.level_up(req) { match self.level_up(req) {
Ok(resp) => { Ok(resp) => {
@ -567,7 +597,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Level up request, Proof Error"); println!("Invalid Level up request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -576,7 +608,11 @@ impl LoxServerContext {
pub fn verify_and_send_issue_invite(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_issue_invite(self, request: Bytes) -> Response<Body> {
let req: issue_invite::Request = match serde_json::from_slice(&request) { let req: issue_invite::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.issue_invite(req) { match self.issue_invite(req) {
Ok(resp) => { Ok(resp) => {
@ -586,7 +622,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Issue invite request, Proof Error"); println!("Invalid Issue invite request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -595,7 +633,11 @@ impl LoxServerContext {
pub fn verify_and_send_redeem_invite(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_redeem_invite(self, request: Bytes) -> Response<Body> {
let req: redeem_invite::Request = match serde_json::from_slice(&request) { let req: redeem_invite::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.redeem_invite(req) { match self.redeem_invite(req) {
Ok(resp) => { Ok(resp) => {
@ -605,7 +647,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Redeem Invite request, Proof Error"); println!("Invalid Redeem Invite request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -614,7 +658,11 @@ impl LoxServerContext {
pub fn verify_and_send_check_blockage(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_check_blockage(self, request: Bytes) -> Response<Body> {
let req: check_blockage::Request = match serde_json::from_slice(&request) { let req: check_blockage::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.check_blockage(req) { match self.check_blockage(req) {
Ok(resp) => { Ok(resp) => {
@ -624,7 +672,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Check blockage request, Proof Error"); println!("Invalid Check blockage request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -633,7 +683,11 @@ impl LoxServerContext {
pub fn verify_and_send_blockage_migration(self, request: Bytes) -> Response<Body> { pub fn verify_and_send_blockage_migration(self, request: Bytes) -> Response<Body> {
let req: blockage_migration::Request = match serde_json::from_slice(&request) { let req: blockage_migration::Request = match serde_json::from_slice(&request) {
Ok(req) => req, Ok(req) => req,
Err(e) => return prepare_error_header(e.to_string()), Err(e) => {
let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
return prepare_header(val);
}
}; };
match self.blockage_migration(req) { match self.blockage_migration(req) {
Ok(resp) => { Ok(resp) => {
@ -643,7 +697,9 @@ impl LoxServerContext {
} }
Err(e) => { Err(e) => {
println!("Invalid Blockage Migration request, Proof Error"); println!("Invalid Blockage Migration request, Proof Error");
prepare_error_header(e.to_string()) let response = json!({"error": e.to_string()});
let val = serde_json::to_string(&response).unwrap();
prepare_header(val)
} }
} }
} }
@ -668,11 +724,3 @@ fn prepare_header(response: String) -> Response<Body> {
.insert("Access-Control-Allow-Origin", HeaderValue::from_static("*")); .insert("Access-Control-Allow-Origin", HeaderValue::from_static("*"));
resp resp
} }
// Prepare HTTP Response for errored Server Request
fn prepare_error_header(error: String) -> Response<Body> {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(error))
.unwrap()
}

View File

@ -124,14 +124,20 @@ async fn rdsys_request(rtype: ResourceInfo, tx: mpsc::Sender<ResourceState>) {
let mut interval = interval(Duration::from_secs(5)); let mut interval = interval(Duration::from_secs(5));
loop { loop {
interval.tick().await; interval.tick().await;
let resources = request_resources( let resources = match request_resources(
rtype.endpoint.clone(), rtype.endpoint.clone(),
rtype.name.clone(), rtype.name.clone(),
rtype.token.clone(), rtype.token.clone(),
rtype.types.clone(), rtype.types.clone(),
) )
.await .await
.unwrap(); {
Ok(resources) => resources,
Err(e) => {
println!("No resources received from rdsys: {:?}", e);
continue;
}
};
tx.send(resources).await.unwrap(); tx.send(resources).await.unwrap();
} }
} }
@ -326,7 +332,8 @@ async fn main() {
}); });
let (tx, rx) = mpsc::channel(32); let (tx, rx) = mpsc::channel(32);
let rdsys_request_handler = spawn(async { rdsys_request_creator(config.rtype, tx, kill_stream).await }); let rdsys_request_handler =
spawn(async { rdsys_request_creator(config.rtype, tx, kill_stream).await });
let rdsys_resource_receiver = let rdsys_resource_receiver =
spawn(async { rdsys_bridge_parser(rdsys_tx, rx, kill_parser).await }); spawn(async { rdsys_bridge_parser(rdsys_tx, rx, kill_parser).await });

View File

@ -342,7 +342,7 @@ mod tests {
.body(Body::empty()) .body(Body::empty())
.unwrap(); .unwrap();
let not_found_response = handle(th.context.clone(), req).await.unwrap(); let not_found_response = handle(th.context.clone(), req).await.unwrap();
assert_eq!(not_found_response.status(), StatusCode::BAD_REQUEST); assert_eq!(not_found_response.status(), StatusCode::OK)
} }
#[tokio::test] #[tokio::test]
@ -415,9 +415,11 @@ mod tests {
&pubkeys_obj.lox_pub, &pubkeys_obj.lox_pub,
) )
.unwrap(); .unwrap();
let mut bridge = Vec::new();
bridge.push(lox_cred.1);
let lox_cred: lox_utils::LoxCredential = lox_utils::LoxCredential { let lox_cred: lox_utils::LoxCredential = lox_utils::LoxCredential {
lox_credential: lox_cred.0, lox_credential: lox_cred.0,
bridgeline: Some(lox_cred.1), bridgelines: Some(bridge),
invitation: None, invitation: None,
}; };

View File

@ -1,5 +1,3 @@
use std::process::exit;
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use lox_library::bridge_table::{BridgeLine, BRIDGE_BYTES, MAX_BRIDGES_PER_BUCKET}; use lox_library::bridge_table::{BridgeLine, BRIDGE_BYTES, MAX_BRIDGES_PER_BUCKET};
use rdsys_backend::proto::Resource; use rdsys_backend::proto::Resource;

View File

@ -7,10 +7,10 @@ rust-version = "1.65.0"
license = "MIT" license = "MIT"
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home" homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
description = "Main Lox library with protocols and functions that that make up Lox" description = "Main Lox library with protocols and functions that that make up Lox"
keywords = ["tor", "lox", "bridge-distribution","censorship-resistance"] keywords = ["tor", "lox", "bridges","anti-censorship", "anonymous-cred"]
categories = ["cryptography"] categories = ["cryptography"]
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-library" repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-library"
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/lox-library/README.md" readme = "README.md"
[dependencies] [dependencies]
@ -19,7 +19,7 @@ ed25519-dalek = { version = "2", features = ["serde", "rand_core"] }
bincode = "1" bincode = "1"
chrono = "0.4" chrono = "0.4"
rand = { version = "0.8", features = ["std_rng"]} rand = { version = "0.8", features = ["std_rng"]}
serde = "1.0.192" serde = "1.0.195"
serde_with = {version = "3.4.0", features = ["json"]} serde_with = {version = "3.4.0", features = ["json"]}
sha2 = "0.10" sha2 = "0.10"
statistical = "1.0.0" statistical = "1.0.0"
@ -27,11 +27,11 @@ lazy_static = "1"
hex_fmt = "0.3" hex_fmt = "0.3"
aes-gcm = { version = "0.10", features =["aes"]} aes-gcm = { version = "0.10", features =["aes"]}
base64 = "0.21" base64 = "0.21"
time = "0.3.30" time = "0.3.31"
prometheus = "0.13.3" prometheus = "0.13.3"
subtle = "2.5" subtle = "2.5"
thiserror = "1.0.49" thiserror = "1.0.56"
zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp" } lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
[features] [features]
fast = [] fast = []

View File

@ -15,7 +15,7 @@ The notation follows that of the paper "Hyphae: Social Secret Sharing"
#![allow(non_snake_case)] #![allow(non_snake_case)]
#[macro_use] #[macro_use]
extern crate zkp; extern crate lox_zkp;
pub mod bridge_table; pub mod bridge_table;
pub mod cred; pub mod cred;
@ -86,9 +86,12 @@ pub enum NoAvailableIDError {
/// This error is thrown after the MAX_DAILY_BRIDGES threshold for bridges /// This error is thrown after the MAX_DAILY_BRIDGES threshold for bridges
/// distributed in a day has been reached /// distributed in a day has been reached
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ExceededMaxBridgesError { pub enum OpenInvitationError {
#[error("The maximum number of bridges has already been distributed today, please try again tomorrow!")] #[error("The maximum number of bridges has already been distributed today, please try again tomorrow!")]
ExceededMaxBridges, ExceededMaxBridges,
#[error("There are no bridges available for open invitations.")]
NoBridgesAvailable,
} }
/// Private Key of the Issuer /// Private Key of the Issuer
@ -113,7 +116,6 @@ impl IssuerPrivKey {
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct IssuerPubKey { pub struct IssuerPubKey {
X: Vec<RistrettoPoint>, X: Vec<RistrettoPoint>,
@ -216,7 +218,7 @@ impl BridgeDb {
/// Produce an open invitation such that the next k users, where k is < /// Produce an open invitation such that the next k users, where k is <
/// OPENINV_K, will receive the same open invitation bucket /// OPENINV_K, will receive the same open invitation bucket
/// chosen randomly from the set of open-invitation buckets. /// chosen randomly from the set of open-invitation buckets.
pub fn invite(&mut self) -> Result<[u8; OPENINV_LENGTH], ExceededMaxBridgesError> { pub fn invite(&mut self) -> Result<[u8; OPENINV_LENGTH], OpenInvitationError> {
let mut res: [u8; OPENINV_LENGTH] = [0; OPENINV_LENGTH]; let mut res: [u8; OPENINV_LENGTH] = [0; OPENINV_LENGTH];
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
// Choose a random invitation id (a Scalar) and serialize it // Choose a random invitation id (a Scalar) and serialize it
@ -227,6 +229,9 @@ impl BridgeDb {
self.today = Utc::now(); self.today = Utc::now();
self.daily_bridges_distributed = 0; self.daily_bridges_distributed = 0;
} }
if self.openinv_buckets.is_empty() {
return Err(OpenInvitationError::NoBridgesAvailable);
}
if self.daily_bridges_distributed < MAX_DAILY_BRIDGES { if self.daily_bridges_distributed < MAX_DAILY_BRIDGES {
if self.current_k < OPENINV_K && !self.distributed_buckets.is_empty() { if self.current_k < OPENINV_K && !self.distributed_buckets.is_empty() {
bucket_num = *self.distributed_buckets.last().unwrap(); bucket_num = *self.distributed_buckets.last().unwrap();
@ -247,7 +252,7 @@ impl BridgeDb {
res[(32 + 4)..].copy_from_slice(&sig.to_bytes()); res[(32 + 4)..].copy_from_slice(&sig.to_bytes());
Ok(res) Ok(res)
} else { } else {
Err(ExceededMaxBridgesError::ExceededMaxBridges) Err(OpenInvitationError::ExceededMaxBridges)
} }
} }
@ -267,11 +272,11 @@ impl BridgeDb {
let bucket = u32::from_le_bytes(invitation[32..(32 + 4)].try_into().unwrap()); let bucket = u32::from_le_bytes(invitation[32..(32 + 4)].try_into().unwrap());
let s = Scalar::from_canonical_bytes(invitation[0..32].try_into().unwrap()); let s = Scalar::from_canonical_bytes(invitation[0..32].try_into().unwrap());
if s.is_some().into() { if s.is_some().into() {
return Ok((s.unwrap(), bucket)); Ok((s.unwrap(), bucket))
} else { } else {
// It should never happen that there's a valid signature on // It should never happen that there's a valid signature on
// an invalid serialization of a Scalar, but check anyway. // an invalid serialization of a Scalar, but check anyway.
return Err(SignatureError::new()); Err(SignatureError::new())
} }
} }
} }

View File

@ -37,9 +37,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -76,7 +76,7 @@ pub struct Request {
EncBucket: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint),
EncBlockages: (RistrettoPoint, RistrettoPoint), EncBlockages: (RistrettoPoint, RistrettoPoint),
// The combined ZKP // The combined lox_zkp
piUser: CompactProof, piUser: CompactProof,
} }
@ -107,7 +107,7 @@ pub struct Response {
TBucket: RistrettoPoint, TBucket: RistrettoPoint,
TBlockages: RistrettoPoint, TBlockages: RistrettoPoint,
// The ZKP // The lox_zkp
piBlindIssue: CompactProof, piBlindIssue: CompactProof,
} }
@ -224,7 +224,7 @@ pub fn request(
// Form a Pedersen commitment to the MAC Q // Form a Pedersen commitment to the MAC Q
// We flip the sign of zQ from that of the Hyphae paper so that // We flip the sign of zQ from that of the Hyphae paper so that
// the ZKP has a "+" instead of a "-", as that's what the zkp // the lox_zkp has a "+" instead of a "-", as that's what the zkp
// macro supports. // macro supports.
let negzQ_lox = Scalar::random(&mut rng); let negzQ_lox = Scalar::random(&mut rng);
let CQ_lox = Q_lox - &negzQ_lox * Atable; let CQ_lox = Q_lox - &negzQ_lox * Atable;
@ -251,7 +251,7 @@ pub fn request(
// Form a Pedersen commitment to the MAC Q // Form a Pedersen commitment to the MAC Q
// We flip the sign of zQ from that of the Hyphae paper so that // We flip the sign of zQ from that of the Hyphae paper so that
// the ZKP has a "+" instead of a "-", as that's what the zkp // the lox_zkp has a "+" instead of a "-", as that's what the zkp
// macro supports. // macro supports.
let negzQ_mig = Scalar::random(&mut rng); let negzQ_mig = Scalar::random(&mut rng);
let CQ_mig = Q_mig - &negzQ_mig * Atable; let CQ_mig = Q_mig - &negzQ_mig * Atable;
@ -416,7 +416,7 @@ impl BridgeAuth {
+ self.migration_priv.x[3] * req.CToBucket + self.migration_priv.x[3] * req.CToBucket
- req.CQ_mig; - req.CQ_mig;
// Verify the ZKP // Verify the zkp
let mut transcript = Transcript::new(b"blockage migration request"); let mut transcript = Transcript::new(b"blockage migration request");
requestproof::verify_compact( requestproof::verify_compact(
&req.piUser, &req.piUser,

View File

@ -33,9 +33,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::serde_as; use serde_with::serde_as;
@ -69,7 +69,7 @@ pub struct Request {
D: RistrettoPoint, D: RistrettoPoint,
EncBucket: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint),
// The combined ZKP // The combined lox_zkp
piUser: CompactProof, piUser: CompactProof,
} }
@ -158,7 +158,7 @@ pub fn request(
// Form a Pedersen commitment to the MAC Q // Form a Pedersen commitment to the MAC Q
// We flip the sign of zQ from that of the Hyphae paper so that // We flip the sign of zQ from that of the Hyphae paper so that
// the ZKP has a "+" instead of a "-", as that's what the zkp // the lox_zkp has a "+" instead of a "-", as that's what the lox_zkp
// macro supports. // macro supports.
let negzQ = Scalar::random(&mut rng); let negzQ = Scalar::random(&mut rng);
let CQ = Q - &negzQ * Atable; let CQ = Q - &negzQ * Atable;
@ -268,7 +268,7 @@ impl BridgeAuth {
+ self.lox_priv.x[6] * req.CBlockages + self.lox_priv.x[6] * req.CBlockages
- req.CQ; - req.CQ;
// Verify the ZKP // Verify the zkp
let mut transcript = Transcript::new(b"check blockage request"); let mut transcript = Transcript::new(b"check blockage request");
requestproof::verify_compact( requestproof::verify_compact(
&req.piUser, &req.piUser,

View File

@ -50,9 +50,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -43,9 +43,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -35,9 +35,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -18,9 +18,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::serde_as; use serde_with::serde_as;

View File

@ -26,9 +26,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -32,9 +32,9 @@ use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity; use curve25519_dalek::traits::IsIdentity;
use zkp::CompactProof; use lox_zkp::CompactProof;
use zkp::ProofError; use lox_zkp::ProofError;
use zkp::Transcript; use lox_zkp::Transcript;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::serde_as; use serde_with::serde_as;

View File

@ -4,9 +4,10 @@ version = "0.1.0"
authors = ["The Tor Project, Inc.", "Lindsey Tulloch <onyinyang@torproject.org"] authors = ["The Tor Project, Inc.", "Lindsey Tulloch <onyinyang@torproject.org"]
edition = "2021" edition = "2021"
rust-version = "1.65" rust-version = "1.65"
license = "MIT"
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home" homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
description = "General helpers used by Lox" description = "General helpers used by Lox"
keywords = ["tor", "lox"] keywords = ["tor", "lox", "utilities"]
categories = ["rust-patterns"] categories = ["rust-patterns"]
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox.git/" repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox.git/"

View File

@ -0,0 +1,3 @@
# Lox Utils
This crate contains a number of helper structs and functions that are used by multiple lox crates.

View File

@ -1,4 +1,6 @@
use lox_library::bridge_table::{from_scalar, BridgeLine, BridgeTable, EncryptedBucket}; use lox_library::bridge_table::{
from_scalar, BridgeLine, BridgeTable, EncryptedBucket, MAX_BRIDGES_PER_BUCKET,
};
use lox_library::cred::{BucketReachability, Invitation, Lox}; use lox_library::cred::{BucketReachability, Invitation, Lox};
use lox_library::proto; use lox_library::proto;
use lox_library::{IssuerPubKey, OPENINV_LENGTH}; use lox_library::{IssuerPubKey, OPENINV_LENGTH};
@ -71,6 +73,21 @@ pub struct PubKeys {
pub invitation_pub: IssuerPubKey, pub invitation_pub: IssuerPubKey,
} }
#[derive(Debug, Deserialize, Serialize)]
pub struct LoxSystemInfo {
max_blockages: [u32; proto::level_up::MAX_LEVEL + 1],
level_interval: [u32; proto::level_up::MAX_LEVEL + 1],
level_invitations: [u32; proto::level_up::MAX_LEVEL + 1],
min_trust_level: u32,
}
pub const LOX_SYSTEM_INFO: LoxSystemInfo = LoxSystemInfo {
max_blockages: proto::level_up::MAX_BLOCKAGES,
level_interval: proto::level_up::LEVEL_INTERVAL,
level_invitations: proto::level_up::LEVEL_INVITATIONS,
min_trust_level: proto::check_blockage::MIN_TRUST_LEVEL,
};
#[serde_as] #[serde_as]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct EncBridgeTable { pub struct EncBridgeTable {
@ -80,10 +97,15 @@ pub struct EncBridgeTable {
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct LoxCredential { pub struct LoxCredential {
pub lox_credential: Lox, pub lox_credential: Lox,
pub bridgeline: Option<BridgeLine>, pub bridgelines: Option<Vec<BridgeLine>>,
pub invitation: Option<Invitation>, pub invitation: Option<Invitation>,
} }
#[derive(Debug, Deserialize, Serialize)]
pub struct IssuedInvitation {
pub invitation: Invitation,
}
// This should also check the pubkey // This should also check the pubkey
pub fn validate(invite: &[u8]) -> Result<[u8; OPENINV_LENGTH], TryFromSliceError> { pub fn validate(invite: &[u8]) -> Result<[u8; OPENINV_LENGTH], TryFromSliceError> {
invite.try_into() invite.try_into()
@ -97,6 +119,17 @@ pub fn generate_reachability_cred(lox_cred: &Lox, encrypted_table: String) -> Bu
bucket.1.unwrap() bucket.1.unwrap()
} }
pub fn get_credential_bridgelines(
lox_cred: &Lox,
encrypted_table: String,
) -> [BridgeLine; MAX_BRIDGES_PER_BUCKET] {
let (id, key) = from_scalar(lox_cred.bucket).unwrap();
let enc_buckets: EncBridgeTable = serde_json::from_str(&encrypted_table).unwrap();
let bucket =
BridgeTable::decrypt_bucket(id, &key, enc_buckets.etable.get(&id).unwrap()).unwrap();
bucket.0
}
//pub const MAX_LEVEL: usize = 4; //pub const MAX_LEVEL: usize = 4;
//pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56, 84]; //pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56, 84];
pub fn calc_test_days(trust_level: i64) -> i64 { pub fn calc_test_days(trust_level: i64) -> i64 {

View File

@ -6,10 +6,10 @@ edition = "2021"
description = "WASM bindings for lox" description = "WASM bindings for lox"
license = "MIT" license = "MIT"
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home" homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
keywords = ["tor", "lox", "bridges","censorship-resistance"] keywords = ["tor", "lox", "bridges","anti-censorship", "wasm"]
categories = ["wasm", "web-programming::http-client","external-ffi-bindings"] categories = ["wasm", "web-programming::http-client","external-ffi-bindings"]
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-wasm" repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/lox-wasm"
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/lox-wasm/README.md" readme = "README.md"
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]
@ -21,13 +21,13 @@ lazy_static = "1.4.0"
lox-library = { path = "../lox-library", version = "0.1.0" } lox-library = { path = "../lox-library", version = "0.1.0" }
lox_utils = { path = "../lox-utils", version = "0.1.0" } lox_utils = { path = "../lox-utils", version = "0.1.0" }
wasm-bindgen = "0.2" wasm-bindgen = "0.2"
time = "0.3.30" time = "0.3.31"
serde_json = "1.0.108" serde_json = "1.0.108"
console_error_panic_hook = "0.1.7" console_error_panic_hook = "0.1.7"
js-sys = "0.3.65" js-sys = "0.3.66"
rand = { version = "0.7", features = ["wasm-bindgen"] } rand = { version = "0.7", features = ["wasm-bindgen"] }
zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp" } lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
[dependencies.chrono] [dependencies.chrono]
version = "0.4.31" version = "0.4.31"

View File

@ -1,6 +1,6 @@
# lox-wasm # lox-wasm
wasm bindings for the lox crate: https://git-crysp.uwaterloo.ca/iang/lox wasm bindings for Lox client requests and response handling. These bindings are compatible with the endpoints in the [`lox-distributor`'s](../../lox-distributor/) [`request_handler`](../../lox-distributor/src/request_handler.rs).
# Dependencies # Dependencies
@ -14,12 +14,9 @@ cargo install wasm-pack
wasm-pack build --target web wasm-pack build --target web
``` ```
# Testing # Testing Locally
The provided `index.html` file can be used for testing the lox bindings. First, follow the instructions to [run the lox-distributor](../../lox-distributor/README.md).
### Testing Locally
The provided `index.html` file can be used for testing the lox bindings. First, follow the instructions to [run a lox server](https://gitlab.torproject.org/cohosh/lox-server).
Then, spin up a simple local webserver in the current directory: Then, spin up a simple local webserver in the current directory:
``` ```
@ -27,3 +24,7 @@ python3 -m http.server 8000
``` ```
Next, open the dev console in your browser and navigate to `http://localhost:8000`. Next, open the dev console in your browser and navigate to `http://localhost:8000`.
### Note
Although all Lox protocols are implemented, they will not all work with the existing [`index.js`](index.js) and the `lox-distributor`'s `request_handler`. This is because varying time intervals must pass between successful requests for certain Lox credentials. To fully test whether or not the full set of Lox credentials are working as intended (while rejecting patience as an acceptable method), the agreed upon time between the client and server must be artificially accelerated in tandem to the required future date after each relevant request so credentials can be validated. An earlier version of the `lox-distributor`: [`lox-server`](https://gitlab.torproject.org/cohosh/lox-server/-/blob/main/src/main.rs) includes some server side examples of how to accomplish this on the server side and the `lox-wasm` crate can be edited to artificially increase the time as shown [here](https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/73c3ef872878b295d84cddc51320d476d6fbcb7f/crates/lox-wasm/src/lib.rs#L102).

View File

@ -16,7 +16,7 @@ import init, {
handle_check_blockage, handle_check_blockage,
blockage_migration, blockage_migration,
handle_blockage_migration, handle_blockage_migration,
set_panic_hook } from "./pkg/lox_wasm.js"; set_panic_hook, get_last_upgrade_time, get_trust_level, get_invites_remaining, get_issued_invite_expiry, get_received_invite_expiry, get_bridgelines_from_bucket} from "./pkg/lox_wasm.js";
let pubkeys = await simple_request("/pubkeys"); let pubkeys = await simple_request("/pubkeys");
console.log("Got pubkeys: " + pubkeys); console.log("Got pubkeys: " + pubkeys);
@ -41,6 +41,12 @@ let open_lox_cred = await init().then(() => {
return cred; return cred;
}); });
get_last_upgrade_time(open_lox_cred);
get_trust_level(open_lox_cred);
get_invites_remaining(open_lox_cred);
let encrypted_table = await simple_request("/reachability");
let info_five = get_bridgelines_from_bucket(open_lox_cred, encrypted_table);
console.log("Bridgelines available: "+info_five);
let requested_trust_promo = trust_promotion(open_lox_cred, pubkeys); let requested_trust_promo = trust_promotion(open_lox_cred, pubkeys);
// Get Migration credential for Trust Promotion from Trust Level 0 -> 1 // Get Migration credential for Trust Promotion from Trust Level 0 -> 1
@ -66,7 +72,7 @@ let lox_cred = await init().then(() => {
return cred; return cred;
}); });
let encrypted_table = await simple_request("/reachability"); encrypted_table = await simple_request("/reachability");
console.log("Got Encrypted Table: " + encrypted_table); console.log("Got Encrypted Table: " + encrypted_table);
let requested_level_two = level_up(lox_cred, encrypted_table, pubkeys); let requested_level_two = level_up(lox_cred, encrypted_table, pubkeys);
@ -95,6 +101,10 @@ lox_cred = await init().then(() => {
return cred; return cred;
}); });
info_three = get_invites_remaining(lox_cred);
console.log("Last upgrade time: "+info_three);
info_four = get_invite_expiry(lox_cred);
console.log("Last upgrade time: "+info_four);
// Update reachability cred // Update reachability cred
encrypted_table = await simple_request("/reachability"); encrypted_table = await simple_request("/reachability");
@ -130,6 +140,10 @@ let prepared_invitation = prepare_invite(lox_cred);
// Trusted Invitation Request // Trusted Invitation Request
let requested_invitation = redeem_invite(prepared_invitation, pubkeys); let requested_invitation = redeem_invite(prepared_invitation, pubkeys);
// Redeem an Invitation cred // Redeem an Invitation cred
info_four = get_received_invite_expiry(prepared_invitation);
console.log("Last upgrade time: "+info_four);
let lox_cred_from_invite = await init().then(() => { let lox_cred_from_invite = await init().then(() => {
set_panic_hook(); set_panic_hook();
let cred = requested_cred("/redeem", requested_invitation).then((response)=> { let cred = requested_cred("/redeem", requested_invitation).then((response)=> {

View File

@ -1,6 +1,6 @@
use chrono::{Duration, Utc}; use chrono::Utc;
use julianday::JulianDay; use julianday::JulianDay;
use lox_library::cred::{Invitation, Lox, Migration}; use lox_library::cred::{Invitation, Migration};
use lox_library::proto::{ use lox_library::proto::{
blockage_migration, check_blockage, issue_invite, level_up, migration, open_invite, blockage_migration, check_blockage, issue_invite, level_up, migration, open_invite,
redeem_invite, trust_promotion, redeem_invite, trust_promotion,
@ -9,31 +9,12 @@ use lox_library::scalar_u32;
use std::panic; use std::panic;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
// Returns today's Julian date as a u32 value
fn today() -> u32 { fn today() -> u32 {
let naive_now = Utc::now().date_naive(); let naive_now = Utc::now().date_naive();
JulianDay::from(naive_now).inner().try_into().unwrap() JulianDay::from(naive_now).inner().try_into().unwrap()
} }
// This should only be used for testing, use today in production
fn test_today(days: i64) -> u32 {
let naive_now_plus = (Utc::now() + Duration::days(days)).date_naive();
JulianDay::from(naive_now_plus).inner().try_into().unwrap()
}
fn calc_test_days(lox_cred: &Lox) -> Result<i64, String> {
let trust_level: i64 = match scalar_u32(&lox_cred.trust_level) {
Some(v) => v as i64,
None => return Err("Error: Trust level does not exist".to_string()),
};
let mut total = 31;
// for level in 0..trust_level {
// let level_interval: u32 = LEVEL_INTERVAL[trust_level as usize];
// total += level_interval;
total += trust_level * 85;
// }
Ok(total)
}
#[wasm_bindgen] #[wasm_bindgen]
extern "C" { extern "C" {
#[wasm_bindgen(js_namespace = console)] #[wasm_bindgen(js_namespace = console)]
@ -45,6 +26,8 @@ pub fn set_panic_hook() {
panic::set_hook(Box::new(console_error_panic_hook::hook)); panic::set_hook(Box::new(console_error_panic_hook::hook));
} }
// Receives an invite and prepares an open_invite request, returning the
// Request and State
#[wasm_bindgen] #[wasm_bindgen]
pub fn open_invite(invite: &[u8]) -> Result<String, JsValue> { pub fn open_invite(invite: &[u8]) -> Result<String, JsValue> {
log(&format!("Using invite: {:?}", invite)); log(&format!("Using invite: {:?}", invite));
@ -58,7 +41,10 @@ pub fn open_invite(invite: &[u8]) -> Result<String, JsValue> {
"Formatted open invite request: {}", "Formatted open invite request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -67,10 +53,19 @@ pub fn handle_new_lox_credential(
open_lox_response: String, open_lox_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let req_state: lox_utils::OpenReqState = serde_json::from_str(&open_lox_result).unwrap(); let req_state: lox_utils::OpenReqState = match serde_json::from_str(&open_lox_result) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&open_lox_response).unwrap(); let deserialized_response = match serde_json::from_str(&open_lox_response) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let lox_cred = match open_invite::handle_response( let lox_cred = match open_invite::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -84,7 +79,7 @@ pub fn handle_new_lox_credential(
}; };
let lox_cred = lox_utils::LoxCredential { let lox_cred = lox_utils::LoxCredential {
lox_credential: lox_cred.0, lox_credential: lox_cred.0,
bridgeline: Some(lox_cred.1), bridgelines: Some(vec![lox_cred.1]),
invitation: None, invitation: None,
}; };
log(&format!( log(&format!(
@ -93,24 +88,29 @@ pub fn handle_new_lox_credential(
)); ));
log(&format!( log(&format!(
"Got new bridgeline: {}", "Got new bridgeline: {}",
serde_json::to_string(&lox_cred.bridgeline).unwrap() serde_json::to_string(&lox_cred.bridgelines).unwrap()
)); ));
Ok(serde_json::to_string(&lox_cred).unwrap()) match serde_json::to_string(&lox_cred) {
Ok(lox_cred) => Ok(lox_cred),
Err(e) => {
log(&format!("Error: {:?}", e.to_string()));
Err(JsValue::from(e.to_string()))
}
}
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn trust_promotion(open_lox_cred: String, lox_pub: String) -> Result<String, JsValue> { pub fn trust_promotion(open_lox_cred: String, lox_pub: String) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = serde_json::from_str(&open_lox_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&open_lox_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
// To test creation of the credential we need to advance the day to 30 Err(e) => return Err(JsValue::from(e.to_string())),
// in production this should just use the today() function };
log(&format!( let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
"TEST ONLY: Add 31 days to today's date: {}", Ok(pubkeys) => pubkeys,
test_today(31) Err(e) => return Err(JsValue::from(e.to_string())),
)); };
let tp_result = let tp_result =
//CHANGE add_today(31) to today() for production match trust_promotion::request(&lox_cred.lox_credential, &pubkeys.lox_pub, today()) {
match trust_promotion::request(&lox_cred.lox_credential, &pubkeys.lox_pub, test_today(31)) {
Ok(tp_result) => tp_result, Ok(tp_result) => tp_result,
Err(e) => { Err(e) => {
log(&format!("Error: {:?}", e.to_string())); log(&format!("Error: {:?}", e.to_string()));
@ -125,7 +125,10 @@ pub fn trust_promotion(open_lox_cred: String, lox_pub: String) -> Result<String,
"Formatted Trust Promotion request: {}", "Formatted Trust Promotion request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -133,9 +136,15 @@ pub fn handle_trust_promotion(
trust_promo_request: String, trust_promo_request: String,
trust_promo_response: String, trust_promo_response: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let req_state: lox_utils::TrustReqState = serde_json::from_str(&trust_promo_request).unwrap(); let req_state: lox_utils::TrustReqState = match serde_json::from_str(&trust_promo_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&trust_promo_response).unwrap(); let deserialized_response = match serde_json::from_str(&trust_promo_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let migration_cred = let migration_cred =
match trust_promotion::handle_response(deserialized_state, deserialized_response) { match trust_promotion::handle_response(deserialized_state, deserialized_response) {
Ok(migration_cred) => migration_cred, Ok(migration_cred) => migration_cred,
@ -148,7 +157,10 @@ pub fn handle_trust_promotion(
"Got new Migration Credential: {}", "Got new Migration Credential: {}",
serde_json::to_string(&migration_cred).unwrap() serde_json::to_string(&migration_cred).unwrap()
)); ));
Ok(serde_json::to_string(&migration_cred).unwrap()) match serde_json::to_string(&migration_cred) {
Ok(migration_cred) => Ok(migration_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -157,8 +169,14 @@ pub fn trust_migration(
trust_promo_cred: String, trust_promo_cred: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = serde_json::from_str(&open_lox_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&open_lox_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let mig_cred: Migration = serde_json::from_str(&trust_promo_cred).unwrap(); let mig_cred: Migration = serde_json::from_str(&trust_promo_cred).unwrap();
let tm_result = match migration::request( let tm_result = match migration::request(
&lox_cred.lox_credential, &lox_cred.lox_credential,
@ -180,7 +198,10 @@ pub fn trust_migration(
"Formatted Trust Migration request: {}", "Formatted Trust Migration request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -189,10 +210,19 @@ pub fn handle_trust_migration(
trust_migration_response: String, trust_migration_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
let req_state: lox_utils::MigReqState = serde_json::from_str(&trust_migration_request).unwrap(); Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let req_state: lox_utils::MigReqState = match serde_json::from_str(&trust_migration_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&trust_migration_response).unwrap(); let deserialized_response = match serde_json::from_str(&trust_migration_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let level_one_cred = match migration::handle_response( let level_one_cred = match migration::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -200,7 +230,7 @@ pub fn handle_trust_migration(
) { ) {
Ok(level_1_cred) => lox_utils::LoxCredential { Ok(level_1_cred) => lox_utils::LoxCredential {
lox_credential: level_1_cred, lox_credential: level_1_cred,
bridgeline: None, bridgelines: None,
invitation: None, invitation: None,
}, },
Err(e) => { Err(e) => {
@ -212,7 +242,11 @@ pub fn handle_trust_migration(
"Got new Level 1 Credential: {}", "Got new Level 1 Credential: {}",
serde_json::to_string(&level_one_cred).unwrap() serde_json::to_string(&level_one_cred).unwrap()
)); ));
Ok(serde_json::to_string(&level_one_cred).unwrap())
match serde_json::to_string(&level_one_cred) {
Ok(level_one_cred) => Ok(level_one_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -221,31 +255,24 @@ pub fn level_up(
encrypted_table: String, encrypted_table: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = serde_json::from_str(&level_one_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&level_one_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let reach_cred = let reach_cred =
lox_utils::generate_reachability_cred(&lox_cred.lox_credential, encrypted_table); lox_utils::generate_reachability_cred(&lox_cred.lox_credential, encrypted_table);
// To test level up of the credential we need to advance the day to the correct interval let lu_result = match level_up::request(
// In this case, the maximum of 85 can be used to test all level ups &lox_cred.lox_credential,
// in production this should just use the today() function &reach_cred,
// decrypt trust level and use to calculate the correct date for now &pubkeys.lox_pub,
// The trust level has to be at least 1 &pubkeys.reachability_pub,
let test_cumulative_days = match calc_test_days(&lox_cred.lox_credential) { today(),
Ok(v) => v, ) {
Err(e) => {
log(&format!("Error: {:?}", e));
return Err(JsValue::from(e));
}
};
log(&format!(
"TEST ONLY: Add 31 (open invitation) + Trust Level*85 days to today's date: {}",
test_today(test_cumulative_days)
));
let lu_result =
//CHANGE add_today(31) to today() for production
match level_up::request(&lox_cred.lox_credential, &reach_cred, &pubkeys.lox_pub, &pubkeys.reachability_pub, test_today(test_cumulative_days)) {
Ok(lu_result) => lu_result, Ok(lu_result) => lu_result,
Err(e) => { Err(e) => {
log(&format!("Error: {:?}", e.to_string())); log(&format!("Error: {:?}", e.to_string()));
@ -260,7 +287,10 @@ pub fn level_up(
"Formatted Level Up request: {}", "Formatted Level Up request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -269,10 +299,19 @@ pub fn handle_level_up(
levelup_response: String, levelup_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
let req_state: lox_utils::LevelupReqState = serde_json::from_str(&levelup_request).unwrap(); Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let req_state: lox_utils::LevelupReqState = match serde_json::from_str(&levelup_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&levelup_response).unwrap(); let deserialized_response = match serde_json::from_str(&levelup_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let level_up_cred = match level_up::handle_response( let level_up_cred = match level_up::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -280,7 +319,7 @@ pub fn handle_level_up(
) { ) {
Ok(level_up_cred) => lox_utils::LoxCredential { Ok(level_up_cred) => lox_utils::LoxCredential {
lox_credential: level_up_cred, lox_credential: level_up_cred,
bridgeline: None, bridgelines: None,
invitation: None, invitation: None,
}, },
Err(e) => { Err(e) => {
@ -292,7 +331,10 @@ pub fn handle_level_up(
"Got new Level Up Credential: {}", "Got new Level Up Credential: {}",
serde_json::to_string(&level_up_cred).unwrap() serde_json::to_string(&level_up_cred).unwrap()
)); ));
Ok(serde_json::to_string(&level_up_cred).unwrap()) match serde_json::to_string(&level_up_cred) {
Ok(level_up_cred) => Ok(level_up_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -301,8 +343,14 @@ pub fn issue_invite(
encrypted_table: String, encrypted_table: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = serde_json::from_str(&trusted_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&trusted_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let reach_cred = let reach_cred =
lox_utils::generate_reachability_cred(&lox_cred.lox_credential, encrypted_table); lox_utils::generate_reachability_cred(&lox_cred.lox_credential, encrypted_table);
@ -311,7 +359,7 @@ pub fn issue_invite(
&reach_cred, &reach_cred,
&pubkeys.lox_pub, &pubkeys.lox_pub,
&pubkeys.reachability_pub, &pubkeys.reachability_pub,
test_today(371), today(),
) { ) {
Ok(issue_result) => issue_result, Ok(issue_result) => issue_result,
Err(e) => { Err(e) => {
@ -327,7 +375,10 @@ pub fn issue_invite(
"Formatted Issue Invite request: {}", "Formatted Issue Invite request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -336,11 +387,20 @@ pub fn handle_issue_invite(
issue_invite_response: String, issue_invite_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let req_state: lox_utils::IssueInviteReqState = let req_state: lox_utils::IssueInviteReqState =
serde_json::from_str(&issue_invite_request).unwrap(); match serde_json::from_str(&issue_invite_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&issue_invite_response).unwrap(); let deserialized_response = match serde_json::from_str(&issue_invite_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let issue_invite_cred = match issue_invite::handle_response( let issue_invite_cred = match issue_invite::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -355,7 +415,7 @@ pub fn handle_issue_invite(
}; };
let invitation_cred = lox_utils::LoxCredential { let invitation_cred = lox_utils::LoxCredential {
lox_credential: issue_invite_cred.0, lox_credential: issue_invite_cred.0,
bridgeline: None, bridgelines: None,
invitation: Some(issue_invite_cred.1), invitation: Some(issue_invite_cred.1),
}; };
@ -363,27 +423,42 @@ pub fn handle_issue_invite(
"Got new Invitation Credential and Lox Credential: {}", "Got new Invitation Credential and Lox Credential: {}",
serde_json::to_string(&invitation_cred).unwrap() serde_json::to_string(&invitation_cred).unwrap()
)); ));
Ok(serde_json::to_string(&invitation_cred).unwrap()) match serde_json::to_string(&invitation_cred) {
Ok(invitation_cred) => Ok(invitation_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
// Separate Trusted Invite from credential prior to passing it to friend // Separate Trusted Invite from credential prior to passing it to friend
#[wasm_bindgen] #[wasm_bindgen]
pub fn prepare_invite(invitation_cred: String) -> String { pub fn prepare_invite(invitation_cred: String) -> Result<String, JsValue> {
let cred: lox_utils::LoxCredential = serde_json::from_str(&invitation_cred).unwrap(); let cred: lox_utils::LoxCredential = match serde_json::from_str(&invitation_cred) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
log(&format!( log(&format!(
"Prepared Invitation: {}", "Prepared Invitation: {}",
serde_json::to_string(&cred.invitation).unwrap() serde_json::to_string(&cred.invitation).unwrap()
)); ));
serde_json::to_string(&cred.invitation).unwrap() match serde_json::to_string(&cred.invitation) {
Ok(invitation) => Ok(invitation),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
// //
#[wasm_bindgen] #[wasm_bindgen]
pub fn redeem_invite(invitation: String, lox_pub: String) -> Result<String, JsValue> { pub fn redeem_invite(invitation: String, lox_pub: String) -> Result<String, JsValue> {
let invitation_cred: Invitation = serde_json::from_str(&invitation).unwrap(); let invitation_cred: Invitation = match serde_json::from_str(&invitation) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(invitation_cred) => invitation_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let redeem_result = let redeem_result =
match redeem_invite::request(&invitation_cred, &pubkeys.invitation_pub, test_today(371)) { match redeem_invite::request(&invitation_cred, &pubkeys.invitation_pub, today()) {
Ok(redeem_result) => redeem_result, Ok(redeem_result) => redeem_result,
Err(e) => { Err(e) => {
log(&format!("Error: {:?}", e.to_string())); log(&format!("Error: {:?}", e.to_string()));
@ -398,7 +473,10 @@ pub fn redeem_invite(invitation: String, lox_pub: String) -> Result<String, JsVa
"Formatted Redeem Invite request: {}", "Formatted Redeem Invite request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -407,11 +485,19 @@ pub fn handle_redeem_invite(
redeem_invite_response: String, redeem_invite_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
let req_state: lox_utils::RedeemReqState = Ok(pubkeys) => pubkeys,
serde_json::from_str(&redeem_invite_request).unwrap(); Err(e) => return Err(JsValue::from(e.to_string())),
};
let req_state: lox_utils::RedeemReqState = match serde_json::from_str(&redeem_invite_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&redeem_invite_response).unwrap(); let deserialized_response = match serde_json::from_str(&redeem_invite_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let redeem_invite_cred = match redeem_invite::handle_response( let redeem_invite_cred = match redeem_invite::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -419,7 +505,7 @@ pub fn handle_redeem_invite(
) { ) {
Ok(issue_invite_cred) => lox_utils::LoxCredential { Ok(issue_invite_cred) => lox_utils::LoxCredential {
lox_credential: issue_invite_cred, lox_credential: issue_invite_cred,
bridgeline: None, bridgelines: None,
invitation: None, invitation: None,
}, },
Err(e) => { Err(e) => {
@ -431,14 +517,23 @@ pub fn handle_redeem_invite(
"Got new Trusted Lox Credential from Invitation: {}", "Got new Trusted Lox Credential from Invitation: {}",
serde_json::to_string(&redeem_invite_cred).unwrap() serde_json::to_string(&redeem_invite_cred).unwrap()
)); ));
Ok(serde_json::to_string(&redeem_invite_cred).unwrap()) match serde_json::to_string(&redeem_invite_cred) {
Ok(redeem_invite_cred) => Ok(redeem_invite_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn check_blockage(lox_cred: String, lox_pub: String) -> Result<String, JsValue> { pub fn check_blockage(lox_cred: String, lox_pub: String) -> Result<String, JsValue> {
let lox: lox_utils::LoxCredential = serde_json::from_str(&lox_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
let cb_result = match check_blockage::request(&lox.lox_credential, &pubkeys.lox_pub) { Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let cb_result = match check_blockage::request(&lox_cred.lox_credential, &pubkeys.lox_pub) {
Ok(cb_result) => cb_result, Ok(cb_result) => cb_result,
Err(e) => { Err(e) => {
log(&format!("Error: {:?}", e.to_string())); log(&format!("Error: {:?}", e.to_string()));
@ -453,7 +548,10 @@ pub fn check_blockage(lox_cred: String, lox_pub: String) -> Result<String, JsVal
"Formatted Check Blockage request: {}", "Formatted Check Blockage request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -462,9 +560,15 @@ pub fn handle_check_blockage(
check_blockage_response: String, check_blockage_response: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let req_state: lox_utils::CheckBlockageReqState = let req_state: lox_utils::CheckBlockageReqState =
serde_json::from_str(&check_blockage_request).unwrap(); match serde_json::from_str(&check_blockage_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&check_blockage_response).unwrap(); let deserialized_response = match serde_json::from_str(&check_blockage_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let migration_cred = let migration_cred =
match check_blockage::handle_response(deserialized_state, deserialized_response) { match check_blockage::handle_response(deserialized_state, deserialized_response) {
Ok(migration_cred) => migration_cred, Ok(migration_cred) => migration_cred,
@ -477,7 +581,10 @@ pub fn handle_check_blockage(
"Got new Blockage Migration Credential: {}", "Got new Blockage Migration Credential: {}",
serde_json::to_string(&migration_cred).unwrap() serde_json::to_string(&migration_cred).unwrap()
)); ));
Ok(serde_json::to_string(&migration_cred).unwrap()) match serde_json::to_string(&migration_cred) {
Ok(migration_cred) => Ok(migration_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -486,8 +593,14 @@ pub fn blockage_migration(
check_migration_cred: String, check_migration_cred: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = serde_json::from_str(&lox_cred).unwrap(); let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred) {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let mig_cred: Migration = serde_json::from_str(&check_migration_cred).unwrap(); let mig_cred: Migration = serde_json::from_str(&check_migration_cred).unwrap();
let bm_result = match blockage_migration::request( let bm_result = match blockage_migration::request(
&lox_cred.lox_credential, &lox_cred.lox_credential,
@ -509,7 +622,10 @@ pub fn blockage_migration(
"Formatted Blockage Migration request: {}", "Formatted Blockage Migration request: {}",
serde_json::to_string(&req_state).unwrap() serde_json::to_string(&req_state).unwrap()
)); ));
Ok(serde_json::to_string(&req_state).unwrap()) match serde_json::to_string(&req_state) {
Ok(req_state) => Ok(req_state),
Err(e) => Err(JsValue::from(e.to_string())),
}
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -518,11 +634,20 @@ pub fn handle_blockage_migration(
blockage_migration_response: String, blockage_migration_response: String,
lox_pub: String, lox_pub: String,
) -> Result<String, JsValue> { ) -> Result<String, JsValue> {
let pubkeys: lox_utils::PubKeys = serde_json::from_str(&lox_pub).unwrap(); let pubkeys: lox_utils::PubKeys = match serde_json::from_str(&lox_pub) {
Ok(pubkeys) => pubkeys,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let req_state: lox_utils::BlockageMigReqState = let req_state: lox_utils::BlockageMigReqState =
serde_json::from_str(&blockage_migration_request).unwrap(); match serde_json::from_str(&blockage_migration_request) {
Ok(req_state) => req_state,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let deserialized_state = req_state.state; let deserialized_state = req_state.state;
let deserialized_response = serde_json::from_str(&blockage_migration_response).unwrap(); let deserialized_response = match serde_json::from_str(&blockage_migration_response) {
Ok(deserialized_response) => deserialized_response,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let lox_cred = match blockage_migration::handle_response( let lox_cred = match blockage_migration::handle_response(
deserialized_state, deserialized_state,
deserialized_response, deserialized_response,
@ -530,7 +655,7 @@ pub fn handle_blockage_migration(
) { ) {
Ok(lox_cred) => lox_utils::LoxCredential { Ok(lox_cred) => lox_utils::LoxCredential {
lox_credential: lox_cred, lox_credential: lox_cred,
bridgeline: None, bridgelines: None,
invitation: None, invitation: None,
}, },
Err(e) => { Err(e) => {
@ -542,5 +667,144 @@ pub fn handle_blockage_migration(
"Got new Lox Credential after Migration: {}", "Got new Lox Credential after Migration: {}",
serde_json::to_string(&lox_cred).unwrap() serde_json::to_string(&lox_cred).unwrap()
)); ));
Ok(serde_json::to_string(&lox_cred).unwrap()) match serde_json::to_string(&lox_cred) {
Ok(lox_cred) => Ok(lox_cred),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
#[wasm_bindgen]
pub fn get_last_upgrade_time(lox_cred_str: String) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let upgrade_date = scalar_u32(&lox_cred.lox_credential.level_since).unwrap();
let date_time = JulianDay::new(upgrade_date as i32).to_date();
log(&format!(
"Time of last upgrade {}",
serde_json::to_string(&date_time).unwrap()
));
match serde_json::to_string(&date_time) {
Ok(date_str) => Ok(date_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
#[wasm_bindgen]
pub fn get_trust_level(lox_cred_str: String) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let trust_level = scalar_u32(&lox_cred.lox_credential.trust_level).unwrap();
log(&format!(
"Trust level {}",
serde_json::to_string(&trust_level).unwrap()
));
match serde_json::to_string(&trust_level) {
Ok(trust_str) => Ok(trust_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
#[wasm_bindgen]
pub fn get_invites_remaining(lox_cred_str: String) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let invites = scalar_u32(&lox_cred.lox_credential.invites_remaining);
log(&format!(
"Invites remaining {}",
serde_json::to_string(&invites).unwrap()
));
match serde_json::to_string(&invites) {
Ok(invite_str) => Ok(invite_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
#[wasm_bindgen]
pub fn get_issued_invite_expiry(lox_cred_str: String) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
match lox_cred.invitation {
Some(invitation) => {
let expiry = (scalar_u32(&invitation.date).unwrap() + 15) as i32;
let date_time = JulianDay::new(expiry).to_date();
println!("Datetime is: {:?}", date_time);
log(&format!(
"Invitation Expiry {}",
serde_json::to_string(&date_time).unwrap()
));
match serde_json::to_string(&date_time) {
Ok(inv_date_str) => Ok(inv_date_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
None => Err(JsValue::from("No Invitation Issued")),
}
}
#[wasm_bindgen]
pub fn get_received_invite_expiry(invite_cred_str: String) -> Result<String, JsValue> {
let invite_cred: lox_utils::IssuedInvitation = match serde_json::from_str(&invite_cred_str) {
Ok(invite_cred) => invite_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let expiry = (scalar_u32(&invite_cred.invitation.date).unwrap() + 15) as i32;
let date_time = JulianDay::new(expiry).to_date();
println!("Datetime is: {:?}", date_time);
log(&format!(
"Invitation Expiry {}",
serde_json::to_string(&date_time).unwrap()
));
match serde_json::to_string(&date_time) {
Ok(date_str) => Ok(date_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
#[wasm_bindgen]
pub fn get_bridgelines_from_bucket(
lox_cred_str: String,
encrypted_table: String,
) -> Result<String, JsValue> {
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
Ok(lox_cred) => lox_cred,
Err(e) => return Err(JsValue::from(e.to_string())),
};
let bridgelines =
lox_utils::get_credential_bridgelines(&lox_cred.lox_credential, encrypted_table);
log(&format!(
"Lox BridgeLines available {}",
serde_json::to_string(&bridgelines).unwrap()
));
match serde_json::to_string(&bridgelines) {
Ok(bridgelines_str) => Ok(bridgelines_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
pub fn get_constants() -> Result<String, JsValue> {
match serde_json::to_string(&lox_utils::LOX_SYSTEM_INFO) {
Ok(system_info_str) => Ok(system_info_str),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
pub fn invitation_is_trusted(unspecified_invitation_str: String) -> Result<bool, JsValue> {
match serde_json::from_str::<Invitation>(&unspecified_invitation_str) {
Ok(_) => Ok(true),
Err(_) => {
let invite = unspecified_invitation_str.as_bytes();
match lox_utils::validate(invite) {
Ok(_) => Ok(false),
Err(e) => Err(JsValue::from(e.to_string())),
}
}
}
} }

View File

@ -4,11 +4,12 @@ authors = ["Cecylia Bocovich <cohosh@torproject.org>, Lindsey Tulloch <onyinyang
version = "0.2.0" version = "0.2.0"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
description = "A backend API to receive resources from rdsys"
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home" homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
keywords = ["tor", "lox", "bridges","censorship-resistance"] keywords = ["tor", "lox", "bridges","anti-censorship", "API"]
categories = ["api-bindings", "encoding"] categories = ["api-bindings", "encoding"]
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/rdsys-backend-api" repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/rdsys-backend-api"
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/rdsys-backend-api/README.md" readme = "README.md"
[dependencies] [dependencies]

View File

@ -1,8 +1,12 @@
# rdsys backend API # rdsys backend API
### Usage The rdsys backend API allows a process to receive resources from rdsys through either of rdsys' two endpoints.
```rust ### Usage with Stream Endpoint
To test or receive a resourcediff from rdsys, the rdsys `resource-stream` endpoint can be accessed with the following sample code:
```
use rdsys_backend::start_stream; use rdsys_backend::start_stream;
use tokio; use tokio;
@ -18,3 +22,22 @@ async fn main() {
} }
} }
``` ```
### Usage with Static Request Endpoint
To test or receive a ResourceState from rdsys, the `resources` endpoint can be accessed with the following sample code:
```
use rdsys_backend::request_resources;
use tokio;
#[tokio::main]
async fn main() {
let endpoint = String::from("http://127.0.0.1:7100/resources");
let name = String::from("https");
let token = String::from("HttpsApiTokenPlaceholder");
let types = vec![String::from("obfs4"), String::from("scramblesuit")];
let rx = request_resources(endpoint, name, token, types).await.unwrap();
println!("Received ResourceState: {:?}", rx);
}
```

View File

@ -284,8 +284,7 @@ pub async fn request_resources(
.header("Authorization", &auth_value) .header("Authorization", &auth_value)
.body(json) .body(json)
.send() .send()
.await .await?;
.unwrap();
match response.status() { match response.status() {
reqwest::StatusCode::OK => { reqwest::StatusCode::OK => {
fetched_resources = match response.json::<proto::ResourceState>().await { fetched_resources = match response.json::<proto::ResourceState>().await {