Check that we can use the credential to read a bucket
This commit is contained in:
parent
77b92036c7
commit
450c62bfc7
|
@ -17,6 +17,7 @@ hex_fmt = "0.3"
|
||||||
aes-gcm = "0.8"
|
aes-gcm = "0.8"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
time = "0.2"
|
time = "0.2"
|
||||||
|
subtle = "2.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["u64_backend"]
|
default = ["u64_backend"]
|
||||||
|
|
|
@ -13,6 +13,7 @@ use aes_gcm::Aes128Gcm;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use subtle::ConstantTimeEq;
|
||||||
|
|
||||||
/// Each bridge information line is serialized into this many bytes
|
/// Each bridge information line is serialized into this many bytes
|
||||||
pub const BRIDGE_BYTES: usize = 220;
|
pub const BRIDGE_BYTES: usize = 220;
|
||||||
|
@ -194,6 +195,16 @@ impl BridgeTable {
|
||||||
plaintext.as_slice().try_into().unwrap(),
|
plaintext.as_slice().try_into().unwrap(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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> {
|
||||||
|
let encbucket = self.encbuckets[id as usize];
|
||||||
|
BridgeTable::decrypt_bucket(key, &encbucket)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unit tests that require access to the testing-only function
|
// Unit tests that require access to the testing-only function
|
||||||
|
@ -225,18 +236,15 @@ mod tests {
|
||||||
btable.encrypt_table();
|
btable.encrypt_table();
|
||||||
// Try to decrypt a 1-bridge bucket
|
// Try to decrypt a 1-bridge bucket
|
||||||
let key7 = btable.keys[7];
|
let key7 = btable.keys[7];
|
||||||
let encbucket7 = btable.encbuckets[7];
|
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
|
||||||
let bucket7 = BridgeTable::decrypt_bucket(&key7, &encbucket7)?;
|
|
||||||
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[24];
|
||||||
let encbucket24 = btable.encbuckets[24];
|
let bucket24 = btable.decrypt_bucket_id(24, &key24)?;
|
||||||
let bucket24 = BridgeTable::decrypt_bucket(&key24, &encbucket24)?;
|
|
||||||
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[12];
|
||||||
let encbucket15 = btable.encbuckets[15];
|
let res = btable.decrypt_bucket_id(15, &key12).unwrap_err();
|
||||||
let res = BridgeTable::decrypt_bucket(&key12, &encbucket15).unwrap_err();
|
|
||||||
println!("bucket key mismatch = {:?}", res);
|
println!("bucket key mismatch = {:?}", res);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -252,3 +260,16 @@ pub fn to_scalar(id: u32, key: [u8; 16]) -> Scalar {
|
||||||
// This cannot fail, since we're only using the low 20 bytes of b
|
// This cannot fail, since we're only using the low 20 bytes of b
|
||||||
Scalar::from_canonical_bytes(b).unwrap()
|
Scalar::from_canonical_bytes(b).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a Scalar attribute to an id and key if possible
|
||||||
|
pub fn from_scalar(s: Scalar) -> Result<(u32, [u8; 16]), aead::Error> {
|
||||||
|
// Check that the top 12 bytes of the Scalar are 0
|
||||||
|
let sbytes = s.as_bytes();
|
||||||
|
if sbytes[20..].ct_eq(&[0u8; 12]).unwrap_u8() == 0 {
|
||||||
|
return Err(aead::Error);
|
||||||
|
}
|
||||||
|
let id = u32::from_le_bytes(sbytes[16..20].try_into().unwrap());
|
||||||
|
let mut key: [u8; 16] = [0; 16];
|
||||||
|
key.copy_from_slice(&sbytes[..16]);
|
||||||
|
Ok((id, key))
|
||||||
|
}
|
||||||
|
|
|
@ -277,6 +277,11 @@ mod tests {
|
||||||
let resp = ba.handle_open_invite(req).unwrap();
|
let resp = ba.handle_open_invite(req).unwrap();
|
||||||
let cred =
|
let cred =
|
||||||
open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
|
open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
|
||||||
|
|
||||||
|
// 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();
|
||||||
println!("cred = {:?}", cred);
|
println!("cred = {:?}", cred);
|
||||||
|
println!("bucket = {:?}", bucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue