|
|
@@ -7,7 +7,6 @@ with a bucket key. Users will have a credential containing a bucket
|
|
|
buckets. Users will either download the whole encrypted bucket list or
|
|
|
use PIR to download a piece of it, so that the bridge authority does not
|
|
|
learn which bucket the user has access to. */
|
|
|
-
|
|
|
use super::cred;
|
|
|
use super::IssuerPrivKey;
|
|
|
use super::CMZ_B_TABLE;
|
|
|
@@ -21,7 +20,7 @@ use rand::RngCore;
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
use serde_with::serde_as;
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
-use std::convert::TryInto;
|
|
|
+use std::convert::{TryInto, TryFrom};
|
|
|
use subtle::ConstantTimeEq;
|
|
|
|
|
|
/// Each bridge information line is serialized into this many bytes
|
|
|
@@ -205,20 +204,47 @@ impl BridgeLine {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
|
+#[serde(try_from="Vec<u8>", into="Vec<u8>")]
|
|
|
+pub struct EncryptedBucket([u8; ENC_BUCKET_BYTES]);
|
|
|
+
|
|
|
+impl From<EncryptedBucket> for Vec<u8> {
|
|
|
+ fn from(e: EncryptedBucket) -> Vec<u8> {
|
|
|
+ e.0.into()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(thiserror::Error, Debug)]
|
|
|
+#[error("wrong slice length")]
|
|
|
+pub struct WrongSliceLengthError;
|
|
|
+
|
|
|
+impl TryFrom<Vec<u8>> for EncryptedBucket {
|
|
|
+ type Error = WrongSliceLengthError;
|
|
|
+ fn try_from(v: Vec<u8>) -> Result<EncryptedBucket, Self::Error> {
|
|
|
+ Ok(EncryptedBucket(*Box::<[u8; ENC_BUCKET_BYTES]>::try_from(v).map_err(|_| WrongSliceLengthError)?))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Serialize, Deserialize)]
|
|
|
+struct K {
|
|
|
+ encbucket: EncryptedBucket,
|
|
|
+ vec: Vec<u8>,
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/// A BridgeTable is the internal structure holding the buckets
|
|
|
/// containing the bridges, the keys used to encrypt the buckets, and
|
|
|
/// the encrypted buckets. The encrypted buckets will be exposed to the
|
|
|
/// users of the system, and each user credential will contain the
|
|
|
/// decryption key for one bucket.
|
|
|
-#[serde_as]
|
|
|
+//#[serde_as]
|
|
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
|
|
pub struct BridgeTable {
|
|
|
// 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]>,
|
|
|
+ pub encbuckets: HashMap<u32, EncryptedBucket>,
|
|
|
/// Individual bridges that are reachable
|
|
|
pub reachable: HashMap<BridgeLine, Vec<(u32, usize)>>,
|
|
|
/// bucket ids of "hot spare" buckets. These buckets are not handed
|
|
|
@@ -279,8 +305,6 @@ impl BridgeTable {
|
|
|
pub fn encrypt_table(&mut self, today: u32, reachability_priv: &IssuerPrivKey) {
|
|
|
let mut rng = rand::thread_rng();
|
|
|
self.encbuckets.clear();
|
|
|
- // We want id to be a u32, so we use .zip(0u32..) instead of
|
|
|
- // enumerate()
|
|
|
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];
|
|
|
@@ -302,7 +326,8 @@ impl BridgeTable {
|
|
|
let ciphertext: Vec<u8> = cipher.encrypt(nonce, plainbucket.as_ref()).unwrap();
|
|
|
encbucket[0..12].copy_from_slice(&noncebytes);
|
|
|
encbucket[12..].copy_from_slice(ciphertext.as_slice());
|
|
|
- self.encbuckets.push(encbucket);
|
|
|
+ let k = EncryptedBucket(encbucket);
|
|
|
+ self.encbuckets.insert(*uid, k);
|
|
|
}
|
|
|
self.date_last_enc = today;
|
|
|
}
|
|
|
@@ -312,14 +337,24 @@ impl BridgeTable {
|
|
|
pub fn decrypt_bucket(
|
|
|
id: u32,
|
|
|
key: &[u8; 16],
|
|
|
- encbucket: &[u8; ENC_BUCKET_BYTES],
|
|
|
+ encbucket: &EncryptedBucket,
|
|
|
) -> Result<Bucket, aead::Error> {
|
|
|
// Set the nonce and the key
|
|
|
- let nonce = GenericArray::from_slice(&encbucket[0..12]);
|
|
|
+ println!("Trying to decrypt");
|
|
|
+ let k = K {
|
|
|
+ encbucket: *encbucket,
|
|
|
+ vec: (0x20..0x30).collect(),
|
|
|
+ };
|
|
|
+ println!("Made EncryptedBucket");
|
|
|
+ let nonce = GenericArray::from_slice(&k.vec[0..12]);
|
|
|
+ println!("got nonce: {:?}", nonce);
|
|
|
let aeskey = GenericArray::from_slice(key);
|
|
|
+ println!("got aeskey: {:?}", aeskey);
|
|
|
// Decrypt
|
|
|
let cipher = Aes128Gcm::new(aeskey);
|
|
|
- let plaintext: Vec<u8> = cipher.decrypt(nonce, encbucket[12..].as_ref())?;
|
|
|
+ println!("got cipher");
|
|
|
+ let plaintext: Vec<u8> = cipher.decrypt(nonce,k.vec[12..].as_ref())?;
|
|
|
+ println!("got plaintext {:?}", plaintext);
|
|
|
// Convert the plaintext bytes to an array of BridgeLines
|
|
|
Ok(BridgeLine::bucket_decode(
|
|
|
plaintext.as_slice().try_into().unwrap(),
|
|
|
@@ -329,8 +364,11 @@ impl BridgeTable {
|
|
|
|
|
|
/// Decrypt an individual encrypted bucket, given its id and key
|
|
|
pub fn decrypt_bucket_id(&self, id: u32, key: &[u8; 16]) -> Result<Bucket, aead::Error> {
|
|
|
- let encbucket = self.encbuckets[id as usize];
|
|
|
- BridgeTable::decrypt_bucket(id, key, &encbucket)
|
|
|
+ let encbucket:&EncryptedBucket = match self.encbuckets.get(&id) {
|
|
|
+ Some(encbucket) => encbucket,
|
|
|
+ None => panic!("Provided ID not found"),
|
|
|
+ };
|
|
|
+ BridgeTable::decrypt_bucket(id, key, encbucket)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -370,7 +408,9 @@ mod tests {
|
|
|
btable.encrypt_table(today, &reachability_priv);
|
|
|
// Try to decrypt a 1-bridge bucket
|
|
|
let key7 = btable.keys[&7u32];
|
|
|
+ println!("Got Key");
|
|
|
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
|
|
|
+ println!("Decrypted");
|
|
|
println!("bucket 7 = {:?}", bucket7);
|
|
|
// Try to decrypt a 3-bridge bucket
|
|
|
let key24 = btable.keys[&24u32];
|