Add Key rotation endpoints

Closes #65 (closed)

This MR introduces key rotation logic for the keys that create open invitation tokens, invitation credentials, and Lox credentials.

Unfortunately since it's not possible to make an HTTP request directly from the wasm, there isn't a good way to automate the credential update process. The best we can do is call update_cred directly from the check_lox_pubkeys_update or check_invitation_pubkeys_update function so that if there is a key update, it prepares the request automatically. If a key rotation is indicated, the resulting request still needs to be sent to the distributor and the result of that request handled with the handle_update_cred function, so this will require changes to the Tor browser integration but I think that would be required anyway.

I would recommend that a calls to check_lox_pubkeys_updateand check_invitation_pubkeys_update should be made at a regular interval, maybe about once/week (and only if a user has an invitation for the latter case) or so and if it returns a {true, update_cred_request}, then the work flow is:

  • replace the old lox_pub pubkey with the new one
  • send the update_cred_request or update_invite_request to the lox authority's updatecred or updateinvite endpoint
  • call the handle_update_cred or handle_update_invite function with the response from that request

We want to avoid users requesting to update their credential immediately prior to another lox endpoint request so that the two actions can not be linked as it can leak information about the updated credential. To illustrate this, if the number of requests per day is relatively low and the lox pubkey was rotated more than 50 days ago, a request for a credential update immediately prior to an issue_invite request for example, would allow the LA to know that the user requesting the invitation hasn't engaged with the lox authority for 50 days, which would give an indication of their trust level and the time the credential was last issued. If the credential can be updated closer to the time of the key change, it reduces the likelihood of leaking extra information.

I think the case of open invitations is the exception here. A user presents the invitation token in plain text anyway, so I think we can just add on to the existing protocol to check if it was issued with an old key.

Still TODO:

  • how often do we need to rotate keys? Can this be automated?
Edited by onyinyang

Merge request reports

Loading
+60 −1
Changes for crates/lox-distributor/src/lox_context.rs: 60 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ use lox_library::{
    bridge_table::{BridgeLine, EncryptedBucket, MAX_BRIDGES_PER_BUCKET},
    proto::{
        blockage_migration, check_blockage, issue_invite, level_up, migration, open_invite,
        redeem_invite, trust_promotion,
        redeem_invite, trust_promotion, update_cred, update_invite,
    },
    BridgeAuth, BridgeDb, IssuerPubKey, OpenInvitationError,
};
@@ -502,6 +502,17 @@ impl LoxServerContext {
        }
    }

    fn update_cred(&self, req: update_cred::Request) -> Result<update_cred::Response, ProofError> {
        self.ba.lock().unwrap().handle_update_cred(req)
    }

    fn update_invite(
        &self,
        req: update_invite::Request,
    ) -> Result<update_invite::Response, ProofError> {
        self.ba.lock().unwrap().handle_update_invite(req)
    }

    // Return the serialized encrypted bridge table as an HTTP response
    pub fn send_reachability_cred(self) -> Response<BoxBody<Bytes, Infallible>> {
        let enc_table = self.encrypt_table();
@@ -762,6 +773,54 @@ impl LoxServerContext {
            }
        }
    }

    pub fn verify_and_send_update_cred(&self, request: Bytes) -> Response<BoxBody<Bytes, Infallible>> {
        let req: update_cred::Request = match serde_json::from_slice(&request) {
            Ok(req) => req,
            Err(e) => {
                let response = json!({"error": e.to_string()});
                let val = serde_json::to_string(&response).unwrap();
                return prepare_header(val);
            }
        };
        match self.update_cred(req) {
            Ok(resp) => {
                let response = serde_json::to_string(&resp).unwrap();
                self.metrics.update_cred_count.inc();
                prepare_header(response)
            }
            Err(e) => {
                println!("Invalid Update Credential request, Proof Error");
                let response = json!({"error": e.to_string()});
                let val = serde_json::to_string(&response).unwrap();
                prepare_header(val)
            }
        }
    }

    pub(crate) fn verify_and_send_update_invite(&self, request: Bytes) -> Response<BoxBody<Bytes, Infallible>> {
        let req: update_invite::Request = match serde_json::from_slice(&request) {
            Ok(req) => req,
            Err(e) => {
                let response = json!({"error": e.to_string()});
                let val = serde_json::to_string(&response).unwrap();
                return prepare_header(val);
            }
        };
        match self.update_invite(req) {
            Ok(resp) => {
                let response = serde_json::to_string(&resp).unwrap();
                self.metrics.update_invite_count.inc();
                prepare_header(response)
            }
            Err(e) => {
                println!("Invalid Update Invite request, Proof Error");
                let response = json!({"error": e.to_string()});
                let val = serde_json::to_string(&response).unwrap();
                prepare_header(val)
            }
        }
    }
}

fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, Infallible> {
+16 −0
Changes for crates/lox-distributor/src/metrics.rs: 16 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ pub struct Metrics {
    pub redeem_invite_count: Counter,
    pub check_blockage_count: Counter,
    pub blockage_migration_count: Counter,
    pub update_cred_count: Counter,
    pub update_invite_count: Counter,
    pub k_reset_count: Counter,
    pub invites_requested: Counter,
}
@@ -43,6 +45,8 @@ impl Default for Metrics {
        let redeem_invite_count = Counter::default();
        let check_blockage_count = Counter::default();
        let blockage_migration_count = Counter::default();
        let update_cred_count = Counter::default();
        let update_invite_count = Counter::default();
        let k_reset_count = Counter::default();
        let invites_requested = Counter::default();

@@ -59,6 +63,8 @@ impl Default for Metrics {
            redeem_invite_count,
            check_blockage_count,
            blockage_migration_count,
            update_cred_count,
            update_invite_count,
            k_reset_count,
            invites_requested,
        }
@@ -129,6 +135,16 @@ impl Metrics {
            "number of blockage migration requests",
            self.blockage_migration_count.clone(),
        );
        r.register(
            "update_cred_counter",
            "number of update credential requests",
            self.update_cred_count.clone(),
        );
        r.register(
            "update_invite_counter",
            "number of update invitation requests",
            self.update_invite_count.clone(),
        );
        r.register(
            "k_reset_counter",
            "number of times k has reset to 0",
+107 −5
Changes for crates/lox-distributor/src/request_handler.rs: 107 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -64,6 +64,14 @@ where
                let bytes = req.into_body().collect().await.unwrap().to_bytes();
                cloned_context.verify_and_send_blockage_migration(bytes)
            }),
            (&Method::POST, "/updatecred") => Ok::<_, Infallible>({
                let bytes = req.into_body().collect().await.unwrap().to_bytes();
                cloned_context.verify_and_send_update_cred(bytes)
            }),
            (&Method::POST, "/updateinvite") => Ok::<_, Infallible>({
                let bytes = req.into_body().collect().await.unwrap().to_bytes();
                cloned_context.verify_and_send_update_invite(bytes)
            }),
            _ => {
                // Return 404 not found response.
                Ok(Response::builder()
@@ -103,6 +111,8 @@ mod tests {
        fn redeeminvite(&self, request: proto::redeem_invite::Request) -> Request<B>;
        fn checkblockage(&self, request: proto::check_blockage::Request) -> Request<B>;
        fn blockagemigration(&self, request: proto::blockage_migration::Request) -> Request<B>;
        fn updatecred(&self, request: proto::update_cred::Request) -> Request<B>;
        fn updateinvite(&self, request: proto::update_invite::Request) -> Request<B>;
    }

    struct LoxClientMock {}
@@ -222,6 +232,26 @@ mod tests {
                .body(full(req_str))
                .unwrap()
        }

        fn updatecred(&self, request: proto::update_cred::Request) -> Request<BoxedBody> {
            let req_str = serde_json::to_string(&request).unwrap();
            Request::builder()
                .header("Content-Type", "application/json")
                .method("POST")
                .uri("http://localhost/updatecred")
                .body(full(req_str))
                .unwrap()
        }

        fn updateinvite(&self, request: proto::update_invite::Request) -> Request<BoxedBody> {
            let req_str = serde_json::to_string(&request).unwrap();
            Request::builder()
                .header("Content-Type", "application/json")
                .method("POST")
                .uri("http://localhost/updateinvite")
                .body(full(req_str))
                .unwrap()
        }
    }

    struct TestHarness {
@@ -267,6 +297,14 @@ mod tests {
            self.context.advance_days_test(days)
        }

        fn rotate_lox_keys(&mut self) {
            self.context.ba.lock().unwrap().rotate_lox_keys();
        }

        fn rotate_invitation_keys(&mut self) {
            self.context.ba.lock().unwrap().rotate_invitation_keys();
        }

        fn simulate_blocking(
            &mut self,
            cred: lox_library::cred::Lox,
@@ -403,10 +441,10 @@ mod tests {
        let open_response_obj = serde_json::from_str(&open_resp).unwrap();

        // Get pubkeys
        let pubkey_request = lc.pubkeys();
        let pubkey_response = handle(th.context.clone(), pubkey_request).await.unwrap();
        let pubkeys = body_to_string(pubkey_response).await;
        let pubkeys_obj: lox_utils::PubKeys = serde_json::from_str(&pubkeys).unwrap();
        let mut pubkey_request = lc.pubkeys();
        let mut pubkey_response = handle(th.context.clone(), pubkey_request).await.unwrap();
        let mut pubkeys = body_to_string(pubkey_response).await;
        let mut pubkeys_obj: lox_utils::PubKeys = serde_json::from_str(&pubkeys).unwrap();

        // Test Trust Promotion and get response
        let lox_cred = lox_library::proto::open_invite::handle_response(
@@ -550,9 +588,42 @@ mod tests {
            Err(e) => panic!("Error: Issue invite credential error {:?}", e.to_string()),
        };

        // Test Update Invitation
        let reissue_invite_result = match proto::update_invite::request(
            &issue_invite_cred.1,
            &pubkeys_obj.invitation_pub,
        ) {
            Ok(reissue_invite_result) => reissue_invite_result,
            Err(e) => panic!(
                "Error: Proof error from update invitation {:?}",
                e.to_string()
            ),
        };
        th.rotate_invitation_keys();
        let reissue_invite_request = lc.updateinvite(reissue_invite_result.0);
        let reissue_invite_response = handle(th.context.clone(), reissue_invite_request)
            .await
            .unwrap();
        assert_eq!(reissue_invite_response.status(), StatusCode::OK);
        let reissued_invite_resp = body_to_string(reissue_invite_response).await;
        let reissued_invite_response_obj = serde_json::from_str(&reissued_invite_resp).unwrap();
        // Get pubkeys
        pubkey_request = lc.pubkeys();
        pubkey_response = handle(th.context.clone(), pubkey_request).await.unwrap();
        pubkeys = body_to_string(pubkey_response).await;
        pubkeys_obj = serde_json::from_str(&pubkeys).unwrap();
        let reissue_invite_cred = match lox_library::proto::update_invite::handle_response(
            reissue_invite_result.1,
            reissued_invite_response_obj,
            &pubkeys_obj.invitation_pub,
        ) {
            Ok(reissue_invite_cred) => reissue_invite_cred,
            Err(e) => panic!("Error: Issue invite credential error {:?}", e.to_string()),
        };

        // Test Redeem Invite
        let new_invite = match proto::redeem_invite::request(
            &issue_invite_cred.1,
            &reissue_invite_cred,
            &pubkeys_obj.invitation_pub,
            test_today(31 + 14),
        ) {
@@ -658,6 +729,37 @@ mod tests {
            .await
            .unwrap();
        assert_eq!(blockagemig_response.status(), StatusCode::OK);

        let new_migration_resp = body_to_string(blockagemig_response).await;
        let new_migration_response_obj = serde_json::from_str(&new_migration_resp).unwrap();

        let new_migrated_cred = match lox_library::proto::blockage_migration::handle_response(
            migration_result.1,
            new_migration_response_obj,
            &pubkeys_obj.lox_pub,
        ) {
            Ok(new_lox_cred) => new_lox_cred,
            Err(e) => panic!(
                "Error: Blockage migration credential error {:?}",
                e.to_string()
            ),
        };
        // Rotate Keys
        th.rotate_lox_keys();

        // Test Upgrade Cred
        let update_cred_request =
            match proto::update_cred::request(&new_migrated_cred, &pubkeys_obj.lox_pub) {
                Ok(update_cred_request) => update_cred_request,
                Err(e) => panic!(
                    "Error: Proof error from update credential {:?}",
                    e.to_string()
                ),
            };

        let update_request = lc.updatecred(update_cred_request.0);
        let update_response = handle(th.context.clone(), update_request).await.unwrap();
        assert_eq!(update_response.status(), StatusCode::OK);
    }

    fn empty() -> BoxBody<Bytes, Infallible> {
+1 −1
Changes for crates/lox-distributor/db_test_file.json: 1 added line, 1 removed line.
Original line number Diff line number Diff line
{"db":{"keypair":[204,238,11,116,156,118,4,211,248,33,27,24,232,54,121,192,254,153,96,178,98,227,14,25,34,22,127,109,27,182,165,139],"pubkey":[83,135,201,149,116,61,213,153,225,79,182,248,93,101,224,98,33,226,62,202,72,25,57,69,204,166,55,215,232,35,71,137],"openinv_buckets":[],"distributed_buckets":[],"current_k":0,"daily_bridges_distributed":0},"ba":{"lox_priv":{"x0tilde":[227,145,242,28,74,205,182,234,229,104,117,240,121,109,18,7,251,13,102,161,79,121,143,194,104,160,47,206,52,211,115,11],"x":[[133,79,194,118,81,162,139,47,86,77,180,142,217,128,8,172,230,94,42,83,220,87,214,115,21,176,97,89,243,34,97,0],[9,30,66,74,80,78,76,230,4,116,134,225,45,171,66,149,107,77,39,3,144,166,142,88,3,171,231,16,162,125,40,12],[218,74,158,188,146,164,67,23,157,193,110,203,172,81,215,160,110,68,248,49,139,25,234,161,199,220,4,251,67,33,116,12],[141,127,236,195,109,31,123,191,252,107,148,2,203,199,31,51,30,215,182,100,140,241,113,40,63,163,253,20,91,177,220,7],[133,60,158,14,240,252,72,208,66,5,31,20,45,107,145,175,124,255,133,227,93,147,147,34,173,161,45,50,98,47,128,0],[169,184,123,196,81,223,224,244,224,199,122,8,143,0,220,17,178,213,191,28,108,53,234,53,210,113,89,96,219,102,99,2],[6,57,248,101,93,209,179,117,187,18,217,170,50,170,214,72,14,228,10,26,121,146,223,139,190,231,179,72,89,73,190,6]]},"lox_pub":{"X":[[112,133,69,67,116,178,255,100,189,178,27,16,218,91,145,37,1,178,86,38,151,248,84,91,59,237,119,96,247,67,105,35],[42,15,174,76,12,162,143,154,248,123,24,120,169,134,66,237,207,196,9,236,70,229,95,235,211,93,65,186,88,172,211,44],[84,0,247,188,11,228,130,48,24,102,237,105,5,13,69,71,0,169,47,172,128,73,219,252,255,176,125,229,154,144,65,85],[106,217,196,206,47,183,149,8,193,245,58,196,182,16,241,22,109,236,202,190,70,113,186,221,1,187,16,34,85,186,3,33],[58,73,25,49,183,159,68,243,96,202,63,51,252,17,225,164,104,47,54,146,196,235,91,143,21,25,242,185,63,22,12,3],[114,231,228,222,22,170,137,165,42,63,38,76,247,189,66,181,12,186,45,169,131,137,44,27,99,86,90,139,30,37,46,77],[168,218,214,128,9,247,255,188,108,121,229,194,139,1,87,196,207,44,9,47,66,192,71,155,180,85,244,116,147,254,6,115]]},"migration_priv":{"x0tilde":[207,115,239,173,195,162,112,121,104,28,199,151,198,49,169,249,9,248,29,107,6,135,163,31,15,63,190,245,229,10,120,8],"x":[[249,135,110,112,152,70,199,141,205,19,194,69,16,235,180,27,198,192,116,116,42,41,168,18,246,173,130,131,25,221,50,2],[91,124,133,218,120,156,197,200,66,70,76,1,251,74,68,237,185,173,186,207,49,52,131,12,204,97,175,108,116,170,93,12],[132,42,166,252,154,232,54,51,125,139,247,48,76,89,167,3,251,153,79,221,111,141,95,8,0,248,66,68,147,49,34,2],[59,46,148,147,13,42,182,88,206,133,244,37,6,204,65,253,71,125,77,136,158,141,159,253,73,143,161,180,98,246,235,7],[132,138,119,252,197,121,109,62,123,108,2,95,112,53,34,140,127,237,249,5,17,162,120,141,219,61,162,205,254,183,213,10]]},"migration_pub":{"X":[[134,83,21,37,32,28,253,181,234,92,249,80,232,84,113,240,206,3,74,139,246,58,198,175,189,73,37,143,64,6,116,72],[188,189,194,54,166,71,42,111,113,151,93,157,67,225,55,71,210,162,142,47,193,45,98,132,44,59,76,140,121,12,142,104],[50,45,253,99,174,195,62,213,234,4,92,173,117,227,144,129,112,247,202,125,13,5,208,108,32,167,247,228,23,164,121,103],[184,155,106,183,237,222,41,176,114,254,248,86,245,23,177,212,236,194,248,140,90,70,208,146,154,222,93,25,25,221,18,98],[36,236,24,27,25,160,171,38,218,227,157,64,240,212,50,94,43,234,215,65,242,218,181,164,124,34,246,176,217,205,171,115]]},"migrationkey_priv":{"x0tilde":[242,23,129,100,160,176,243,50,236,20,207,201,79,162,130,242,137,118,204,90,108,158,51,92,173,44,254,249,17,44,125,5],"x":[[21,11,237,41,215,29,99,56,116,232,91,126,183,213,236,20,118,74,252,138,1,162,199,84,50,44,229,190,2,155,82,14],[181,9,174,87,181,204,249,1,230,76,92,0,144,74,94,104,221,168,63,35,222,184,174,124,183,159,65,112,10,181,209,0],[191,171,141,160,71,98,104,7,121,242,122,175,107,202,73,221,54,34,108,108,195,195,230,105,17,53,216,189,167,83,66,15]]},"migrationkey_pub":{"X":[[32,159,58,32,53,86,226,212,104,183,151,116,226,29,157,85,45,11,48,124,22,15,253,125,253,156,94,182,55,124,103,107],[38,13,193,218,122,132,22,143,231,141,143,170,128,12,18,88,119,184,188,113,112,206,99,185,161,74,119,231,182,186,255,86],[88,126,34,210,226,164,231,252,28,101,227,183,36,146,45,28,215,220,237,40,95,167,173,18,214,165,78,124,0,241,73,61]]},"reachability_priv":{"x0tilde":[135,181,110,185,128,21,245,159,50,181,245,221,54,139,22,230,234,107,145,240,249,65,3,162,168,88,72,155,68,41,189,12],"x":[[236,239,205,57,33,61,255,2,11,252,165,233,235,127,118,137,197,169,122,219,222,52,53,58,235,109,233,2,176,211,225,10],[236,66,232,206,38,247,33,43,199,172,152,103,160,101,96,209,186,141,113,233,2,153,59,227,197,72,119,68,110,149,191,9],[48,160,13,205,229,70,94,58,201,162,121,141,245,215,25,115,209,17,65,92,116,26,212,234,212,67,19,70,10,181,88,3]]},"reachability_pub":{"X":[[142,186,35,166,137,25,117,68,89,72,90,164,8,139,64,228,135,188,237,143,96,164,32,255,248,79,142,45,29,93,18,111],[248,252,32,195,224,53,127,36,68,119,20,212,224,81,122,178,215,65,160,148,189,153,33,224,62,215,112,112,128,69,155,16],[70,177,142,234,125,233,139,192,186,238,121,234,64,72,22,163,29,4,80,175,106,231,118,144,238,186,23,48,148,100,156,28]]},"invitation_priv":{"x0tilde":[120,158,240,38,64,79,194,163,54,135,221,120,255,45,168,236,185,40,180,219,152,240,13,44,0,242,84,114,122,5,202,2],"x":[[38,203,24,171,228,254,88,167,31,45,156,60,84,79,74,242,61,211,141,60,215,113,37,118,107,135,107,155,92,85,120,6],[15,71,28,1,115,32,80,223,171,121,219,210,118,222,81,177,232,174,96,34,147,15,8,204,192,247,169,177,169,184,66,12],[114,91,88,58,186,137,204,203,86,78,13,224,131,98,40,153,148,163,85,198,235,166,102,32,102,6,231,90,124,171,137,5],[58,215,51,204,39,242,37,178,209,169,221,137,254,220,247,40,216,252,89,27,241,211,47,153,110,173,217,212,46,51,229,0],[128,145,124,194,206,228,166,235,18,45,152,46,104,150,241,87,64,148,41,206,148,227,40,88,228,38,62,108,1,167,199,13]]},"invitation_pub":{"X":[[136,88,187,230,247,242,53,114,190,51,116,174,35,14,254,39,149,131,246,215,68,83,48,111,162,45,142,104,117,54,5,38],[116,105,240,170,110,8,76,173,70,92,132,253,146,225,227,169,198,132,137,28,234,113,168,196,226,168,241,148,187,58,220,98],[76,151,137,102,200,14,12,175,143,249,31,64,29,52,39,72,81,53,89,147,228,233,160,11,124,141,11,130,96,161,124,38],[0,195,180,103,193,170,6,112,225,249,42,190,74,169,224,0,247,87,100,158,228,247,45,137,189,158,44,220,192,118,206,94],[154,56,182,19,45,99,32,115,2,151,249,201,188,194,87,56,184,160,247,31,164,69,228,30,179,76,48,198,136,79,146,17]]},"bridgedb_pub":[83,135,201,149,116,61,213,153,225,79,182,248,93,101,224,98,33,226,62,202,72,25,57,69,204,166,55,215,232,35,71,137],"bridge_table":{"counter":0,"keys":{},"buckets":{},"encbuckets":{},"reachable":{},"spares":[],"unallocated_bridges":[],"recycleable_keys":[],"blocked_keys":[],"open_inv_keys":[],"date_last_enc":0},"trustup_migration_table":{"table":{},"migration_type":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"blockage_migration_table":{"table":{},"migration_type":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"openinv_filter":{"seen_table":[]},"id_filter":{"seen_table":[]},"inv_id_filter":{"seen_table":[]},"trust_promotion_filter":{"seen_table":[]}},"extra_bridges":[]}
 No newline at end of file
{"db":{"keypair":[91,124,61,5,175,225,67,136,164,210,189,80,53,238,229,119,34,183,123,220,251,237,37,220,16,19,215,33,102,43,122,91],"pubkey":[90,31,105,120,139,57,246,66,23,93,183,235,154,150,146,9,143,192,163,171,15,157,134,5,92,132,249,35,137,166,97,168],"openinv_buckets":[],"distributed_buckets":[],"current_k":0,"daily_bridges_distributed":0},"ba":{"lox_priv":{"x0tilde":[33,204,128,107,184,48,153,32,202,169,82,115,113,223,132,217,30,164,48,19,92,32,83,39,76,150,237,171,129,88,71,6],"x":[[146,244,82,5,7,138,171,201,79,119,122,9,202,240,168,10,100,124,99,79,86,47,187,200,74,151,27,200,26,143,57,1],[49,129,77,139,190,237,149,112,142,121,251,186,49,106,38,90,247,196,173,100,65,62,57,119,63,45,222,80,180,194,140,6],[121,44,212,93,48,47,149,72,115,21,177,31,5,64,55,163,26,90,230,126,186,249,113,141,92,61,69,69,62,134,32,0],[69,217,200,247,47,25,197,208,129,66,82,88,69,232,155,250,196,116,188,157,117,160,208,8,111,28,94,122,83,101,73,11],[31,54,165,105,93,187,200,58,143,79,238,203,93,80,47,127,48,170,133,98,101,61,201,55,45,94,62,228,161,5,41,12],[163,25,241,245,91,179,138,127,93,225,94,210,0,41,6,194,157,33,56,101,92,181,221,165,116,183,213,125,46,234,239,7],[114,209,31,3,207,1,200,131,151,108,41,253,121,213,167,247,125,50,166,96,68,55,181,88,200,107,22,205,121,127,95,5]]},"lox_pub":{"X":[[124,218,152,173,28,183,104,99,251,202,11,79,224,138,240,137,179,22,45,195,84,171,56,168,255,145,163,194,229,242,145,7],[120,80,108,250,109,127,197,1,61,121,195,210,234,105,135,183,142,209,186,233,135,250,58,115,4,88,138,196,215,52,118,2],[52,250,122,73,171,71,161,97,28,179,86,222,248,74,96,106,245,250,195,109,118,214,82,48,52,191,71,63,163,30,78,117],[214,238,99,86,3,108,11,88,178,104,86,95,141,55,197,251,44,235,109,101,214,64,162,107,246,206,116,235,243,187,192,2],[6,168,156,53,74,192,77,233,42,57,202,94,80,196,141,130,94,18,40,167,250,190,26,204,105,244,27,13,142,248,251,78],[104,19,1,107,107,216,98,187,179,234,174,162,57,51,92,116,86,179,246,147,159,0,228,179,244,203,190,107,25,57,16,31],[56,197,205,250,155,89,251,128,188,111,224,6,121,127,88,138,53,2,210,20,192,248,188,165,140,142,243,50,18,7,218,49]]},"migration_priv":{"x0tilde":[71,5,234,88,34,1,74,140,81,109,59,184,165,8,109,23,57,184,200,13,175,171,44,250,139,4,255,59,132,148,175,11],"x":[[156,187,54,244,32,25,160,39,213,53,240,135,172,231,253,121,225,13,153,72,16,129,44,182,168,120,173,1,86,29,4,3],[143,153,27,94,77,205,177,74,249,12,227,194,38,65,201,27,157,175,236,211,64,118,94,37,56,51,30,70,151,65,234,6],[62,229,251,116,133,171,219,187,238,107,205,18,207,226,135,190,11,164,46,221,132,138,214,154,230,10,182,175,249,108,189,5],[191,187,143,220,195,3,217,172,116,31,117,237,43,139,171,200,229,4,243,0,83,221,63,32,159,49,113,47,72,61,49,10],[74,148,204,186,156,27,29,199,40,114,176,228,76,248,251,231,13,199,142,243,125,167,45,188,213,67,107,55,146,13,155,7]]},"migration_pub":{"X":[[86,238,57,220,125,74,213,122,249,74,240,246,49,71,234,84,244,219,42,134,26,168,195,100,11,50,31,140,26,104,233,31],[152,157,147,248,195,149,239,215,132,69,153,7,84,254,129,56,231,9,55,54,164,243,107,226,187,246,217,202,135,198,133,46],[136,126,24,217,86,224,67,240,48,108,14,187,236,215,101,193,56,77,133,167,50,36,177,176,173,81,201,26,11,225,93,72],[228,2,114,146,67,63,17,233,117,76,142,62,86,238,74,12,127,17,154,138,147,187,88,214,241,37,176,205,101,156,126,18],[40,7,232,29,129,185,166,23,225,149,144,0,115,48,247,161,53,88,238,74,110,201,94,106,196,240,68,173,89,53,212,34]]},"migrationkey_priv":{"x0tilde":[229,43,224,58,88,231,241,170,77,228,171,4,160,105,81,38,8,8,188,61,2,208,199,111,178,210,77,100,237,60,10,6],"x":[[199,108,227,47,106,21,26,192,135,78,221,191,91,157,42,213,103,52,182,156,145,130,20,178,19,1,90,24,17,170,136,4],[212,1,60,92,134,47,111,13,175,205,105,124,39,105,41,6,233,168,74,209,113,9,149,202,253,164,60,203,95,124,89,11],[133,218,160,90,31,129,78,197,229,240,154,151,173,30,235,215,40,42,4,126,93,204,188,54,92,180,161,22,30,81,215,14]]},"migrationkey_pub":{"X":[[52,21,211,205,69,101,138,9,84,127,166,217,192,216,253,73,83,176,206,77,63,158,131,91,253,103,95,200,24,205,166,44],[20,27,192,98,233,185,148,200,203,236,97,120,64,113,90,188,42,96,2,6,112,158,109,90,238,132,102,134,192,226,127,103],[92,216,201,34,97,134,244,127,1,251,75,79,118,159,160,75,134,176,106,73,43,114,32,81,122,128,71,130,103,23,174,76]]},"reachability_priv":{"x0tilde":[245,229,72,229,94,6,245,80,13,94,245,134,73,22,124,135,1,72,60,236,28,215,32,46,119,127,55,169,54,44,77,13],"x":[[198,127,197,48,4,123,69,16,226,13,67,178,138,184,239,237,115,186,230,205,107,39,221,95,228,55,39,63,126,100,194,1],[33,162,211,161,201,202,92,172,193,240,81,38,245,81,88,219,142,205,86,49,96,98,183,96,91,178,234,16,145,25,212,13],[184,146,245,233,48,185,160,215,127,187,96,50,21,83,15,81,127,147,213,226,114,222,182,56,178,219,56,135,52,77,57,6]]},"reachability_pub":{"X":[[48,237,176,205,118,81,171,117,177,110,126,155,90,82,164,118,93,143,226,41,137,21,82,102,15,46,145,91,85,180,84,50],[48,163,255,138,104,74,37,163,53,119,143,64,22,169,151,154,11,153,148,122,115,193,158,85,13,53,238,192,138,174,6,74],[118,133,240,154,189,239,241,8,10,68,161,138,17,137,112,101,87,28,102,165,41,193,97,39,170,45,186,212,10,69,162,122]]},"invitation_priv":{"x0tilde":[54,35,147,185,142,68,120,25,15,149,177,70,250,131,45,208,0,14,111,57,121,178,252,41,255,68,70,158,36,12,203,12],"x":[[213,250,8,149,215,235,30,54,16,202,211,18,163,159,15,147,126,148,169,25,47,139,134,92,127,81,246,83,87,171,92,13],[1,17,55,151,208,135,248,66,91,31,152,10,149,84,111,91,38,36,78,71,80,233,159,44,245,219,210,111,45,252,179,8],[26,21,146,188,54,110,223,9,23,231,183,226,75,249,187,94,214,156,93,113,208,238,84,85,136,21,136,220,180,140,99,0],[218,124,215,204,107,238,168,71,96,145,47,106,227,10,98,27,111,244,217,55,173,79,230,34,176,75,162,93,20,166,73,12],[218,8,206,126,177,160,154,119,218,251,96,164,218,129,95,164,202,183,85,102,23,58,116,229,186,227,88,126,25,145,40,8]]},"invitation_pub":{"X":[[50,176,7,185,50,182,132,117,145,66,250,206,120,49,49,36,173,147,105,250,19,85,132,196,138,116,210,246,241,99,239,77],[90,168,240,38,90,127,246,42,20,222,166,2,109,238,100,143,113,145,118,13,52,181,222,128,145,28,133,224,114,136,192,46],[32,103,229,0,180,158,115,125,200,22,105,103,81,224,105,107,154,242,247,185,156,54,2,146,224,103,182,47,211,221,201,40],[106,250,64,195,31,141,214,180,45,170,51,97,214,220,244,238,178,233,250,154,214,52,254,114,216,203,62,218,144,137,176,61],[116,147,127,238,76,173,41,107,200,219,153,230,85,160,0,194,157,24,173,199,88,13,92,132,19,249,174,137,226,184,42,83]]},"bridgedb_pub":[90,31,105,120,139,57,246,66,23,93,183,235,154,150,146,9,143,192,163,171,15,157,134,5,92,132,249,35,137,166,97,168],"bridge_table":{"counter":0,"keys":{},"buckets":{},"encbuckets":{},"reachable":{},"spares":[],"unallocated_bridges":[],"recycleable_keys":[],"blocked_keys":[],"open_inv_keys":[],"date_last_enc":0},"trustup_migration_table":{"table":{},"migration_type":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"blockage_migration_table":{"table":{},"migration_type":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"bridgedb_pub_filter":{"seen_table":[]},"id_filter":{"seen_table":[]},"inv_id_filter":{"seen_table":[]},"trust_promotion_filter":{"seen_table":[]},"old_keys":{"lox_keys":[],"bridgedb_key":[],"invitation_keys":[]},"old_filters":{"lox_filter":[],"openinv_filter":[],"invitation_filter":[]}},"extra_bridges":[]}
 No newline at end of file
+34 −5
Changes for crates/lox-library/src/proto/open_invite.rs: 34 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -151,18 +151,47 @@ impl BridgeAuth {
    /// Receive an open invitation issued by the BridgeDb and if it is
    /// valid and fresh, issue a Lox credential at trust level 0.
    pub fn handle_open_invite(&mut self, req: Request) -> Result<Response, ProofError> {
        // Check the signature on the open_invite.  We manually match
        // here because we're changing the Err type from SignatureError

        // Check the signature on the open_invite, first with the old key, then with the new key.
        // We manually match here because we're changing the Err type from SignatureError
        // to ProofError
        let (invite_id, bucket_id) = match BridgeDb::verify(req.invite, self.bridgedb_pub) {
        let mut old_token: Option<((Scalar, u32), usize)> = Default::default();
        let invite_id: Scalar;
        let bucket_id: u32;
        // If there are old openinv keys, check them first
        for (i, old_openinv_key) in self.old_keys.bridgedb_key.iter().enumerate() {
            old_token = match BridgeDb::verify(req.invite, *old_openinv_key) {
                Ok(res) => Some((res, i)),
                Err(_) => None,
            };
        }

        // Check if verifying with the old key succeeded, if it did, check if it has been seen
        if old_token.is_some() {
            // Only proceed if the invite_id is fresh
            (invite_id, bucket_id) = old_token.unwrap().0;
            if self
                .old_filters
                .openinv_filter
                .get_mut(old_token.unwrap().1)
                .unwrap()
                .filter(&invite_id)
                == SeenType::Seen
            {
                return Err(ProofError::VerificationFailure);
            }
        // If it didn't, try verifying with the new key
        } else {
            (invite_id, bucket_id) = match BridgeDb::verify(req.invite, self.bridgedb_pub) {
                Ok(res) => res,
                // Also verify that the request doesn't match with an old openinv_key
                Err(_) => return Err(ProofError::VerificationFailure),
            };

            // Only proceed if the invite_id is fresh
        if self.openinv_filter.filter(&invite_id) == SeenType::Seen {
            if self.bridgedb_pub_filter.filter(&invite_id) == SeenType::Seen {
                return Err(ProofError::VerificationFailure);
            }
        }

        // And also check that the bucket id is valid
        if !self.bridge_table.buckets.contains_key(&bucket_id) {
Loading
Loading