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]
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct BridgeTable {
pub keys: Vec<[u8; 16]>,
pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
// All structures in the bridgetable are indexed by counter
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]>")]
pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
/// Individual bridges that are reachable
@ -249,20 +251,21 @@ impl BridgeTable {
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) {
// Pick a random key to encrypt this bucket
let mut rng = rand::thread_rng();
let mut key: [u8; 16] = [0; 16];
rng.fill_bytes(&mut key);
self.keys[index as usize] = key;
self.buckets[index as usize] = *bucket;
for (i, b) in bucket.iter().enumerate() {
if b.port > 0 {
if let Some(v) = self.reachable.get_mut(b) {
let key = self.keys.get(&index).unwrap();
let bucket = *self.buckets.get(&index).unwrap();
for (i, bridgeline) in bucket.iter().enumerate() {
if bridgeline.port > 0 {
if let Some(v) = self.reachable.get_mut(bridgeline) {
v.push((index, i));
} else {
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 key: [u8; 16] = [0; 16];
rng.fill_bytes(&mut key);
self.keys.push(key);
self.buckets.push(*bucket);
let bucketnum: u32 = (self.buckets.len() - 1).try_into().unwrap();
// Increase the counter to identify the bucket, wrap value if beyond u32::MAX
self.counter = self.counter.wrapping_add(1);
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
for (i, b) in bucket.iter().enumerate() {
if b.port > 0 {
if let Some(v) = self.reachable.get_mut(b) {
v.push((bucketnum, i));
v.push((self.counter, i));
} else {
let v = vec![(bucketnum, i)];
let v = vec![(self.counter, i)];
self.reachable.insert(*b, v);
}
}
}
bucketnum
self.counter
}
/// Create the vector of encrypted buckets from the keys and buckets
@ -303,13 +308,14 @@ impl BridgeTable {
self.encbuckets.clear();
// We want id to be a u32, so we use .zip(0u32..) instead of
// 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 plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(
bucket,
&self.reachable,
today,
&to_scalar(id, key),
&to_scalar(*uid, key),
reachability_priv,
);
// Set the AES key
@ -390,15 +396,15 @@ mod tests {
// Create the encrypted bridge table
btable.encrypt_table(today, &reachability_priv);
// 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)?;
println!("bucket 7 = {:?}", bucket7);
// 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)?;
println!("bucket 24 = {:?}", bucket24);
// 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();
println!("bucket key mismatch = {:?}", res);
Ok(())

View File

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

View File

@ -196,10 +196,11 @@ impl BridgeAuth {
// Create the bucket attribute (Scalar), which is a combination
// 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 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
// Julian date
let level_since: Scalar = self.today().into();