onyinyang 10 месяцев назад
Родитель
Сommit
d96b43e924
2 измененных файлов с 144 добавлено и 0 удалено
  1. 2 0
      src/lib.rs
  2. 142 0
      src/proto/update_cred.rs

+ 2 - 0
src/lib.rs

@@ -41,7 +41,9 @@ pub mod proto {
     pub mod level_up;
     pub mod open_invite;
     pub mod redeem_invite;
+    pub mod update_cred;
 }
+
 #[cfg(feature = "bridgeauth")]
 use bridge_table::BridgeTable;
 //    BridgeLine, EncryptedBucket, MAX_BRIDGES_PER_BUCKET, MIN_BUCKET_REACHABILITY,

+ 142 - 0
src/proto/update_cred.rs

@@ -0,0 +1,142 @@
+/*! A module for the protocol for a user to request the issuing of an updated credential after a key rotation has occurred
+
+
+They are allowed to do this as long as their current Lox credential is valid
+
+The user presents their current Lox credential:
+- id: revealed
+- bucket: blinded
+- trust_level: blinded
+- level_since: blinded
+- invites_remaining: blinded
+- blockages: 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 in the Lox
+  credential above
+- trust_level: blinded, but proved in ZK that it's the same as in the
+  Lox credential above
+- level_since: blinded, but proved in ZK that it's the same as in the
+  Lox credential above
+- invites_remaining: blinded, but proved in ZK that it's the same as in the Lox credential above
+- blockages: blinded, but proved in ZK that it's the same as in the
+  Lox credential above
+
+*/
+
+#[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;
+use cmz::*;
+use curve25519_dalek::ristretto::RistrettoPoint as G;
+use group::Group;
+use rand_core::RngCore;
+use sha2::Sha512;
+
+muCMZProtocol! { update_cred,
+    L: Lox { id: R, bucket: H, trust_level: H, level_since: H, invites_remaining: H, blockages: H },
+    N: Lox {id: J, bucket: H, trust_level: H, level_since: H, invites_remaining: H, blockages: H },
+    N.bucket = L.bucket,
+    N.trust_level = L.trust_level,
+    N.level_since = L.level_since,
+    N.invites_remaining = L.invites_remaining,
+    N.blockages = L.blockages,
+}
+
+pub fn request(
+    L: Lox,
+    pubkeys: CMZPubkey<G>,
+) -> Result<(update_cred::Request, update_cred::ClientState), CredentialError> {
+    let mut rng = rand::thread_rng();
+    cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
+
+    let N = Lox::using_pubkey(&pubkeys);
+    match update_cred::prepare(&mut rng, &L, N) {
+        Ok(req_state) => Ok(req_state),
+        Err(e) => Err(CredentialError::CMZError(e)),
+    }
+}
+
+#[cfg(feature = "bridgeauth")]
+impl BridgeAuth {
+    pub fn handle_update_cred(
+        &mut self,
+        req: update_cred::Request,
+    ) -> Result<update_cred::Reply, CredentialError> {
+        let mut rng = rand::thread_rng();
+
+        // Both of these must be true and should be true after rotate_lox_keys is called
+        if self.old_keys.lox_keys.is_empty() || self.old_filters.lox_filter.is_empty() {
+            return Err(CredentialError::CredentialMismatch);
+        }
+
+        let reqbytes = req.as_bytes();
+        let recvreq = update_cred::Request::try_from(&reqbytes[..]).unwrap();
+        match update_cred::handle(
+            &mut rng,
+            recvreq,
+            |L: &mut Lox, N: &mut Lox| {
+                // calling this function will automatically use the most recent old private key for
+                // verification and the new private key for issuing.
+
+                // Recompute the "error factors" using knowledge of our own
+                // (the issuer's) outdated private key instead of knowledge of the
+                // hidden attributes
+                let old_keys = match self
+                    .old_keys
+                    .lox_keys
+                    .iter()
+                    .find(|x| x.pub_key == *L.get_pubkey())
+                {
+                    Some(old_keys) => old_keys,
+                    None => return Err(CMZError::RevealAttrMissing("Key", "Mismatch")),
+                };
+                let old_priv_key = old_keys.priv_key.clone();
+                L.set_privkey(&old_priv_key);
+                N.set_privkey(&self.lox_priv);
+                Ok(())
+            },
+            |L: &Lox, _N: &Lox| {
+                let index = match self
+                    .old_keys
+                    .lox_keys
+                    .iter()
+                    .position(|x| x.pub_key == *L.get_pubkey())
+                {
+                    Some(index) => index,
+                    None => return Err(CMZError::RevealAttrMissing("Key", "Mismatch")),
+                };
+                if self
+                    .old_filters
+                    .lox_filter
+                    .get_mut(index)
+                    .unwrap()
+                    .filter(&L.id.unwrap())
+                    == SeenType::Seen
+                {
+                    return Err(CMZError::RevealAttrMissing("id", "Credential Expired"));
+                }
+                Ok(())
+            },
+        ) {
+            Ok((response, (_L_issuer, _N_issuer))) => Ok(response),
+            Err(e) => Err(CredentialError::CMZError(e)),
+        }
+    }
+}
+
+pub fn handle_response(
+    state: update_cred::ClientState,
+    rep: update_cred::Reply,
+) -> Result<Lox, CMZError> {
+    let replybytes = rep.as_bytes();
+    let recvreply = update_cred::Reply::try_from(&replybytes[..]).unwrap();
+    match state.finalize(recvreply) {
+        Ok(cred) => Ok(cred),
+        Err(_e) => Err(CMZError::Unknown),
+    }
+}