forked from Keelrleek/SoulStream
spaces: leaving a room says so, so an owner stops publishing a seat nobody sits in
This commit is contained in:
1 parent
d6102101af
commit
06baa5a805
3 files changed
+147
-7
No files matched your search
@@ -255,6 +255,24 @@ pub fn join_proof_valid(
|
||||
crate::verify_sig_in(SIGN_DOMAIN, persona, &join_proof_payload(space_id, owner, room_key), proof)
|
||||
}
|
||||
|
||||
/// What a member signs to give up their seat. Prefixed, so a join proof can
|
||||
/// never be replayed as a leave, and signed by the key that HOLDS the seat —
|
||||
/// holding it is the whole authority to vacate it, and the owner needs no
|
||||
/// second fact to act.
|
||||
pub fn leave_proof_payload(space_id: &[u8; 16], owner: &[u8; 32], worn: &[u8; 32]) -> Vec<u8> {
|
||||
let mut v = Vec::with_capacity(5 + 16 + 32 + 32);
|
||||
v.extend_from_slice(b"leave");
|
||||
v.extend_from_slice(space_id);
|
||||
v.extend_from_slice(owner);
|
||||
v.extend_from_slice(worn);
|
||||
blake3::hash(&v).as_bytes().to_vec()
|
||||
}
|
||||
|
||||
/// True when whoever sits under `worn` really did ask to leave this Space.
|
||||
pub fn leave_proof_valid(space_id: &[u8; 16], owner: &[u8; 32], worn: &[u8; 32], proof: &[u8]) -> bool {
|
||||
crate::verify_sig_in(SIGN_DOMAIN, worn, &leave_proof_payload(space_id, owner, worn), proof)
|
||||
}
|
||||
|
||||
pub fn checkpoint_valid(owner: &[u8; 32], space_id: &[u8; 16], c: &Checkpoint) -> bool {
|
||||
c.schema_version == SCHEMA_VERSION
|
||||
&& &c.space_id == space_id
|
||||
@@ -453,6 +471,27 @@ mod tests {
|
||||
assert!(!join_proof_valid(&[4; 16], &ok, &room, &mallory, &proof), "anyone could claim it");
|
||||
}
|
||||
|
||||
/// A seat is given up by the key that holds it, and a join proof is not a
|
||||
/// leave proof — otherwise the owner's own invitation answer could be
|
||||
/// replayed to unseat the person who sent it.
|
||||
#[test]
|
||||
fn a_leave_proof_comes_from_the_seat_it_gives_up() {
|
||||
let owner = SigningKey::from_bytes(&[1; 32]);
|
||||
let ok = owner.verifying_key().to_bytes();
|
||||
let room_secret = [9u8; 32];
|
||||
let room = member_public(&room_secret);
|
||||
let proof = sign_as_member(&room_secret, &leave_proof_payload(&[4; 16], &ok, &room));
|
||||
assert!(leave_proof_valid(&[4; 16], &ok, &room, &proof));
|
||||
// Not reusable in another Space, and not against another seat.
|
||||
assert!(!leave_proof_valid(&[5; 16], &ok, &room, &proof), "replayed into another Space");
|
||||
assert!(!leave_proof_valid(&[4; 16], &ok, &member_public(&[8; 32]), &proof), "bound to the wrong seat");
|
||||
// A join proof carries a different payload, so it cannot stand in.
|
||||
let bob_persona = SigningKey::from_bytes(&[2; 32]);
|
||||
let bp = bob_persona.verifying_key().to_bytes();
|
||||
let join = sign(&bob_persona, &join_proof_payload(&[4; 16], &ok, &bp));
|
||||
assert!(!leave_proof_valid(&[4; 16], &ok, &bp, &join), "a join proof unseated its own sender");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roster_is_the_authority_and_removal_is_an_epoch() {
|
||||
let owner = SigningKey::from_bytes(&[1; 32]);
|
||||
|
||||
Reference in new issue
Block a user