Handle the response of the trust promotion protocol to produce the Migration credential
This commit is contained in:
parent
03de724a8c
commit
6013386f07
|
@ -269,6 +269,17 @@ impl BridgeAuth {
|
|||
* cred.P;
|
||||
return Q == cred.Q;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Verify the MAC on a Migration credential
|
||||
pub fn verify_migration(&self, cred: &cred::Migration) -> bool {
|
||||
let Q = (self.migration_priv.x[0]
|
||||
+ cred.lox_id * self.migration_priv.x[1]
|
||||
+ cred.from_bucket * self.migration_priv.x[2]
|
||||
+ cred.to_bucket * self.migration_priv.x[3])
|
||||
* cred.P;
|
||||
return Q == cred.Q;
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to extract a u64 from a Scalar
|
||||
|
|
|
@ -8,7 +8,9 @@ that the credentials contain the bucket attributes, which include both
|
|||
the id and the bucket decrytpion key, but the table just contains the
|
||||
bucket ids.) */
|
||||
|
||||
use curve25519_dalek::ristretto::CompressedRistretto;
|
||||
use curve25519_dalek::ristretto::RistrettoBasepointTable;
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
use sha2::Digest;
|
||||
|
@ -21,6 +23,7 @@ use rand::RngCore;
|
|||
use std::collections::HashMap;
|
||||
|
||||
use super::bridge_table;
|
||||
use super::cred::Migration;
|
||||
use super::IssuerPrivKey;
|
||||
use super::CMZ_B_TABLE;
|
||||
|
||||
|
@ -168,3 +171,52 @@ impl MigrationTable {
|
|||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypt an encrypted Migration credential given Qk, the known
|
||||
/// attributes id and from_bucket for the Migration credential, and a
|
||||
/// HashMap mapping labels to ciphertexts.
|
||||
pub fn decrypt_cred(
|
||||
Qk: &RistrettoPoint,
|
||||
lox_id: &Scalar,
|
||||
from_bucket: &Scalar,
|
||||
enc_migration_table: &HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>,
|
||||
) -> Option<Migration> {
|
||||
// Compute the hash of (id, from_bucket, Qk)
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&lox_id.as_bytes()[..]);
|
||||
hasher.update(&from_bucket.as_bytes()[..]);
|
||||
hasher.update(&Qk.compress().as_bytes()[..]);
|
||||
let fullhash = hasher.finalize();
|
||||
|
||||
// Use the first half of the above hash as the label
|
||||
let mut label: [u8; 16] = [0; 16];
|
||||
label[..].copy_from_slice(&fullhash[..16]);
|
||||
|
||||
// Look up the label in the HashMap
|
||||
let ciphertext = enc_migration_table.get(&label)?;
|
||||
|
||||
// Create the decryption key from the 2nd half of the hash
|
||||
let aeskey = GenericArray::from_slice(&fullhash[16..]);
|
||||
|
||||
// Decrypt
|
||||
let nonce = GenericArray::from_slice(&ciphertext[..12]);
|
||||
let cipher = Aes128Gcm::new(aeskey);
|
||||
let plaintext: Vec<u8> = match cipher.decrypt(&nonce, ciphertext[12..].as_ref()) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return None,
|
||||
};
|
||||
let plaintextbytes = plaintext.as_slice();
|
||||
let mut to_bucket_bytes: [u8; 32] = [0; 32];
|
||||
to_bucket_bytes.copy_from_slice(&plaintextbytes[..32]);
|
||||
let to_bucket = Scalar::from_bytes_mod_order(to_bucket_bytes);
|
||||
let P = CompressedRistretto::from_slice(&plaintextbytes[32..64]).decompress()?;
|
||||
let Q = CompressedRistretto::from_slice(&plaintextbytes[64..]).decompress()?;
|
||||
|
||||
Some(Migration {
|
||||
P,
|
||||
Q,
|
||||
lox_id: *lox_id,
|
||||
from_bucket: *from_bucket,
|
||||
to_bucket,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -89,6 +89,13 @@ fn test_trust_promotion() {
|
|||
ba.advance_days(47);
|
||||
|
||||
let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap();
|
||||
let resp = ba.handle_trust_promotion(promreq).unwrap();
|
||||
println!("resp = {:?}", resp);
|
||||
let promresp = ba.handle_trust_promotion(promreq).unwrap();
|
||||
let migcred = trust_promotion::handle_response(promstate, promresp).unwrap();
|
||||
println!("resp = {:?}", migcred);
|
||||
assert!(ba.verify_migration(&migcred));
|
||||
// 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();
|
||||
println!("bucket = {:?}", bucket);
|
||||
}
|
||||
|
|
|
@ -527,3 +527,23 @@ impl BridgeAuth {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle the response to the request, producing a Migration credential
|
||||
/// if successful.
|
||||
///
|
||||
/// The Migration credential can then be used in the migration protocol
|
||||
/// to actually upgrade to trust level 1.
|
||||
pub fn handle_response(state: State, resp: Response) -> Result<cred::Migration, ProofError> {
|
||||
if resp.Pk.is_identity() {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
}
|
||||
|
||||
// Decrypt the MAC on the Migration Key credential
|
||||
let Qk = resp.EncQk.1 - (state.d * resp.EncQk.0);
|
||||
|
||||
// Use Qk to locate and decrypt the Migration credential
|
||||
match migration_table::decrypt_cred(&Qk, &state.id, &state.bucket, &resp.enc_migration_table) {
|
||||
Some(m) => Ok(m),
|
||||
None => Err(ProofError::VerificationFailure),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue