From cf19bf80ee1ef8d9b468c9f26f2102ec10d43b98 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 18:26:58 -0400 Subject: [PATCH] Make an easier to use test harness --- crates/lox-library/src/tests.rs | 403 +++++++++++++++++--------------- 1 file changed, 216 insertions(+), 187 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1778c50..a960fd9 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -5,272 +5,301 @@ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +struct TestHarness { + bdb: BridgeDb, + pub ba: BridgeAuth, +} + +impl TestHarness { + fn new() -> Self { + // Create a BridegDb + let bdb = BridgeDb::new(15); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 15 buckets with one random bridge each + for _ in 0..15 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // Make 5 more buckets, each containing 3 of the previously + // created bridges + for i in 0u32..5 { + let iusize = i as usize; + let bucket: [BridgeLine; 3] = [ + ba.bridge_table.buckets[3 * iusize][0], + ba.bridge_table.buckets[3 * iusize + 1][0], + ba.bridge_table.buckets[3 * iusize + 2][0], + ]; + ba.bridge_table.new_bucket(bucket); + // Add the allowed migrations to the migration table + ba.migration_table.table.insert(3 * i, 15 + i); + ba.migration_table.table.insert(3 * i + 1, 15 + i); + ba.migration_table.table.insert(3 * i + 2, 15 + i); + } + // Create the encrypted bridge table + ba.enc_bridge_table(); + + Self { bdb, ba } + } + + fn advance_days(&mut self, days: u16) { + self.ba.advance_days(days); + } + + fn open_invite(&mut self) -> cred::Lox { + // Issue an open invitation + let inv = self.bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = self.ba.handle_open_invite(req).unwrap(); + open_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } + + fn trust_promotion(&mut self, cred: &cred::Lox) -> cred::Migration { + let (promreq, promstate) = + trust_promotion::request(&cred, &self.ba.lox_pub, self.ba.today()).unwrap(); + let promresp = self.ba.handle_trust_promotion(promreq).unwrap(); + trust_promotion::handle_response(promstate, promresp).unwrap() + } + + fn level0_migration(&mut self, loxcred: &cred::Lox, migcred: &cred::Migration) -> cred::Lox { + let (migreq, migstate) = + migration::request(loxcred, migcred, &self.ba.lox_pub, &self.ba.migration_pub).unwrap(); + let migresp = self.ba.handle_migration(migreq).unwrap(); + migration::handle_response(migstate, migresp, &self.ba.lox_pub).unwrap() + } + + fn level_up(&mut self, cred: &cred::Lox) -> cred::Lox { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = self.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + // Use the Bucket Reachability credential to advance to the next + // level + let (req, state) = level_up::request( + &cred, + &reachcred, + &self.ba.lox_pub, + &self.ba.reachability_pub, + self.ba.today(), + ) + .unwrap(); + let resp = self.ba.handle_level_up(req).unwrap(); + level_up::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } + + fn issue_invite(&mut self, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = self.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + let (req, state) = issue_invite::request( + &cred, + &reachcred, + &self.ba.lox_pub, + &self.ba.reachability_pub, + self.ba.today(), + ) + .unwrap(); + let resp = self.ba.handle_issue_invite(req).unwrap(); + issue_invite::handle_response(state, resp, &self.ba.lox_pub, &self.ba.invitation_pub) + .unwrap() + } + + fn redeem_invite(&mut self, inv: &cred::Invitation) -> cred::Lox { + let (req, state) = + redeem_invite::request(&inv, &self.ba.invitation_pub, self.ba.today()).unwrap(); + let resp = self.ba.handle_redeem_invite(req).unwrap(); + redeem_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } +} + #[test] fn test_open_invite() { - // Create a BridegDb - let bdb = BridgeDb::new(20); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); + let mut th = TestHarness::new(); - // Make 20 buckets with one random bridge each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // And 20 more with three random bridges each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = [ - BridgeLine::random(), - BridgeLine::random(), - BridgeLine::random(), - ]; - ba.bridge_table.new_bucket(bucket); - } - // Create the encrypted bridge table - ba.enc_bridge_table(); - - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); + // Join an untrusted user + let cred = th.open_invite(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); assert!(bucket.1.is_none()); - assert!(ba.verify_lox(&cred)); -} - -fn setup() -> (BridgeDb, BridgeAuth) { - // Create a BridegDb - let bdb = BridgeDb::new(15); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); - - // Make 15 buckets with one random bridge each - for _ in 0..15 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // Make 5 more buckets, each containing 3 of the previously - // created bridges - for i in 0u32..5 { - let iusize = i as usize; - let bucket: [BridgeLine; 3] = [ - ba.bridge_table.buckets[3 * iusize][0], - ba.bridge_table.buckets[3 * iusize + 1][0], - ba.bridge_table.buckets[3 * iusize + 2][0], - ]; - ba.bridge_table.new_bucket(bucket); - // Add the allowed migrations to the migration table - ba.migration_table.table.insert(3 * i, 15 + i); - ba.migration_table.table.insert(3 * i + 1, 15 + i); - ba.migration_table.table.insert(3 * i + 2, 15 + i); - } - // Create the encrypted bridge table - ba.enc_bridge_table(); - - (bdb, ba) -} - -fn trust_promotion(bdb: &BridgeDb, ba: &mut BridgeAuth) -> (cred::Lox, cred::Migration) { - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); - assert!(ba.verify_lox(&cred)); - - // Time passes - ba.advance_days(47); - - let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); - let promresp = ba.handle_trust_promotion(promreq).unwrap(); - let migcred = trust_promotion::handle_response(promstate, promresp).unwrap(); - - (cred, migcred) + assert!(th.ba.verify_lox(&cred)); } #[test] fn test_trust_promotion() { - let (bdb, mut ba) = setup(); + let mut th = TestHarness::new(); - let (_loxcred, migcred) = trust_promotion(&bdb, &mut ba); + let cred = th.open_invite(); + assert!(th.ba.verify_lox(&cred)); + + // Time passes + th.advance_days(47); + + let migcred = th.trust_promotion(&cred); + assert!(th.ba.verify_migration(&migcred)); - assert!(ba.verify_migration(&migcred)); // Check that we can use the to_bucket in the Migration credenital // to read a bucket let (id, key) = bridge_table::from_scalar(migcred.to_bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); - assert!(ba.verify_reachability(&bucket.1.unwrap())); -} - -fn level0_migration(bdb: &BridgeDb, ba: &mut BridgeAuth) -> cred::Lox { - let (loxcred, migcred) = trust_promotion(bdb, ba); - - let (migreq, migstate) = - migration::request(&loxcred, &migcred, &ba.lox_pub, &ba.migration_pub).unwrap(); - let migresp = ba.handle_migration(migreq).unwrap(); - let newloxcred = migration::handle_response(migstate, migresp, &ba.lox_pub).unwrap(); - newloxcred + assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } #[test] fn test_level0_migration() { - let (bdb, mut ba) = setup(); + let mut th = TestHarness::new(); - let newloxcred = level0_migration(&bdb, &mut ba); + let cred = th.open_invite(); + assert!(th.ba.verify_lox(&cred)); - assert!(ba.verify_lox(&newloxcred)); + // Time passes + th.advance_days(47); + + let migcred = th.trust_promotion(&cred); + assert!(th.ba.verify_migration(&migcred)); + + let newloxcred = th.level0_migration(&cred, &migcred); + + assert!(th.ba.verify_lox(&newloxcred)); println!("newloxcred = {:?}", newloxcred); // Check that we can use the credenital to read a bucket let (id, key) = bridge_table::from_scalar(newloxcred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); - assert!(ba.verify_reachability(&bucket.1.unwrap())); -} - -fn level_up(ba: &mut BridgeAuth, cred: &cred::Lox) -> cred::Lox { - // Read the bucket in the credential to get today's Bucket - // Reachability credential - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - let reachcred = bucket.1.unwrap(); - - // Use the Bucket Reachability credential to advance to the next - // level - let (req, state) = level_up::request( - &cred, - &reachcred, - &ba.lox_pub, - &ba.reachability_pub, - ba.today(), - ) - .unwrap(); - let resp = ba.handle_level_up(req).unwrap(); - let cred = level_up::handle_response(state, resp, &ba.lox_pub).unwrap(); - cred + assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } #[test] fn test_level_up() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); // Time passes - ba.advance_days(30); + th.advance_days(30); - let cred3 = level_up(&mut ba, &cred2); + let cred3 = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred3 = {:?}", cred3); - assert!(ba.verify_lox(&cred3)); + assert!(th.ba.verify_lox(&cred3)); // Time passes - ba.advance_days(60); + th.advance_days(60); - let cred4 = level_up(&mut ba, &cred3); + let cred4 = th.level_up(&cred3); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred4 = {:?}", cred4); - assert!(ba.verify_lox(&cred4)); -} - -fn issue_invite(ba: &mut BridgeAuth, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { - // Read the bucket in the credential to get today's Bucket - // Reachability credential - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - let reachcred = bucket.1.unwrap(); - - let (req, state) = issue_invite::request( - &cred, - &reachcred, - &ba.lox_pub, - &ba.reachability_pub, - ba.today(), - ) - .unwrap(); - let resp = ba.handle_issue_invite(req).unwrap(); - issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap() + assert!(th.ba.verify_lox(&cred4)); } #[test] fn test_issue_invite() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + // Go up to level 2 + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); - let (cred3, invite) = issue_invite(&mut ba, &cred2); - assert!(ba.verify_lox(&cred3)); - assert!(ba.verify_invitation(&invite)); - println!("cred3 = {:?}", cred3); + // Issue an invitation + let (cred2a, invite) = th.issue_invite(&cred2); + assert!(th.ba.verify_lox(&cred2a)); + assert!(th.ba.verify_invitation(&invite)); + println!("cred2a = {:?}", cred2a); println!("invite = {:?}", invite); } -fn redeem_invite(ba: &mut BridgeAuth, inv: &cred::Invitation) -> cred::Lox { - let (req, state) = redeem_invite::request(&inv, &ba.invitation_pub, ba.today()).unwrap(); - let resp = ba.handle_redeem_invite(req).unwrap(); - redeem_invite::handle_response(state, resp, &ba.lox_pub).unwrap() -} - #[test] fn test_redeem_invite() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + // Go up to level 2 + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); - let (cred3, invite) = issue_invite(&mut ba, &cred2); - println!("cred3 = {:?}", cred3); - println!("invite = {:?}", invite); + // Issue an invitation to Bob + let (cred2a, bob_invite) = th.issue_invite(&cred2); + assert!(th.ba.verify_lox(&cred2a)); + assert!(th.ba.verify_invitation(&bob_invite)); + println!("cred2a = {:?}", cred2a); + println!("bob_invite = {:?}", bob_invite); // Time passes - ba.advance_days(12); + th.advance_days(12); - let cred4 = redeem_invite(&mut ba, &invite); - assert!(ba.verify_lox(&cred4)); - println!("cred4 = {:?}", cred4); + // Bob joins the system + let bob_cred = th.redeem_invite(&bob_invite); + assert!(th.ba.verify_lox(&bob_cred)); + println!("bob_cred = {:?}", bob_cred); }