|
@@ -1,12 +1,15 @@
|
|
|
use async_trait::async_trait;
|
|
|
use curve25519_dalek::scalar::Scalar;
|
|
|
-use lox::bridge_table::BridgeLine;
|
|
|
-use lox::bridge_table::ENC_BUCKET_BYTES;
|
|
|
-use lox::proto::*;
|
|
|
-use lox::IssuerPubKey;
|
|
|
-use lox::OPENINV_LENGTH;
|
|
|
+use lox_library::bridge_table::BridgeLine;
|
|
|
+use lox_library::bridge_table::EncryptedBucket;
|
|
|
+use lox_library::proto::*;
|
|
|
+use lox_library::scalar_u32;
|
|
|
+use lox_library::IssuerPubKey;
|
|
|
+use lox_library::OPENINV_LENGTH;
|
|
|
+use lox_utils::EncBridgeTable;
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
use serde_with::serde_as;
|
|
|
+use std::collections::HashMap;
|
|
|
use std::time::Duration;
|
|
|
|
|
|
// used for testing function
|
|
@@ -26,42 +29,6 @@ pub struct Invite {
|
|
|
#[serde_as(as = "[_; OPENINV_LENGTH]")]
|
|
|
invite: [u8; OPENINV_LENGTH],
|
|
|
}
|
|
|
-#[serde_as]
|
|
|
-#[derive(Serialize, Deserialize)]
|
|
|
-pub struct EncBridgeTable {
|
|
|
- #[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")]
|
|
|
- etable: Vec<[u8; ENC_BUCKET_BYTES]>,
|
|
|
-}
|
|
|
-
|
|
|
-// These two functions should only be used for testing.
|
|
|
-// This file should probably belong to the client, not the library.
|
|
|
-const TIME_OFFSET_FILENAME: &str = "time_offset.json";
|
|
|
-fn get_time_offset() -> u32 {
|
|
|
- if std::path::Path::new(&TIME_OFFSET_FILENAME).exists() {
|
|
|
- let infile = std::fs::File::open(&TIME_OFFSET_FILENAME).unwrap();
|
|
|
- serde_json::from_reader(infile).unwrap()
|
|
|
- } else {
|
|
|
- 0
|
|
|
- }
|
|
|
-}
|
|
|
-fn save_time_offset(secs: &u32) {
|
|
|
- let mut outfile =
|
|
|
- std::fs::File::create(&TIME_OFFSET_FILENAME).expect("Failed to create time_offset");
|
|
|
- write!(outfile, "{}", serde_json::to_string(&secs).unwrap())
|
|
|
- .expect("Failed to write to time_offset");
|
|
|
-}
|
|
|
-
|
|
|
-/// Get today's (real or simulated) date
|
|
|
-///
|
|
|
-/// This function is modified from the lox lib.rs
|
|
|
-fn today(time_offset: Duration) -> u32 {
|
|
|
- // We will not encounter negative Julian dates (~6700 years ago)
|
|
|
- // or ones larger than 32 bits
|
|
|
- (time::OffsetDateTime::now_utc().date() + time_offset)
|
|
|
- .julian_day()
|
|
|
- .try_into()
|
|
|
- .unwrap()
|
|
|
-}
|
|
|
|
|
|
// Helper functions to get public keys from vector
|
|
|
pub fn get_lox_pub(lox_auth_pubkeys: &Vec<IssuerPubKey>) -> &IssuerPubKey {
|
|
@@ -86,7 +53,7 @@ pub fn get_invitation_pub(lox_auth_pubkeys: &Vec<IssuerPubKey>) -> &IssuerPubKey
|
|
|
|
|
|
// Helper function to get credential trust level as i8
|
|
|
// (Note that this value should only be 0-4)
|
|
|
-pub fn get_cred_trust_level(cred: &lox::cred::Lox) -> i8 {
|
|
|
+pub fn get_cred_trust_level(cred: &lox_library::cred::Lox) -> i8 {
|
|
|
let trust_levels: [Scalar; 5] = [
|
|
|
Scalar::zero(),
|
|
|
Scalar::one(),
|
|
@@ -102,6 +69,41 @@ pub fn get_cred_trust_level(cred: &lox::cred::Lox) -> i8 {
|
|
|
-1
|
|
|
}
|
|
|
|
|
|
+// Helper function to check if credential is eligible for
|
|
|
+// promotion from level 0 to 1
|
|
|
+pub async fn eligible_for_trust_promotion(
|
|
|
+ net: &dyn Networking,
|
|
|
+ cred: &lox_library::cred::Lox,
|
|
|
+) -> bool {
|
|
|
+ let level_since: u32 = match scalar_u32(&cred.level_since) {
|
|
|
+ Some(v) => v,
|
|
|
+ None => return false,
|
|
|
+ };
|
|
|
+ get_cred_trust_level(cred) == 0
|
|
|
+ && level_since + lox_library::proto::trust_promotion::UNTRUSTED_INTERVAL
|
|
|
+ <= get_today(net).await
|
|
|
+}
|
|
|
+
|
|
|
+// Helper function to check if credential is eligible for
|
|
|
+// level up from level 1+
|
|
|
+pub async fn eligible_for_level_up(net: &dyn Networking, cred: &lox_library::cred::Lox) -> bool {
|
|
|
+ let level_since: u32 = match scalar_u32(&cred.level_since) {
|
|
|
+ Some(v) => v,
|
|
|
+ None => return false,
|
|
|
+ };
|
|
|
+ let trust_level: usize = get_cred_trust_level(cred).try_into().unwrap();
|
|
|
+ trust_level > 0
|
|
|
+ && level_since + lox_library::proto::level_up::LEVEL_INTERVAL[trust_level]
|
|
|
+ <= get_today(net).await
|
|
|
+}
|
|
|
+
|
|
|
+// Get current date from Lox Auth
|
|
|
+pub async fn get_today(net: &dyn Networking) -> u32 {
|
|
|
+ let resp = net.request("/today".to_string(), [].to_vec()).await;
|
|
|
+ let today: u32 = serde_json::from_slice(&resp).unwrap();
|
|
|
+ today
|
|
|
+}
|
|
|
+
|
|
|
// Download Lox Auth pubkeys
|
|
|
pub async fn get_lox_auth_keys(net: &dyn Networking) -> Vec<IssuerPubKey> {
|
|
|
let resp = net.request("/pubkeys".to_string(), [].to_vec()).await;
|
|
@@ -110,7 +112,7 @@ pub async fn get_lox_auth_keys(net: &dyn Networking) -> Vec<IssuerPubKey> {
|
|
|
}
|
|
|
|
|
|
// Get encrypted bridge table
|
|
|
-pub async fn get_reachability_credential(net: &dyn Networking) -> Vec<[u8; ENC_BUCKET_BYTES]> {
|
|
|
+pub async fn get_reachability_credential(net: &dyn Networking) -> HashMap<u32, EncryptedBucket> {
|
|
|
let resp = net.request("/reachability".to_string(), [].to_vec()).await;
|
|
|
let reachability_cred: EncBridgeTable = serde_json::from_slice(&resp).unwrap();
|
|
|
reachability_cred.etable
|
|
@@ -128,7 +130,7 @@ pub async fn get_lox_credential(
|
|
|
net: &dyn Networking,
|
|
|
open_invite: &[u8; OPENINV_LENGTH],
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
-) -> (lox::cred::Lox, BridgeLine) {
|
|
|
+) -> (lox_library::cred::Lox, BridgeLine) {
|
|
|
let (req, state) = open_invite::request(&open_invite);
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
|
let encoded_resp = net.request("/openreq".to_string(), encoded_req).await;
|
|
@@ -140,16 +142,10 @@ pub async fn get_lox_credential(
|
|
|
// Get a migration credential to migrate to higher trust
|
|
|
pub async fn trust_promotion(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Migration {
|
|
|
- // FOR TESTING ONLY
|
|
|
- let time_offset = get_time_offset() + 60 * 60 * 24 * 31;
|
|
|
- save_time_offset(&time_offset);
|
|
|
-
|
|
|
- let (req, state) =
|
|
|
-// trust_promotion::request(&lox_cred, &lox_pub, today(Duration::ZERO)).unwrap();
|
|
|
- trust_promotion::request(&lox_cred, &lox_pub, today(Duration::from_secs(time_offset.into()))).unwrap(); // FOR TESTING ONLY
|
|
|
+) -> lox_library::cred::Migration {
|
|
|
+ let (req, state) = trust_promotion::request(&lox_cred, &lox_pub, get_today(net).await).unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
|
let encoded_resp = net.request("/trustpromo".to_string(), encoded_req).await;
|
|
|
let decoded_resp: trust_promotion::Response = serde_json::from_slice(&encoded_resp).unwrap();
|
|
@@ -160,11 +156,11 @@ pub async fn trust_promotion(
|
|
|
// Promote from untrusted (trust level 0) to trusted (trust level 1)
|
|
|
pub async fn trust_migration(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
- migration_cred: &lox::cred::Migration,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
+ migration_cred: &lox_library::cred::Migration,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
migration_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Lox {
|
|
|
+) -> lox_library::cred::Lox {
|
|
|
let (req, state) =
|
|
|
migration::request(lox_cred, migration_cred, lox_pub, migration_pub).unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
@@ -177,23 +173,22 @@ pub async fn trust_migration(
|
|
|
// Increase trust from at least level 1 to higher levels
|
|
|
pub async fn level_up(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
- encbuckets: &Vec<[u8; ENC_BUCKET_BYTES]>,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
+ encbuckets: &HashMap<u32, EncryptedBucket>,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
reachability_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Lox {
|
|
|
+) -> lox_library::cred::Lox {
|
|
|
// Read the bucket in the credential to get today's Bucket
|
|
|
// Reachability credential
|
|
|
-
|
|
|
- let (id, key) = lox::bridge_table::from_scalar(lox_cred.bucket).unwrap();
|
|
|
- let bucket =
|
|
|
- lox::bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
|
|
|
+ let (id, key) = lox_library::bridge_table::from_scalar(lox_cred.bucket).unwrap();
|
|
|
+ let bucket = lox_library::bridge_table::BridgeTable::decrypt_bucket(
|
|
|
+ id,
|
|
|
+ &key,
|
|
|
+ &encbuckets.get(&id).unwrap(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
let reachcred = bucket.1.unwrap();
|
|
|
|
|
|
- // FOR TESTING ONLY
|
|
|
- let time_offset = get_time_offset() + 60 * 60 * 24 * 85;
|
|
|
- save_time_offset(&time_offset);
|
|
|
-
|
|
|
// Use the Bucket Reachability credential to advance to the next
|
|
|
// level
|
|
|
let (req, state) = level_up::request(
|
|
@@ -201,8 +196,7 @@ pub async fn level_up(
|
|
|
&reachcred,
|
|
|
lox_pub,
|
|
|
reachability_pub,
|
|
|
- //today(Duration::ZERO),
|
|
|
- today(Duration::from_secs(time_offset.into())), // FOR TESTING ONLY
|
|
|
+ get_today(net).await,
|
|
|
)
|
|
|
.unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
@@ -215,18 +209,22 @@ pub async fn level_up(
|
|
|
// Request an Invitation credential to give to a friend
|
|
|
pub async fn issue_invite(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
- encbuckets: &Vec<[u8; ENC_BUCKET_BYTES]>,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
+ encbuckets: &HashMap<u32, EncryptedBucket>,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
reachability_pub: &IssuerPubKey,
|
|
|
invitation_pub: &IssuerPubKey,
|
|
|
-) -> (lox::cred::Lox, lox::cred::Invitation) {
|
|
|
+) -> (lox_library::cred::Lox, lox_library::cred::Invitation) {
|
|
|
// Read the bucket in the credential to get today's Bucket
|
|
|
// Reachability credential
|
|
|
|
|
|
- let (id, key) = lox::bridge_table::from_scalar(lox_cred.bucket).unwrap();
|
|
|
- let bucket =
|
|
|
- lox::bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
|
|
|
+ let (id, key) = lox_library::bridge_table::from_scalar(lox_cred.bucket).unwrap();
|
|
|
+ let bucket = lox_library::bridge_table::BridgeTable::decrypt_bucket(
|
|
|
+ id,
|
|
|
+ &key,
|
|
|
+ &encbuckets.get(&id).unwrap(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
let reachcred = bucket.1.unwrap();
|
|
|
|
|
|
let (req, state) = issue_invite::request(
|
|
@@ -234,7 +232,7 @@ pub async fn issue_invite(
|
|
|
&reachcred,
|
|
|
lox_pub,
|
|
|
reachability_pub,
|
|
|
- today(Duration::ZERO),
|
|
|
+ get_today(net).await,
|
|
|
)
|
|
|
.unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
@@ -248,12 +246,12 @@ pub async fn issue_invite(
|
|
|
// Redeem an Invitation credential to start at trust level 1
|
|
|
pub async fn redeem_invite(
|
|
|
net: &dyn Networking,
|
|
|
- invite: &lox::cred::Invitation,
|
|
|
+ invite: &lox_library::cred::Invitation,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
invitation_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Lox {
|
|
|
+) -> lox_library::cred::Lox {
|
|
|
let (req, state) =
|
|
|
- redeem_invite::request(invite, invitation_pub, today(Duration::ZERO)).unwrap();
|
|
|
+ redeem_invite::request(invite, invitation_pub, get_today(net).await).unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
|
let encoded_resp = net.request("/redeem".to_string(), encoded_req).await;
|
|
|
let decoded_resp: redeem_invite::Response = serde_json::from_slice(&encoded_resp).unwrap();
|
|
@@ -264,9 +262,9 @@ pub async fn redeem_invite(
|
|
|
// Check for a migration credential to move to a new bucket
|
|
|
pub async fn check_blockage(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Migration {
|
|
|
+) -> lox_library::cred::Migration {
|
|
|
let (req, state) = check_blockage::request(lox_cred, lox_pub).unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
|
let encoded_resp = net.request("/checkblockage".to_string(), encoded_req).await;
|
|
@@ -278,11 +276,11 @@ pub async fn check_blockage(
|
|
|
// Migrate to a new bucket (must be level >= 3)
|
|
|
pub async fn blockage_migration(
|
|
|
net: &dyn Networking,
|
|
|
- lox_cred: &lox::cred::Lox,
|
|
|
- migcred: &lox::cred::Migration,
|
|
|
+ lox_cred: &lox_library::cred::Lox,
|
|
|
+ migcred: &lox_library::cred::Migration,
|
|
|
lox_pub: &IssuerPubKey,
|
|
|
migration_pub: &IssuerPubKey,
|
|
|
-) -> lox::cred::Lox {
|
|
|
+) -> lox_library::cred::Lox {
|
|
|
let (req, state) =
|
|
|
blockage_migration::request(lox_cred, migcred, lox_pub, migration_pub).unwrap();
|
|
|
let encoded_req: Vec<u8> = serde_json::to_vec(&req).unwrap();
|
|
@@ -293,3 +291,15 @@ pub async fn blockage_migration(
|
|
|
let cred = blockage_migration::handle_response(state, decoded_resp, lox_pub).unwrap();
|
|
|
cred
|
|
|
}
|
|
|
+
|
|
|
+// Advance days on server (ONLY FOR TESTING)
|
|
|
+pub async fn advance_days(net: &dyn Networking, days: u16) -> u32 {
|
|
|
+ let resp = net
|
|
|
+ .request(
|
|
|
+ "/advancedays".to_string(),
|
|
|
+ serde_json::to_vec(&days).unwrap(),
|
|
|
+ )
|
|
|
+ .await;
|
|
|
+ let today: u32 = serde_json::from_slice(&resp).unwrap();
|
|
|
+ today
|
|
|
+}
|