Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19906.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Updated experimental support for [MSC4388: Secure out-of-band channel for sign in with QR](https://github.com/matrix-org/matrix-spec-proposals/pull/4388).
21 changes: 12 additions & 9 deletions rust/src/msc4388_rendezvous/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub struct Session {
/// treated as an idempotent no-op.
previous_hash: Option<[u8; 32]>,
data: String,
/// Monotonic counter incremented on each successful write.
sequence: u64,
last_modified: SystemTime,
expires: SystemTime,
}
Expand Down Expand Up @@ -88,12 +90,14 @@ impl<'source> IntoPyObject<'source> for PutResponse {
impl Session {
/// Create a new session with the given data and time-to-live.
pub fn new(id: Ulid, data: String, now: SystemTime, ttl: Duration) -> Self {
let hash = Self::compute_hash(&data, now);
let sequence = 0;
let hash = Self::compute_hash(id, sequence, &data);
Self {
id,
hash,
previous_hash: None,
data,
sequence,
expires: now + ttl,
last_modified: now,
}
Expand All @@ -107,7 +111,8 @@ impl Session {
/// Update the session with new data and last modified time.
pub fn update(&mut self, data: String, now: SystemTime) {
self.previous_hash = Some(self.hash);
self.hash = Self::compute_hash(&data, now);
self.sequence += 1;
self.hash = Self::compute_hash(self.id, self.sequence, &data);
self.data = data;
self.last_modified = now;
}
Expand All @@ -126,15 +131,13 @@ impl Session {
URL_SAFE_NO_PAD.encode(previous_hash) == sequence_token
}

/// Compute the hash of the data and timestamp.
fn compute_hash(data: &str, now: SystemTime) -> [u8; 32] {
/// Compute the hash of the rendezvous ID, write counter and data, as
/// recommended by MSC4388 for `sequence_token` values.
fn compute_hash(id: Ulid, sequence: u64, data: &str) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(id.to_bytes());
hasher.update(sequence.to_be_bytes());
hasher.update(data);
let now_millis = now
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
hasher.update(now_millis.to_be_bytes());
hasher.finalize().into()
}

Expand Down
Loading