|
@@ -51,7 +51,6 @@ use super::super::dup_filter::SeenType;
|
|
|
use super::super::BridgeAuth;
|
|
|
use super::super::{scalar_u32, Scalar, G};
|
|
|
use super::errors::CredentialError;
|
|
|
-use super::level_up::{LEVEL_INVITATIONS, MAX_LEVEL};
|
|
|
use crate::lox_creds::{BucketReachability, Invitation, Lox};
|
|
|
use cmz::*;
|
|
|
use group::Group;
|
|
@@ -65,7 +64,7 @@ const SESSION_ID: &[u8] = b"issue_invite";
|
|
|
/// also add bits to the zero knowledge proof.
|
|
|
pub const INVITATION_EXPIRY: u32 = 15;
|
|
|
|
|
|
-muCMZProtocol! { issue_invite<max_invitations>,
|
|
|
+muCMZProtocol! { issue_invite,
|
|
|
[L: Lox {id: R, bucket: H, trust_level: H, level_since: H, invites_remaining: H, blockages: H}, B: BucketReachability { date: R, bucket: H } ],
|
|
|
[ I: Invitation { inv_id: J, date: S, bucket: H, blockages: H }, N: Lox {id: J, bucket: H, trust_level: H, level_since: H, invites_remaining: H, blockages: H }],
|
|
|
L.bucket = B.bucket,
|
|
@@ -75,18 +74,18 @@ muCMZProtocol! { issue_invite<max_invitations>,
|
|
|
N.level_since = L.level_since,
|
|
|
N.invites_remaining = L.invites_remaining - 1,
|
|
|
N.blockages = L.blockages,
|
|
|
- I. bucket = L.bucket,
|
|
|
+ I.bucket = L.bucket,
|
|
|
I.blockages = L.blockages
|
|
|
}
|
|
|
|
|
|
pub fn request(
|
|
|
+ rng: &mut (impl CryptoRng + RngCore),
|
|
|
L: Lox,
|
|
|
lox_pubkeys: CMZPubkey<G>,
|
|
|
B: BucketReachability,
|
|
|
inv_pub: CMZPubkey<G>,
|
|
|
today: u32,
|
|
|
) -> Result<(issue_invite::Request, issue_invite::ClientState), CredentialError> {
|
|
|
- let mut rng = rand::thread_rng();
|
|
|
cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
|
|
|
|
|
|
// Ensure the credential can be correctly shown: it must be the case
|
|
@@ -124,19 +123,21 @@ pub fn request(
|
|
|
));
|
|
|
}
|
|
|
|
|
|
- let params = issue_invite::Params {
|
|
|
- max_invitations: LEVEL_INVITATIONS[MAX_LEVEL].into(),
|
|
|
- };
|
|
|
+ let mut I: Invitation = Invitation::using_pubkey(&inv_pub);
|
|
|
+ I.inv_id = Some(Scalar::random(rng));
|
|
|
+ I.date = Some(today.into());
|
|
|
+ I.bucket = L.bucket;
|
|
|
+ I.blockages = L.blockages;
|
|
|
+
|
|
|
+ let mut N: Lox = Lox::using_pubkey(&lox_pubkeys);
|
|
|
+ N.id = Some(Scalar::random(rng));
|
|
|
+ N.bucket = L.bucket;
|
|
|
+ N.trust_level = L.trust_level;
|
|
|
+ N.level_since = L.level_since;
|
|
|
+ N.invites_remaining = Some(L.invites_remaining.unwrap() - Scalar::ONE);
|
|
|
+ N.blockages = L.blockages;
|
|
|
|
|
|
- match issue_invite::prepare(
|
|
|
- &mut rng,
|
|
|
- SESSION_ID,
|
|
|
- &L,
|
|
|
- &B,
|
|
|
- Invitation::using_pubkey(&inv_pub),
|
|
|
- Lox::using_pubkey(&lox_pubkeys),
|
|
|
- ¶ms,
|
|
|
- ) {
|
|
|
+ match issue_invite::prepare(rng, SESSION_ID, &L, &B, I, N) {
|
|
|
Ok(req_state) => Ok(req_state),
|
|
|
Err(e) => Err(CredentialError::CMZError(e)),
|
|
|
}
|
|
@@ -164,20 +165,11 @@ impl BridgeAuth {
|
|
|
if B.date.is_some_and(|b| b != today.into()) {
|
|
|
return Err(CMZError::RevealAttrMissing("date", "not today"));
|
|
|
}
|
|
|
- L.bucket = B.bucket;
|
|
|
- N.bucket = L.bucket;
|
|
|
- N.trust_level = L.trust_level;
|
|
|
- N.level_since = Some(today.into());
|
|
|
- N.invites_remaining = Some(L.invites_remaining.unwrap() - Scalar::ONE);
|
|
|
- N.blockages = L.blockages;
|
|
|
- I.bucket = N.bucket;
|
|
|
- I.blockages = L.blockages;
|
|
|
- Ok(issue_invite::Params {
|
|
|
- max_invitations: LEVEL_INVITATIONS[MAX_LEVEL].into(),
|
|
|
- })
|
|
|
+ I.date = Some(today.into());
|
|
|
+ Ok(())
|
|
|
},
|
|
|
- |_L: &Lox, _B: &BucketReachability, I: &Invitation, _N: &Lox| {
|
|
|
- if self.inv_id_filter.filter(&I.inv_id.unwrap()) == SeenType::Seen {
|
|
|
+ |L: &Lox, _B: &BucketReachability, _I: &Invitation, _N: &Lox| {
|
|
|
+ if self.id_filter.filter(&L.id.unwrap()) == SeenType::Seen {
|
|
|
return Err(CMZError::RevealAttrMissing("id", "Credential Expired"));
|
|
|
}
|
|
|
Ok(())
|
|
@@ -200,3 +192,138 @@ pub fn handle_response(
|
|
|
Err(_e) => Err(CMZError::Unknown),
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+#[cfg(all(test, feature = "bridgeauth"))]
|
|
|
+mod tests {
|
|
|
+ use super::*;
|
|
|
+ use crate::bridge_table;
|
|
|
+ use crate::mock_auth::TestHarness;
|
|
|
+ use crate::proto::{
|
|
|
+ issue_invite,
|
|
|
+ level_up::{self, LEVEL_INTERVAL},
|
|
|
+ migration, open_invite,
|
|
|
+ trust_promotion::{self, UNTRUSTED_INTERVAL},
|
|
|
+ };
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_issue_invite() {
|
|
|
+ let mut th = TestHarness::new();
|
|
|
+ let rng = &mut rand::thread_rng();
|
|
|
+ let open_invitation_request = open_invite::request(rng, th.ba.lox_pub.clone());
|
|
|
+ assert!(
|
|
|
+ open_invitation_request.is_ok(),
|
|
|
+ "Open invitation request should succeed"
|
|
|
+ );
|
|
|
+ let (request, client_state) = open_invitation_request.unwrap();
|
|
|
+ let invite = th.bdb.invite();
|
|
|
+ let open_invitation_response = th.ba.open_invitation(request, &invite.unwrap());
|
|
|
+ assert!(
|
|
|
+ open_invitation_response.is_ok(),
|
|
|
+ "Open invitation response from server should succeed"
|
|
|
+ );
|
|
|
+ let (response, _) = open_invitation_response.unwrap();
|
|
|
+ let creds = open_invite::handle_response(client_state, response);
|
|
|
+ println!("{}", th.ba.today());
|
|
|
+ assert!(creds.is_ok(), "Handle response should succeed");
|
|
|
+ th.advance_days((UNTRUSTED_INTERVAL + 1).try_into().unwrap());
|
|
|
+ println!("{}", th.ba.today());
|
|
|
+ let lox_cred = creds.unwrap();
|
|
|
+ let trust_promo_request = trust_promotion::request(
|
|
|
+ rng,
|
|
|
+ lox_cred.clone(),
|
|
|
+ th.ba.migrationkey_pub.clone(),
|
|
|
+ th.ba.today(),
|
|
|
+ );
|
|
|
+ assert!(
|
|
|
+ trust_promo_request.is_ok(),
|
|
|
+ "Trust Promotion request should succeed"
|
|
|
+ );
|
|
|
+ let (tp_request, tp_client_state) = trust_promo_request.unwrap();
|
|
|
+ let trust_promo_response = th.ba.handle_trust_promotion(tp_request);
|
|
|
+ assert!(
|
|
|
+ trust_promo_response.is_ok(),
|
|
|
+ "Trust promotion response from server should succeed"
|
|
|
+ );
|
|
|
+ let (response, enc) = trust_promo_response.unwrap();
|
|
|
+ let mig_cred = trust_promotion::handle_response(
|
|
|
+ th.ba.migration_pub.clone(),
|
|
|
+ tp_client_state,
|
|
|
+ response,
|
|
|
+ enc,
|
|
|
+ );
|
|
|
+ assert!(mig_cred.is_ok(), "Handle response should succeed");
|
|
|
+ let migration_request = migration::request(
|
|
|
+ rng,
|
|
|
+ lox_cred.clone(),
|
|
|
+ mig_cred.unwrap(),
|
|
|
+ th.ba.lox_pub.clone(),
|
|
|
+ );
|
|
|
+ assert!(
|
|
|
+ migration_request.is_ok(),
|
|
|
+ "Migration request should succeed"
|
|
|
+ );
|
|
|
+ let (mig_request, mig_client_state) = migration_request.unwrap();
|
|
|
+ let migration_response = th.ba.handle_migration(mig_request);
|
|
|
+ assert!(
|
|
|
+ migration_response.is_ok(),
|
|
|
+ "Migration response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = migration_response.unwrap();
|
|
|
+ let mut cred = migration::handle_response(mig_client_state, response);
|
|
|
+ assert!(cred.is_ok(), "Handle response should succeed");
|
|
|
+ let lox_cred = cred.unwrap();
|
|
|
+ let trust_level: u32 = scalar_u32(&lox_cred.clone().trust_level.unwrap()).unwrap();
|
|
|
+ th.advance_days(LEVEL_INTERVAL[trust_level as usize] + 1);
|
|
|
+ let (id, key) = bridge_table::from_scalar(lox_cred.bucket.unwrap()).unwrap();
|
|
|
+ let encbuckets = th.ba.enc_bridge_table().clone();
|
|
|
+ let reach_pub = th.ba.reachability_pub.clone();
|
|
|
+ let bucket = bridge_table::BridgeTable::decrypt_bucket(
|
|
|
+ id,
|
|
|
+ &key,
|
|
|
+ encbuckets.get(&id).unwrap(),
|
|
|
+ &reach_pub,
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ let reachcred = bucket.1.unwrap();
|
|
|
+
|
|
|
+ let level_up_request = level_up::request(
|
|
|
+ rng,
|
|
|
+ lox_cred.clone(),
|
|
|
+ reachcred.clone(),
|
|
|
+ th.ba.lox_pub.clone(),
|
|
|
+ th.ba.today(),
|
|
|
+ );
|
|
|
+ assert!(level_up_request.is_ok(), "Level up request should succeed");
|
|
|
+ let (level_up_request, level_up_client_state) = level_up_request.unwrap();
|
|
|
+ let level_up_response = th.ba.handle_level_up(level_up_request);
|
|
|
+ assert!(
|
|
|
+ level_up_response.is_ok(),
|
|
|
+ "Level up response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = level_up_response.unwrap();
|
|
|
+ cred = level_up::handle_response(level_up_client_state, response);
|
|
|
+ assert!(cred.is_ok(), "Handle response should succeed");
|
|
|
+ let level_up_cred = cred.unwrap();
|
|
|
+ let issue_invite_request = issue_invite::request(
|
|
|
+ rng,
|
|
|
+ level_up_cred.clone(),
|
|
|
+ th.ba.lox_pub.clone(),
|
|
|
+ reachcred.clone(),
|
|
|
+ th.ba.invitation_pub.clone(),
|
|
|
+ th.ba.today(),
|
|
|
+ );
|
|
|
+ let (issue_invite_request, issue_invite_client_state) = issue_invite_request.unwrap();
|
|
|
+ let issue_invite_response = th.ba.handle_issue_invite(issue_invite_request);
|
|
|
+ assert!(
|
|
|
+ issue_invite_response.is_ok(),
|
|
|
+ "Issue Invite response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = issue_invite_response.unwrap();
|
|
|
+ let i_cred = issue_invite::handle_response(issue_invite_client_state, response);
|
|
|
+ assert!(i_cred.is_ok(), "Handle response should succeed");
|
|
|
+ let issue_invite_cred = i_cred.unwrap();
|
|
|
+ th.verify_lox(&issue_invite_cred.clone().1);
|
|
|
+ th.verify_invitation(&issue_invite_cred.clone().0);
|
|
|
+ }
|
|
|
+}
|