|
|
@@ -10,15 +10,15 @@ learn which bucket the user has access to. */
|
|
|
use super::lox_creds::BucketReachability;
|
|
|
//use super::IssuerPrivKey;
|
|
|
//use super::CMZ_B_TABLE;
|
|
|
+use super::{Scalar, G};
|
|
|
use aes_gcm::aead;
|
|
|
-//use aes_gcm::aead::{generic_array::GenericArray, Aead};
|
|
|
-//use aes_gcm::{Aes128Gcm, KeyInit};
|
|
|
+use aes_gcm::aead::{generic_array::GenericArray, Aead};
|
|
|
+use aes_gcm::{Aes128Gcm, KeyInit};
|
|
|
#[cfg(feature = "bridgeauth")]
|
|
|
#[allow(unused_imports)]
|
|
|
use base64::{engine::general_purpose, Engine as _};
|
|
|
-//use curve25519_dalek::ristretto::CompressedRistretto;
|
|
|
-//use curve25519_dalek::ristretto::RistrettoBasepointTable;
|
|
|
-use curve25519_dalek::scalar::Scalar;
|
|
|
+use cmz::{CMZCredential, CMZPrivkey, CMZPubkey};
|
|
|
+use curve25519_dalek::ristretto::CompressedRistretto;
|
|
|
#[allow(unused_imports)]
|
|
|
use rand::RngCore;
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
@@ -98,7 +98,7 @@ impl Default for BridgeLine {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-/*
|
|
|
+
|
|
|
impl BridgeLine {
|
|
|
/// Encode a BridgeLine to a byte array
|
|
|
pub fn encode(&self) -> [u8; BRIDGE_BYTES] {
|
|
|
@@ -127,7 +127,7 @@ impl BridgeLine {
|
|
|
reachable: &HashMap<BridgeLine, Vec<(u32, usize)>>,
|
|
|
today: u32,
|
|
|
bucket_attr: &Scalar,
|
|
|
- reachability_priv: &IssuerPrivKey,
|
|
|
+ reachability_priv: &CMZPrivkey<G>,
|
|
|
) -> [u8; BUCKET_BYTES] {
|
|
|
let mut res: [u8; BUCKET_BYTES] = [0; BUCKET_BYTES];
|
|
|
let mut pos: usize = 0;
|
|
|
@@ -143,25 +143,32 @@ impl BridgeLine {
|
|
|
// Construct a Bucket Reachability credential for this
|
|
|
// bucket and today's date
|
|
|
let today_attr: Scalar = today.into();
|
|
|
- let mut rng = rand::rngs::OsRng;
|
|
|
- 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;
|
|
|
+ //let mut rng = rand::rngs::OsRng;
|
|
|
+ let mut B = BucketReachability::using_privkey(reachability_priv);
|
|
|
+ B.date = Some(today_attr);
|
|
|
+ B.bucket = Some(*bucket_attr);
|
|
|
+ //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[pos + 4..pos + 36].copy_from_slice(B.MAC.P.compress().as_bytes());
|
|
|
+ res[pos + 36..].copy_from_slice(B.MAC.Q.compress().as_bytes());
|
|
|
}
|
|
|
res
|
|
|
}
|
|
|
/// 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 {
|
|
|
+ fn bucket_decode(
|
|
|
+ data: &[u8; BUCKET_BYTES],
|
|
|
+ bucket_attr: &Scalar,
|
|
|
+ reachability_pub: &CMZPubkey<G>,
|
|
|
+ ) -> Bucket {
|
|
|
let mut pos: usize = 0;
|
|
|
let mut bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default();
|
|
|
for bridge in bridges.iter_mut().take(MAX_BRIDGES_PER_BUCKET) {
|
|
|
@@ -185,14 +192,13 @@ impl BridgeLine {
|
|
|
};
|
|
|
if let (Some(P), Some(Q)) = (optP, optQ) {
|
|
|
let date_attr: Scalar = date.into();
|
|
|
- let mut B = BucketReachability::using_privkey
|
|
|
- (
|
|
|
- bridges,
|
|
|
- Some(BucketReachability {
|
|
|
- date: date_attr,
|
|
|
- bucket: *bucket_attr,
|
|
|
- }),
|
|
|
- )
|
|
|
+ let mut B = BucketReachability::using_pubkey(reachability_pub);
|
|
|
+ B.date = Some(date_attr);
|
|
|
+ B.bucket = Some(*bucket_attr);
|
|
|
+ B.MAC.P = P;
|
|
|
+ B.MAC.Q = Q;
|
|
|
+
|
|
|
+ (bridges, Some(B))
|
|
|
} else {
|
|
|
(bridges, None)
|
|
|
}
|
|
|
@@ -231,7 +237,7 @@ impl BridgeLine {
|
|
|
res
|
|
|
}
|
|
|
}
|
|
|
-*/
|
|
|
+
|
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
|
#[serde(try_from = "Vec<u8>", into = "Vec<u8>")]
|
|
|
pub struct EncryptedBucket([u8; ENC_BUCKET_BYTES]);
|
|
|
@@ -338,7 +344,6 @@ impl BridgeTable {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- /*
|
|
|
/// 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
|
|
|
@@ -347,7 +352,7 @@ impl BridgeTable {
|
|
|
/// enough (at least MIN_BUCKET_REACHABILITY) bridges in the bucket
|
|
|
/// are reachable.
|
|
|
#[cfg(feature = "bridgeauth")]
|
|
|
- pub fn encrypt_table(&mut self, today: u32, reachability_priv: &IssuerPrivKey) {
|
|
|
+ pub fn encrypt_table(&mut self, today: u32, reachability_priv: &CMZPrivkey<G>) {
|
|
|
let mut rng = rand::rngs::OsRng;
|
|
|
self.encbuckets.clear();
|
|
|
for (uid, key) in self.keys.iter() {
|
|
|
@@ -383,6 +388,7 @@ impl BridgeTable {
|
|
|
id: u32,
|
|
|
key: &[u8; 16],
|
|
|
encbucket: &EncryptedBucket,
|
|
|
+ reachability_pub: &CMZPubkey<G>,
|
|
|
) -> Result<Bucket, aead::Error> {
|
|
|
// Set the nonce and the key
|
|
|
let k = K {
|
|
|
@@ -397,31 +403,40 @@ impl BridgeTable {
|
|
|
Ok(BridgeLine::bucket_decode(
|
|
|
plaintext.as_slice().try_into().unwrap(),
|
|
|
&to_scalar(id, key),
|
|
|
+ reachability_pub,
|
|
|
))
|
|
|
}
|
|
|
|
|
|
/// Decrypt an individual encrypted bucket, given its id and key
|
|
|
#[cfg(feature = "bridgeauth")]
|
|
|
- pub fn decrypt_bucket_id(&self, id: u32, key: &[u8; 16]) -> Result<Bucket, aead::Error> {
|
|
|
+ pub fn decrypt_bucket_id(
|
|
|
+ &self,
|
|
|
+ id: u32,
|
|
|
+ key: &[u8; 16],
|
|
|
+ reachability_pub: &CMZPubkey<G>,
|
|
|
+ ) -> Result<Bucket, aead::Error> {
|
|
|
let encbucket: &EncryptedBucket = match self.encbuckets.get(&id) {
|
|
|
Some(encbucket) => encbucket,
|
|
|
None => panic!("Provided ID not found"),
|
|
|
};
|
|
|
- BridgeTable::decrypt_bucket(id, key, encbucket)
|
|
|
+ BridgeTable::decrypt_bucket(id, key, encbucket, reachability_pub)
|
|
|
}
|
|
|
- */
|
|
|
}
|
|
|
-/*
|
|
|
+
|
|
|
// Unit tests that require access to the testing-only function
|
|
|
// BridgeLine::random()
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
use super::*;
|
|
|
+ use cmz::cmz_group_init;
|
|
|
+ use sha2::Sha512;
|
|
|
|
|
|
#[test]
|
|
|
fn test_bridge_table() -> Result<(), aead::Error> {
|
|
|
// Create private keys for the Bucket Reachability credentials
|
|
|
- let reachability_priv = IssuerPrivKey::new(2);
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
+ cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
|
|
|
+ let (reachability_priv, reachability_pub) = BucketReachability::gen_keys(&mut rng, true);
|
|
|
// Create an empty bridge table
|
|
|
let mut btable: BridgeTable = Default::default();
|
|
|
// Make 20 buckets with one random bridge each
|
|
|
@@ -450,20 +465,21 @@ mod tests {
|
|
|
btable.encrypt_table(today, &reachability_priv);
|
|
|
// Try to decrypt a 1-bridge bucket
|
|
|
let key7 = btable.keys.get(&7u32).unwrap();
|
|
|
- let bucket7 = btable.decrypt_bucket_id(7, key7)?;
|
|
|
+ let bucket7 = btable.decrypt_bucket_id(7, key7, &reachability_pub)?;
|
|
|
println!("bucket 7 = {:?}", bucket7);
|
|
|
// Try to decrypt a 3-bridge bucket
|
|
|
let key24 = btable.keys.get(&24u32).unwrap();
|
|
|
- let bucket24 = btable.decrypt_bucket_id(24, key24)?;
|
|
|
+ let bucket24 = btable.decrypt_bucket_id(24, key24, &reachability_pub)?;
|
|
|
println!("bucket 24 = {:?}", bucket24);
|
|
|
// Try to decrypt a bucket with the wrong key
|
|
|
let key12 = btable.keys.get(&12u32).unwrap();
|
|
|
- let res = btable.decrypt_bucket_id(15, key12).unwrap_err();
|
|
|
+ let res = btable
|
|
|
+ .decrypt_bucket_id(15, key12, &reachability_pub)
|
|
|
+ .unwrap_err();
|
|
|
println!("bucket key mismatch = {:?}", res);
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
-*/
|
|
|
|
|
|
/// Convert an id and key to a Scalar attribute
|
|
|
pub fn to_scalar(id: u32, key: &[u8; 16]) -> Scalar {
|