Create Bucket Reachability credentials and put them in buckets as appropriate
This commit is contained in:
parent
33f3de3b68
commit
ba13545b3c
|
@ -8,11 +8,17 @@ 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;
|
||||
use aes_gcm::aead;
|
||||
use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead};
|
||||
use aes_gcm::Aes128Gcm;
|
||||
use curve25519_dalek::ristretto::CompressedRistretto;
|
||||
use curve25519_dalek::ristretto::RistrettoBasepointTable;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use rand::RngCore;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::TryInto;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
|
@ -22,14 +28,14 @@ pub const BRIDGE_BYTES: usize = 220;
|
|||
/// The max number of bridges per bucket
|
||||
pub const MAX_BRIDGES_PER_BUCKET: usize = 3;
|
||||
|
||||
/// The size of a plaintext bucket
|
||||
pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET;
|
||||
|
||||
/// The size of an encrypted bucket
|
||||
pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16;
|
||||
/// The minimum number of bridges in a bucket that must be reachable for
|
||||
/// the bucket to get a Bucket Reachability credential that will allow
|
||||
/// users of that bucket to gain trust levels (once they are already at
|
||||
/// level 1)
|
||||
pub const MIN_BUCKET_REACHABILITY: usize = 2;
|
||||
|
||||
/// A bridge information line
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct BridgeLine {
|
||||
/// IPv4 or IPv6 address
|
||||
pub addr: [u8; 16],
|
||||
|
@ -40,6 +46,20 @@ pub struct BridgeLine {
|
|||
pub info: [u8; BRIDGE_BYTES - 18],
|
||||
}
|
||||
|
||||
/// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the
|
||||
/// information needed to construct a Bucket Reachability credential,
|
||||
/// which is a 4-byte date, and a (P,Q) MAC
|
||||
type Bucket = (
|
||||
[BridgeLine; MAX_BRIDGES_PER_BUCKET],
|
||||
Option<cred::BucketReachability>,
|
||||
);
|
||||
|
||||
/// The size of a plaintext bucket
|
||||
pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET + 4 + 32 + 32;
|
||||
|
||||
/// The size of an encrypted bucket
|
||||
pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16;
|
||||
|
||||
impl Default for BridgeLine {
|
||||
/// An "empty" BridgeLine is represented by all zeros
|
||||
fn default() -> Self {
|
||||
|
@ -68,25 +88,79 @@ impl BridgeLine {
|
|||
res.info.copy_from_slice(&data[18..]);
|
||||
res
|
||||
}
|
||||
/// Encode a bucket to a byte array
|
||||
pub fn bucket_encode(bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> [u8; BUCKET_BYTES] {
|
||||
/// Encode a bucket to a byte array, including a Bucket Reachability
|
||||
/// credential if appropriate
|
||||
pub fn bucket_encode(
|
||||
bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET],
|
||||
reachable: &HashSet<BridgeLine>,
|
||||
today: u32,
|
||||
bucket_attr: &Scalar,
|
||||
reachability_priv: &IssuerPrivKey,
|
||||
) -> [u8; BUCKET_BYTES] {
|
||||
let mut res: [u8; BUCKET_BYTES] = [0; BUCKET_BYTES];
|
||||
let mut pos: usize = 0;
|
||||
let mut num_reachable: usize = 0;
|
||||
for bridge in bucket {
|
||||
res[pos..pos + BRIDGE_BYTES].copy_from_slice(&bridge.encode());
|
||||
if reachable.contains(bridge) {
|
||||
num_reachable += 1;
|
||||
}
|
||||
pos += BRIDGE_BYTES;
|
||||
}
|
||||
if num_reachable >= MIN_BUCKET_REACHABILITY {
|
||||
// Construct a Bucket Reachability credential for this
|
||||
// bucket and today's date
|
||||
let today_attr: Scalar = today.into();
|
||||
let mut rng = rand::thread_rng();
|
||||
let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
|
||||
let b = Scalar::random(&mut rng);
|
||||
let P = &b * Btable;
|
||||
let Q = &(b
|
||||
* (reachability_priv.x[0]
|
||||
+ reachability_priv.x[1] * today_attr
|
||||
+ reachability_priv.x[2] * bucket_attr))
|
||||
* Btable;
|
||||
res[pos..pos + 4].copy_from_slice(&today.to_le_bytes());
|
||||
res[pos + 4..pos + 36].copy_from_slice(&P.compress().as_bytes()[..]);
|
||||
res[pos + 36..].copy_from_slice(&Q.compress().as_bytes()[..]);
|
||||
}
|
||||
res
|
||||
}
|
||||
/// Decode a bucket from a byte array
|
||||
pub fn bucket_decode(data: &[u8; BUCKET_BYTES]) -> [BridgeLine; MAX_BRIDGES_PER_BUCKET] {
|
||||
/// Decode a bucket from a byte array, yielding the array of
|
||||
/// BridgeLine entries and an optional Bucket Reachability
|
||||
/// credential
|
||||
fn bucket_decode(data: &[u8; BUCKET_BYTES], bucket_attr: &Scalar) -> Bucket {
|
||||
let mut pos: usize = 0;
|
||||
let mut res: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default();
|
||||
for bridge in res.iter_mut().take(MAX_BRIDGES_PER_BUCKET) {
|
||||
let mut bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default();
|
||||
for bridge in bridges.iter_mut().take(MAX_BRIDGES_PER_BUCKET) {
|
||||
*bridge = BridgeLine::decode(data[pos..pos + BRIDGE_BYTES].try_into().unwrap());
|
||||
pos += BRIDGE_BYTES;
|
||||
}
|
||||
res
|
||||
// See if there's a nonzero date in the Bucket Reachability
|
||||
// Credential
|
||||
let date = u32::from_le_bytes(data[pos..pos + 4].try_into().unwrap());
|
||||
let (optP, optQ) = if date > 0 {
|
||||
(
|
||||
CompressedRistretto::from_slice(&data[pos + 4..pos + 36]).decompress(),
|
||||
CompressedRistretto::from_slice(&data[pos + 36..]).decompress(),
|
||||
)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
if let (Some(P), Some(Q)) = (optP, optQ) {
|
||||
let date_attr: Scalar = date.into();
|
||||
(
|
||||
bridges,
|
||||
Some(cred::BucketReachability {
|
||||
P,
|
||||
Q,
|
||||
date: date_attr,
|
||||
bucket: *bucket_attr,
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
(bridges, None)
|
||||
}
|
||||
}
|
||||
/// Create a random BridgeLine for testing
|
||||
#[cfg(test)]
|
||||
|
@ -134,6 +208,12 @@ pub struct BridgeTable {
|
|||
pub keys: Vec<[u8; 16]>,
|
||||
pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
|
||||
pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
|
||||
pub reachable: HashSet<BridgeLine>,
|
||||
/// The date the buckets were last encrypted to make the encbucket.
|
||||
///
|
||||
/// The encbucket must be rebuilt each day so that the Bucket
|
||||
/// Reachability credentials in the buckets can be refreshed.
|
||||
pub date_last_enc: u32,
|
||||
}
|
||||
|
||||
// Invariant: the lengths of the keys and buckets vectors are the same.
|
||||
|
@ -153,18 +233,35 @@ impl BridgeTable {
|
|||
rng.fill_bytes(&mut key);
|
||||
self.keys.push(key);
|
||||
self.buckets.push(bucket);
|
||||
// Mark the new bridges as available
|
||||
for b in bucket.iter() {
|
||||
if b.port > 0 {
|
||||
self.reachable.insert(*b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the vector of encrypted buckets from the keys and buckets
|
||||
/// in the BridgeTable. All of the entries will be (randomly)
|
||||
/// re-encrypted, so it will be hidden whether any individual bucket
|
||||
/// has changed (except for entirely new buckets, of course).
|
||||
pub fn encrypt_table(&mut self) {
|
||||
/// Bucket Reachability credentials are added to the buckets when
|
||||
/// enough (at least MIN_BUCKET_REACHABILITY) bridges in the bucket
|
||||
/// are reachable.
|
||||
pub fn encrypt_table(&mut self, today: u32, reachability_priv: &IssuerPrivKey) {
|
||||
let mut rng = rand::thread_rng();
|
||||
self.encbuckets.clear();
|
||||
for (key, bucket) in self.keys.iter().zip(self.buckets.iter()) {
|
||||
// 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..) {
|
||||
let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES];
|
||||
let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(bucket);
|
||||
let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(
|
||||
bucket,
|
||||
&self.reachable,
|
||||
today,
|
||||
&to_scalar(id, key),
|
||||
reachability_priv,
|
||||
);
|
||||
// Set the AES key
|
||||
let aeskey = GenericArray::from_slice(key);
|
||||
// Pick a random nonce
|
||||
|
@ -178,13 +275,16 @@ impl BridgeTable {
|
|||
encbucket[12..].copy_from_slice(ciphertext.as_slice());
|
||||
self.encbuckets.push(encbucket);
|
||||
}
|
||||
self.date_last_enc = today;
|
||||
}
|
||||
|
||||
/// Decrypt an individual encrypted bucket, given its key
|
||||
/// Decrypt an individual encrypted bucket, given its id, key, and
|
||||
/// the encrypted bucket itself
|
||||
pub fn decrypt_bucket(
|
||||
id: u32,
|
||||
key: &[u8; 16],
|
||||
encbucket: &[u8; ENC_BUCKET_BYTES],
|
||||
) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> {
|
||||
) -> Result<Bucket, aead::Error> {
|
||||
// Set the nonce and the key
|
||||
let nonce = GenericArray::from_slice(&encbucket[0..12]);
|
||||
let aeskey = GenericArray::from_slice(key);
|
||||
|
@ -194,17 +294,14 @@ impl BridgeTable {
|
|||
// Convert the plaintext bytes to an array of BridgeLines
|
||||
Ok(BridgeLine::bucket_decode(
|
||||
plaintext.as_slice().try_into().unwrap(),
|
||||
&to_scalar(id, key),
|
||||
))
|
||||
}
|
||||
|
||||
/// Decrypt an individual encrypted bucket, given its id and key
|
||||
pub fn decrypt_bucket_id(
|
||||
&self,
|
||||
id: u32,
|
||||
key: &[u8; 16],
|
||||
) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> {
|
||||
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(key, &encbucket)
|
||||
BridgeTable::decrypt_bucket(id, key, &encbucket)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,6 +313,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_bridge_table() -> Result<(), aead::Error> {
|
||||
// Create private keys for the Bucket Reachability credentials
|
||||
let reachability_priv = IssuerPrivKey::new(2);
|
||||
// Create an empty bridge table
|
||||
let mut btable: BridgeTable = Default::default();
|
||||
// Make 20 buckets with one random bridge each
|
||||
|
@ -233,8 +332,13 @@ mod tests {
|
|||
];
|
||||
btable.new_bucket(bucket);
|
||||
}
|
||||
let today: u32 = time::OffsetDateTime::now_utc()
|
||||
.date()
|
||||
.julian_day()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
// Create the encrypted bridge table
|
||||
btable.encrypt_table();
|
||||
btable.encrypt_table(today, &reachability_priv);
|
||||
// Try to decrypt a 1-bridge bucket
|
||||
let key7 = btable.keys[7];
|
||||
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
|
||||
|
|
|
@ -7,9 +7,10 @@ zero-knowledge proof of its correctness (as it does at issuing time). */
|
|||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
/// A migration credential. This credential authorizes the holder of
|
||||
/// the Lox credential with the given id to switch from bucket
|
||||
/// from_bucket to bucket to_bucket.
|
||||
/// A migration credential.
|
||||
///
|
||||
/// This credential authorizes the holder of the Lox credential with the
|
||||
/// given id to switch from bucket from_bucket to bucket to_bucket.
|
||||
#[derive(Debug)]
|
||||
pub struct Migration {
|
||||
pub P: RistrettoPoint,
|
||||
|
@ -19,15 +20,17 @@ pub struct Migration {
|
|||
pub to_bucket: Scalar,
|
||||
}
|
||||
|
||||
/// The main user credential in the Lox system. Its id is jointly
|
||||
/// generated by the user and the BA (bridge authority), but known only
|
||||
/// to the user. The level_since date is the Julian date of when this
|
||||
/// user was changed to the current trust level. (P_noopmigration,
|
||||
/// Q_noopmigration) are the MAC on the implicit no-op migration
|
||||
/// credential formed by the attributes (id, bucket, bucket), which
|
||||
/// authorizes the user to switch from its current bucket to the same
|
||||
/// bucket (i.e., a no-op). This can be useful for hiding from the BA
|
||||
/// whether or not the user is performing a bucket migration.
|
||||
/// The main user credential in the Lox system.
|
||||
///
|
||||
/// Its id is jointly generated by the user and the BA (bridge
|
||||
/// authority), but known only to the user. The level_since date is the
|
||||
/// Julian date of when this user was changed to the current trust
|
||||
/// level. (P_noopmigration, Q_noopmigration) are the MAC on the
|
||||
/// implicit no-op migration credential formed by the attributes (id,
|
||||
/// bucket, bucket), which authorizes the user to switch from its
|
||||
/// current bucket to the same bucket (i.e., a no-op). This can be
|
||||
/// useful for hiding from the BA whether or not the user is performing
|
||||
/// a bucket migration.
|
||||
#[derive(Debug)]
|
||||
pub struct Lox {
|
||||
pub P: RistrettoPoint,
|
||||
|
@ -42,18 +45,40 @@ pub struct Lox {
|
|||
pub Q_noopmigration: RistrettoPoint,
|
||||
}
|
||||
|
||||
// The migration key credential is never actually instantiated. It is
|
||||
// an implicit credential with the following attributes:
|
||||
// - lox_id: Scalar,
|
||||
// - from_bucket: Scalar
|
||||
// Plus the usual (P,Q) MAC. This credential type does have an
|
||||
// associated private and public key, however. The idea is that if a
|
||||
// user proves (in zero knowledge) that their Lox credential entitles
|
||||
// them to migrate from one bucket to another, the BA will issue a
|
||||
// (blinded, so the BA will not know the values of the attributes or of
|
||||
// Q) MAC on this implicit credential. The Q value will then be used
|
||||
// (actually, a hash of lox_id, from_bucket, and Q) to encrypt the
|
||||
// to_bucket, P, and Q fields of a Migration credential. That way,
|
||||
// people entitled to migrate buckets can receive a Migration credential
|
||||
// with their new bucket, without the BA learning either their old or
|
||||
// new buckets.
|
||||
/// The migration key credential.
|
||||
///
|
||||
/// This credential is never actually instantiated. It is an implicit
|
||||
/// credential on attributes lox_id and from_bucket. This credential
|
||||
/// type does have an associated private and public key, however. The
|
||||
/// idea is that if a user proves (in zero knowledge) that their Lox
|
||||
/// credential entitles them to migrate from one bucket to another, the
|
||||
/// BA will issue a (blinded, so the BA will not know the values of the
|
||||
/// attributes or of Q) MAC on this implicit credential. The Q value
|
||||
/// will then be used (actually, a hash of lox_id, from_bucket, and Q)
|
||||
/// to encrypt the to_bucket, P, and Q fields of a Migration credential.
|
||||
/// That way, people entitled to migrate buckets can receive a Migration
|
||||
/// credential with their new bucket, without the BA learning either
|
||||
/// their old or new buckets.
|
||||
#[derive(Debug)]
|
||||
pub struct MigrationKey {
|
||||
pub P: RistrettoPoint,
|
||||
pub Q: RistrettoPoint,
|
||||
pub lox_id: Scalar,
|
||||
pub from_bucket: Scalar,
|
||||
}
|
||||
|
||||
/// The Bucket Reachability credential.
|
||||
///
|
||||
/// Each day, a credential of this type is put in each bucket that has
|
||||
/// at least a (configurable) threshold number of bridges that have not
|
||||
/// been blocked as of the given date. Users can present this
|
||||
/// credential (in zero knowledge) with today's date to prove that the
|
||||
/// bridges in their bucket have not been blocked, in order to gain a
|
||||
/// trust level.
|
||||
#[derive(Debug)]
|
||||
pub struct BucketReachability {
|
||||
pub P: RistrettoPoint,
|
||||
pub Q: RistrettoPoint,
|
||||
pub date: Scalar,
|
||||
pub bucket: Scalar,
|
||||
}
|
||||
|
|
|
@ -186,6 +186,10 @@ pub struct BridgeAuth {
|
|||
migrationkey_priv: IssuerPrivKey,
|
||||
/// The public key for migration key credentials
|
||||
pub migrationkey_pub: IssuerPubKey,
|
||||
/// The private key for bucket reachability credentials
|
||||
reachability_priv: IssuerPrivKey,
|
||||
/// The public key for bucket reachability credentials
|
||||
pub reachability_pub: IssuerPubKey,
|
||||
|
||||
/// The public key of the BridgeDb issuing open invitations
|
||||
pub bridgedb_pub: PublicKey,
|
||||
|
@ -218,6 +222,8 @@ impl BridgeAuth {
|
|||
let migration_pub = IssuerPubKey::new(&migration_priv);
|
||||
let migrationkey_priv = IssuerPrivKey::new(2);
|
||||
let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv);
|
||||
let reachability_priv = IssuerPrivKey::new(2);
|
||||
let reachability_pub = IssuerPubKey::new(&reachability_priv);
|
||||
Self {
|
||||
lox_priv,
|
||||
lox_pub,
|
||||
|
@ -225,6 +231,8 @@ impl BridgeAuth {
|
|||
migration_pub,
|
||||
migrationkey_priv,
|
||||
migrationkey_pub,
|
||||
reachability_priv,
|
||||
reachability_pub,
|
||||
bridgedb_pub,
|
||||
bridge_table: Default::default(),
|
||||
migration_table: Default::default(),
|
||||
|
@ -258,6 +266,20 @@ impl BridgeAuth {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
/// Get a reference to the encrypted bridge table.
|
||||
///
|
||||
/// Be sure to call this function when you want the latest version
|
||||
/// of the table, since it will put fresh Bucket Reachability
|
||||
/// credentials in the buckets each day.
|
||||
pub fn enc_bridge_table(&mut self) -> &Vec<[u8; bridge_table::ENC_BUCKET_BYTES]> {
|
||||
let today = self.today();
|
||||
if self.bridge_table.date_last_enc != today {
|
||||
self.bridge_table
|
||||
.encrypt_table(today, &self.reachability_priv);
|
||||
}
|
||||
&self.bridge_table.encbuckets
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Verify the two MACs on a Lox credential
|
||||
pub fn verify_lox(&self, cred: &cred::Lox) -> bool {
|
||||
|
@ -297,6 +319,20 @@ impl BridgeAuth {
|
|||
* cred.P;
|
||||
return Q == cred.Q;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Verify the MAC on a Bucket Reachability credential
|
||||
pub fn verify_reachability(&self, cred: &cred::BucketReachability) -> bool {
|
||||
if cred.P.is_identity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Q = (self.reachability_priv.x[0]
|
||||
+ cred.date * self.reachability_priv.x[1]
|
||||
+ cred.bucket * self.reachability_priv.x[2])
|
||||
* cred.P;
|
||||
return Q == cred.Q;
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to extract a u64 from a Scalar
|
||||
|
|
|
@ -28,7 +28,7 @@ fn test_open_invite() {
|
|||
ba.bridge_table.new_bucket(bucket);
|
||||
}
|
||||
// Create the encrypted bridge table
|
||||
ba.bridge_table.encrypt_table();
|
||||
ba.enc_bridge_table();
|
||||
|
||||
// Issue an open invitation
|
||||
let inv = bdb.invite();
|
||||
|
@ -40,7 +40,9 @@ fn test_open_invite() {
|
|||
|
||||
// Check that we can use the credential to read a bucket
|
||||
let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap();
|
||||
let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap();
|
||||
let encbuckets = 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!(ba.verify_lox(&cred));
|
||||
|
@ -74,7 +76,7 @@ fn setup() -> (BridgeDb, BridgeAuth) {
|
|||
ba.migration_table.table.insert(3 * i + 2, 15 + i);
|
||||
}
|
||||
// Create the encrypted bridge table
|
||||
ba.bridge_table.encrypt_table();
|
||||
ba.enc_bridge_table();
|
||||
|
||||
(bdb, ba)
|
||||
}
|
||||
|
@ -109,7 +111,9 @@ fn test_trust_promotion() {
|
|||
// 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 bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap();
|
||||
let encbuckets = ba.enc_bridge_table();
|
||||
let bucket =
|
||||
bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
|
||||
println!("bucket = {:?}", bucket);
|
||||
}
|
||||
|
||||
|
@ -128,6 +132,8 @@ fn test_level0_migration() {
|
|||
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 bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap();
|
||||
let encbuckets = ba.enc_bridge_table();
|
||||
let bucket =
|
||||
bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
|
||||
println!("bucket = {:?}", bucket);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue