Browse Source

Add migration extension

onyinyang 8 months ago
parent
commit
9390650146
2 changed files with 156 additions and 0 deletions
  1. 1 0
      src/lib.rs
  2. 155 0
      src/proto/migration.rs

+ 1 - 0
src/lib.rs

@@ -39,6 +39,7 @@ pub mod proto {
     pub mod errors;
     pub mod issue_invite;
     pub mod level_up;
+    pub mod migration;
     pub mod open_invite;
     pub mod redeem_invite;
     pub mod update_cred;

+ 155 - 0
src/proto/migration.rs

@@ -0,0 +1,155 @@
+/*! A module for the protocol for the user to migrate from one bucket to
+another and change trust level from untrusted (trust level 0) to trusted
+(trust level 1).
+
+The user presents their current Lox credential:
+
+- id: revealed
+- bucket: blinded
+- trust_level: revealed to be 0
+- level_since: blinded
+- invites_remaining: revealed to be 0
+- blockages: revealed to be 0
+
+and a Migration credential:
+
+- id: revealed as the same as the Lox credential id above
+- from_bucket: blinded, but proved in ZK that it's the same as the
+  bucket in the Lox credential above
+- to_bucket: blinded
+
+and a new Lox credential to be issued:
+
+- id: jointly chosen by the user and BA
+- bucket: blinded, but proved in ZK that it's the same as the to_bucket
+  in the Migration credential above
+- trust_level: 1
+- level_since: today
+- invites_remaining: 0
+- blockages: 0
+
+*/
+
+#[cfg(feature = "bridgeauth")]
+use super::super::dup_filter::SeenType;
+#[cfg(feature = "bridgeauth")]
+use super::super::BridgeAuth;
+use super::errors::CredentialError;
+use crate::lox_creds::{Lox, Migration};
+#[cfg(feature = "bridgeauth")]
+use crate::scalar_u32;
+use cmz::*;
+use curve25519_dalek::ristretto::RistrettoPoint as G;
+use curve25519_dalek::scalar::Scalar;
+use group::Group;
+use rand_core::RngCore;
+use sha2::Sha512;
+
+muCMZProtocol! { migration,
+    [ L: Lox { id: R, bucket: H, trust_level: R, level_since: H, invites_remaining: R, blockages: R },
+    M: Migration { lox_id: R, from_bucket: H, to_bucket: H } ],
+    N: Lox {id: J, bucket: H, trust_level: I, level_since: S, invites_remaining: I, blockages: I },
+    L.id = M.lox_id,
+    L.bucket = M.from_bucket,
+    N.bucket = M.to_bucket,
+}
+
+pub fn request(
+    L: Lox,
+    M: Migration,
+    pubkeys: CMZPubkey<G>,
+) -> Result<(migration::Request, migration::ClientState), CredentialError> {
+    let mut rng = rand::thread_rng();
+    cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
+
+    // Ensure that the credenials can be correctly shown; that is, the
+    // ids match and the Lox credential bucket matches the Migration
+    // credential from_bucket
+    if L.id.is_some_and(|i| i != M.lox_id.unwrap()) {
+        return Err(CredentialError::CredentialMismatch);
+    }
+
+    // This protocol only allows migrating from trust level 0 to trust
+    // level 1
+    if L.trust_level.is_some_and(|t| t != Scalar::ZERO) {
+        return Err(CredentialError::InvalidField(
+            String::from("trust_level"),
+            String::from("must be zero"),
+        ));
+    }
+
+    if L.bucket.is_some_and(|b| b != M.from_bucket.unwrap()) {
+        return Err(CredentialError::CredentialMismatch);
+    }
+
+    let mut N = Lox::using_pubkey(&pubkeys);
+    N.trust_level = Some(Scalar::ONE);
+
+    match migration::prepare(&mut rng, &L, &M, N) {
+        Ok(req_state) => Ok(req_state),
+        Err(e) => Err(CredentialError::CMZError(e)),
+    }
+}
+
+#[cfg(feature = "bridgeauth")]
+impl BridgeAuth {
+    pub fn handle_migration(
+        &mut self,
+        req: migration::Request,
+    ) -> Result<migration::Reply, CredentialError> {
+        let mut rng = rand::thread_rng();
+        let reqbytes = req.as_bytes();
+        let recvreq = migration::Request::try_from(&reqbytes[..]).unwrap();
+
+        let today = self.today();
+        match migration::handle(
+            &mut rng,
+            recvreq,
+            |L: &mut Lox, M: &mut Migration, N: &mut Lox| {
+                match scalar_u32(&L.trust_level.unwrap()) {
+                    Some(v) if v as usize == 0 => v,
+                    _ => {
+                        // This error should be improved i.e., InvalidAttr and the type
+                        // with a description
+                        return Err(CMZError::RevealAttrMissing(
+                            "migration",
+                            "Could not be converted to u32 or trust_level not 0",
+                        ));
+                    }
+                };
+                L.set_privkey(&self.lox_priv);
+                M.set_privkey(&self.migration_priv);
+                N.set_privkey(&self.lox_priv);
+                L.id = M.lox_id;
+                L.bucket = M.from_bucket;
+                N.bucket = M.to_bucket;
+                N.trust_level = Some(Scalar::ONE);
+                N.level_since = Some(today.into());
+                N.invites_remaining = Some(Scalar::ZERO);
+                N.blockages = Some(Scalar::ZERO);
+                Ok(())
+            },
+            |L: &Lox, _M: &Migration, _N: &Lox| {
+                if self.id_filter.filter(&L.id.unwrap()) == SeenType::Seen {
+                    return Err(CMZError::RevealAttrMissing("id", ""));
+                }
+                Ok(())
+            },
+        ) {
+            Ok((response, (_L_issuer, _M_isser, _N_issuer))) => Ok(response),
+            Err(e) => Err(CredentialError::CMZError(e)),
+        }
+    }
+}
+
+pub fn handle_response(
+    state: migration::ClientState,
+    rep: migration::Reply,
+) -> Result<Lox, CMZError> {
+    let replybytes = rep.as_bytes();
+    let recvreply = migration::Reply::try_from(&replybytes[..]).unwrap();
+    match state.finalize(recvreply) {
+        Ok(cred) => Ok(cred),
+        Err(_e) => Err(CMZError::Unknown),
+    }
+}