2 Commitit b7571cfcac ... 51f6c1fdb3

Tekijä SHA1 Viesti Päivämäärä
  onyinyang 51f6c1fdb3 Add tests for update_cred 3 viikkoa sitten
  onyinyang dc1fac9008 Add rotate keys functions to lib.rs 3 viikkoa sitten
2 muutettua tiedostoa jossa 115 lisäystä ja 7 poistoa
  1. 51 0
      src/lib.rs
  2. 64 7
      src/proto/update_cred.rs

+ 51 - 0
src/lib.rs

@@ -399,6 +399,57 @@ impl BridgeAuth {
         }
     }
 
+    pub fn rotate_lox_keys(&mut self, rng: &mut (impl CryptoRng + RngCore)) {
+        let (updated_lox_priv, updated_lox_pub) = Lox::gen_keys(rng, true);
+        // Store the old keys until the next key rotation (this should happen no more than 511 days after the
+        // last rotation to ensure that all credentials issued with the old key can be updated
+        self.old_keys.lox_keys.push(OldKeyStore {
+            priv_key: self.lox_priv.clone(),
+            pub_key: self.lox_pub.clone(),
+        });
+        // Move the old lox id filter to the old_lox_id_filter
+        self.old_filters.lox_filter.push(self.id_filter.clone());
+        // TODO: Commit to the new keys and post the commitment somewhere public that can be verified
+        // by users, ideally
+        self.lox_priv = updated_lox_priv;
+        self.lox_pub = updated_lox_pub;
+        self.id_filter = Default::default();
+    }
+
+    pub fn rotate_invitation_keys(&mut self, rng: &mut (impl CryptoRng + RngCore)) {
+        let (updated_invitation_priv, updated_invitation_pub) = Invitation::gen_keys(rng, true);
+        // Store the old keys until the next key rotation (this should happen no more than 511 days after the
+        // last rotation to ensure that all credentials issued with the old key can be updated
+        self.old_keys.invitation_keys.push(OldKeyStore {
+            priv_key: self.invitation_priv.clone(),
+            pub_key: self.invitation_pub.clone(),
+        });
+        // Move the old invitation id filter to the old_invitation_id_filter
+        self.old_filters
+            .invitation_filter
+            .push(self.inv_id_filter.clone());
+        // TODO: Commit to the new keys and post the commitment somewhere public that can be verified
+        // by users, ideally
+        self.invitation_priv = updated_invitation_priv;
+        self.invitation_pub = updated_invitation_pub;
+        self.inv_id_filter = Default::default();
+    }
+
+    pub fn rotate_bridgedb_keys(&mut self, new_bridgedb_pub: VerifyingKey) {
+        // Store the old verifying key until the next key rotation (this should happen no more often than the
+        // we would reasonably expect a user to redeem an open invitation token to ensure that all invitations
+        // issued with the old key can be updated)
+        self.old_keys.bridgedb_key.push(self.bridgedb_pub);
+        // Move the old lox id filter to the old_lox_id_filter
+        self.old_filters
+            .openinv_filter
+            .push(self.bridgedb_pub_filter.clone());
+        // TODO: Commit to the new keys and post the commitment somewhere public that can be verified
+        // by users, ideally
+        self.bridgedb_pub = new_bridgedb_pub;
+        self.bridgedb_pub_filter = Default::default();
+    }
+
     /// Insert a set of open invitation bridges.
     ///
     /// Each of the bridges will be given its own open invitation

+ 64 - 7
src/proto/update_cred.rs

@@ -29,10 +29,10 @@ and a new Lox credential to be issued:
 use super::super::dup_filter::SeenType;
 #[cfg(feature = "bridgeauth")]
 use super::super::BridgeAuth;
+use super::super::{Scalar, G};
 use super::errors::CredentialError;
 use crate::lox_creds::Lox;
 use cmz::*;
-use curve25519_dalek::ristretto::RistrettoPoint as G;
 use group::Group;
 use rand::{CryptoRng, RngCore};
 use sha2::Sha512;
@@ -55,8 +55,15 @@ pub fn request(
     pubkeys: CMZPubkey<G>,
 ) -> Result<(update_cred::Request, update_cred::ClientState), CredentialError> {
     cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
+    let mut N: Lox = Lox::using_pubkey(&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 = L.invites_remaining;
+    N.blockages = L.blockages;
 
-    match update_cred::prepare(&mut *rng, SESSION_ID, &L, Lox::using_pubkey(&pubkeys)) {
+    match update_cred::prepare(&mut *rng, SESSION_ID, &L, N) {
         Ok(req_state) => Ok(req_state),
         Err(e) => Err(CredentialError::CMZError(e)),
     }
@@ -66,9 +73,10 @@ pub fn request(
 impl BridgeAuth {
     pub fn handle_update_cred(
         &mut self,
-        rng: &mut (impl CryptoRng + RngCore),
+        old_pub_key: CMZPubkey<G>,
         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);
@@ -77,7 +85,7 @@ impl BridgeAuth {
         let reqbytes = req.as_bytes();
         let recvreq = update_cred::Request::try_from(&reqbytes[..]).unwrap();
         match update_cred::handle(
-            &mut *rng,
+            &mut rng,
             SESSION_ID,
             recvreq,
             |L: &mut Lox, N: &mut Lox| {
@@ -91,10 +99,13 @@ impl BridgeAuth {
                     .old_keys
                     .lox_keys
                     .iter()
-                    .find(|x| x.pub_key == *L.get_pubkey())
+                    .find(|x| x.pub_key == old_pub_key)
                 {
                     Some(old_keys) => old_keys,
-                    None => return Err(CMZError::RevealAttrMissing("Key", "Mismatch")),
+                    None => {
+                        println!("Back here");
+                        return Err(CMZError::RevealAttrMissing("Key", "Mismatch"));
+                    }
                 };
                 let old_priv_key = old_keys.priv_key.clone();
                 L.set_privkey(&old_priv_key);
@@ -106,7 +117,7 @@ impl BridgeAuth {
                     .old_keys
                     .lox_keys
                     .iter()
-                    .position(|x| x.pub_key == *L.get_pubkey())
+                    .position(|x| x.pub_key == old_pub_key)
                 {
                     Some(index) => index,
                     None => return Err(CMZError::RevealAttrMissing("Key", "Mismatch")),
@@ -141,3 +152,49 @@ pub fn handle_response(
         Err(_e) => Err(CMZError::Unknown),
     }
 }
+
+#[cfg(all(test, feature = "bridgeauth"))]
+mod tests {
+    use super::*;
+    use crate::mock_auth::TestHarness;
+    use crate::proto::{open_invite, update_cred};
+
+    #[test]
+    fn test_update_cred() {
+        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);
+        assert!(creds.is_ok(), "Handle response should succeed");
+        let old_pub = th.ba.lox_pub.clone();
+        th.ba.rotate_lox_keys(rng);
+        let update_cred_request = update_cred::request(rng, creds.unwrap(), th.ba.lox_pub.clone());
+        assert!(
+            update_cred_request.is_ok(),
+            "Update credential request should succeed"
+        );
+        let (request, client_state) = update_cred_request.unwrap();
+        let update_cred_response = th.ba.handle_update_cred(old_pub, request);
+        println!("Update cred response: {:?}", update_cred_response);
+        assert!(
+            update_cred_response.is_ok(),
+            "Update cred response from server should succeed"
+        );
+        let response = update_cred_response.unwrap();
+        let creds = update_cred::handle_response(client_state, response);
+        assert!(creds.is_ok(), "Handle response should succeed");
+        th.verify_lox(&creds.unwrap());
+    }
+}