Converting bridgetable vectors to HashMaps

This commit is contained in:
onyinyang 2023-06-16 11:02:13 -04:00
parent 73c3ef8728
commit 607ecd89c7
No known key found for this signature in database
GPG Key ID: 156A6435430C2036
3 changed files with 57 additions and 34 deletions

View File

@ -213,8 +213,10 @@ impl BridgeLine {
#[serde_as] #[serde_as]
#[derive(Debug, Default, Serialize, Deserialize)] #[derive(Debug, Default, Serialize, Deserialize)]
pub struct BridgeTable { pub struct BridgeTable {
pub keys: Vec<[u8; 16]>, // All structures in the bridgetable are indexed by counter
pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, pub counter: u32,
pub keys: HashMap<u32, [u8; 16]>,
pub buckets: HashMap<u32, [BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
#[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")] #[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")]
pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
/// Individual bridges that are reachable /// Individual bridges that are reachable
@ -249,20 +251,21 @@ impl BridgeTable {
self.buckets.len() self.buckets.len()
} }
// TODO Don't need with hashmaps, but remove unused buckets
pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) { pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) {
// Pick a random key to encrypt this bucket // Pick a random key to encrypt this bucket
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut key: [u8; 16] = [0; 16]; let mut key: [u8; 16] = [0; 16];
rng.fill_bytes(&mut key); rng.fill_bytes(&mut key);
self.keys[index as usize] = key; let key = self.keys.get(&index).unwrap();
self.buckets[index as usize] = *bucket; let bucket = *self.buckets.get(&index).unwrap();
for (i, b) in bucket.iter().enumerate() { for (i, bridgeline) in bucket.iter().enumerate() {
if b.port > 0 { if bridgeline.port > 0 {
if let Some(v) = self.reachable.get_mut(b) { if let Some(v) = self.reachable.get_mut(bridgeline) {
v.push((index, i)); v.push((index, i));
} else { } else {
let v = vec![(index, i)]; let v = vec![(index, i)];
self.reachable.insert(*b, v); self.reachable.insert(*bridgeline, v);
} }
} }
} }
@ -274,21 +277,23 @@ impl BridgeTable {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut key: [u8; 16] = [0; 16]; let mut key: [u8; 16] = [0; 16];
rng.fill_bytes(&mut key); rng.fill_bytes(&mut key);
self.keys.push(key); // Increase the counter to identify the bucket, wrap value if beyond u32::MAX
self.buckets.push(*bucket); self.counter = self.counter.wrapping_add(1);
let bucketnum: u32 = (self.buckets.len() - 1).try_into().unwrap(); self.keys.insert(self.counter, key);
self.buckets.insert(self.counter, *bucket);
// TODO: maybe we don't need this if the hashtable can keep track of available bridges
// Mark the new bridges as available // Mark the new bridges as available
for (i, b) in bucket.iter().enumerate() { for (i, b) in bucket.iter().enumerate() {
if b.port > 0 { if b.port > 0 {
if let Some(v) = self.reachable.get_mut(b) { if let Some(v) = self.reachable.get_mut(b) {
v.push((bucketnum, i)); v.push((self.counter, i));
} else { } else {
let v = vec![(bucketnum, i)]; let v = vec![(self.counter, i)];
self.reachable.insert(*b, v); self.reachable.insert(*b, v);
} }
} }
} }
bucketnum self.counter
} }
/// Create the vector of encrypted buckets from the keys and buckets /// Create the vector of encrypted buckets from the keys and buckets
@ -303,13 +308,14 @@ impl BridgeTable {
self.encbuckets.clear(); self.encbuckets.clear();
// We want id to be a u32, so we use .zip(0u32..) instead of // We want id to be a u32, so we use .zip(0u32..) instead of
// enumerate() // enumerate()
for ((key, bucket), id) in self.keys.iter().zip(self.buckets.iter()).zip(0u32..) { for (uid, key) in self.keys.iter(){
let bucket = self.buckets.get(uid).unwrap();
let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES]; let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES];
let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode( let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(
bucket, bucket,
&self.reachable, &self.reachable,
today, today,
&to_scalar(id, key), &to_scalar(*uid, key),
reachability_priv, reachability_priv,
); );
// Set the AES key // Set the AES key
@ -390,15 +396,15 @@ mod tests {
// Create the encrypted bridge table // Create the encrypted bridge table
btable.encrypt_table(today, &reachability_priv); btable.encrypt_table(today, &reachability_priv);
// Try to decrypt a 1-bridge bucket // Try to decrypt a 1-bridge bucket
let key7 = btable.keys[7]; let key7 = btable.keys[&7u32];
let bucket7 = btable.decrypt_bucket_id(7, &key7)?; let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
println!("bucket 7 = {:?}", bucket7); println!("bucket 7 = {:?}", bucket7);
// Try to decrypt a 3-bridge bucket // Try to decrypt a 3-bridge bucket
let key24 = btable.keys[24]; let key24 = btable.keys[&24u32];
let bucket24 = btable.decrypt_bucket_id(24, &key24)?; let bucket24 = btable.decrypt_bucket_id(24, &key24)?;
println!("bucket 24 = {:?}", bucket24); println!("bucket 24 = {:?}", bucket24);
// Try to decrypt a bucket with the wrong key // Try to decrypt a bucket with the wrong key
let key12 = btable.keys[12]; let key12 = btable.keys[&12u32];
let res = btable.decrypt_bucket_id(15, &key12).unwrap_err(); let res = btable.decrypt_bucket_id(15, &key12).unwrap_err();
println!("bucket key mismatch = {:?}", res); println!("bucket key mismatch = {:?}", res);
Ok(()) Ok(())

View File

@ -380,14 +380,22 @@ impl BridgeAuth {
if let Some(v) = positions { if let Some(v) = positions {
for (bucketnum, offset) in v.iter() { for (bucketnum, offset) in v.iter() {
println!("Bucket num: {:?} and offset: {:?}", bucketnum, offset); println!("Bucket num: {:?} and offset: {:?}", bucketnum, offset);
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
None => return res
};
assert!( assert!(
self.bridge_table.buckets[*bucketnum as usize][*offset] bridgelines[*offset]
== reachable_bridge.0 == reachable_bridge.0
); );
self.bridge_table.buckets[*bucketnum as usize][*offset] = *bridge; bridgelines[*offset] = *bridge;
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); self.bridge_table.buckets.insert(*bucketnum, bridgelines);
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
None => return res
};
assert!( assert!(
self.bridge_table.buckets[*bucketnum as usize][*offset] bridgelines[*offset]
!= reachable_bridge.0 != reachable_bridge.0
); );
} }
@ -418,23 +426,33 @@ impl BridgeAuth {
let reachable_bridges = &self.bridge_table.reachable.clone(); let reachable_bridges = &self.bridge_table.reachable.clone();
match reachable_bridges.get(bridge) { match reachable_bridges.get(bridge) {
Some(positions) => { Some(positions) => {
println!("Should not get here");
if let Some(replacement) = available_bridge { if let Some(replacement) = available_bridge {
for (bucketnum, offset) in positions.iter() { for (bucketnum, offset) in positions.iter() {
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement; Some(bridgelines) => *bridgelines,
None => return ReplaceSuccess::NotFound,
};
assert!(bridgelines[*offset] == *bridge);
bridgelines[*offset] = *replacement;
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
// Remove the bridge from the reachable bridges and add new bridge // Remove the bridge from the reachable bridges and add new bridge
self.bridge_table self.bridge_table
.reachable .reachable
.insert(*replacement, positions.clone()); .insert(*replacement, positions.clone());
// Remove the bridge from the bucket // Remove the bridge from the bucket
self.bridge_table.reachable.remove(bridge); self.bridge_table.reachable.remove(bridge);
res = ReplaceSuccess::Replaced
} }
res = ReplaceSuccess::Replaced
} else if !self.bridge_table.unallocated_bridges.is_empty() { } else if !self.bridge_table.unallocated_bridges.is_empty() {
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap(); let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
for (bucketnum, offset) in positions.iter() { for (bucketnum, offset) in positions.iter() {
self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement; let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
None => return ReplaceSuccess::NotFound,
};
assert!(bridgelines[*offset] == *bridge);
bridgelines[*offset] = *replacement;
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
self.bridge_table self.bridge_table
.reachable .reachable
.insert(*replacement, positions.clone()); .insert(*replacement, positions.clone());
@ -446,10 +464,8 @@ impl BridgeAuth {
// Get the first spare and remove it from the spares set. // Get the first spare and remove it from the spares set.
let spare = *self.bridge_table.spares.iter().next().unwrap(); let spare = *self.bridge_table.spares.iter().next().unwrap();
self.bridge_table.spares.remove(&spare); self.bridge_table.spares.remove(&spare);
// Indicate the removed bucket as a recyclable bucket
self.bridge_table.recyclable.insert(spare);
// Get the actual bridges from the spare bucket // Get the actual bridges from the spare bucket
let spare_bucket = self.bridge_table.buckets[spare as usize]; let spare_bucket = self.bridge_table.buckets[&spare];
let mut replacement: &BridgeLine = &BridgeLine::default(); let mut replacement: &BridgeLine = &BridgeLine::default();
// Make the first spare the replacement bridge, add the others to the set of // Make the first spare the replacement bridge, add the others to the set of
// unallocated_bridges // unallocated_bridges

View File

@ -196,9 +196,10 @@ impl BridgeAuth {
// Create the bucket attribute (Scalar), which is a combination // Create the bucket attribute (Scalar), which is a combination
// of the bucket id (u32) and the bucket's decryption key ([u8; 16]) // of the bucket id (u32) and the bucket's decryption key ([u8; 16])
let bucket_key = self.bridge_table.keys[bucket_id]; let bucket_key = self.bridge_table.keys.get(&bucket_id_u32).unwrap();
let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key); let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key);
let bridge_line = self.bridge_table.buckets[bucket_id][0]; let bridge_lines = self.bridge_table.buckets.get(&bucket_id_u32).unwrap();
let bridge_line = bridge_lines[0];
// Create the level_since attribute (Scalar), which is today's // Create the level_since attribute (Scalar), which is today's
// Julian date // Julian date