From c8688ce307400d4e26b6b7579d033cdc4345c2b8 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 24 Nov 2023 18:17:40 +0000 Subject: [PATCH] Factor out serialization functions to a new module --- .../src/crypto_store/indexeddb_serializer.rs | 164 +++++++++++ .../src/crypto_store/mod.rs | 258 +++++------------- 2 files changed, 236 insertions(+), 186 deletions(-) create mode 100644 crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs new file mode 100644 index 00000000000..9d21d622921 --- /dev/null +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs @@ -0,0 +1,164 @@ +// Copyright 2023 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::sync::Arc; + +use gloo_utils::format::JsValueSerdeExt; +use matrix_sdk_crypto::CryptoStoreError; +use matrix_sdk_store_encryption::StoreCipher; +use serde::{de::DeserializeOwned, Serialize}; +use wasm_bindgen::JsValue; +use web_sys::IdbKeyRange; + +use crate::{safe_encode::SafeEncode, IndexeddbCryptoStoreError}; + +type Result = std::result::Result; + +/// Handles the functionality of serializing and encrypting data for the +/// indexeddb store. +pub struct IndexeddbSerializer { + store_cipher: Option>, +} + +impl IndexeddbSerializer { + pub fn new(store_cipher: Option>) -> Self { + Self { store_cipher } + } + + /// Hash the given key securely for the given tablename, using the store + /// cipher. + /// + /// First calls [`SafeEncode::as_encoded_string`] + /// on the `key` to encode it into a formatted string. + /// + /// Then, if a cipher is configured, hashes the formatted key and returns + /// the hash encoded as unpadded base64. + /// + /// If no cipher is configured, just returns the formatted key. + /// + /// This is faster than [`serialize_value`] and reliably gives the same + /// output for the same input, making it suitable for index keys. + pub fn encode_key(&self, table_name: &str, key: T) -> JsValue + where + T: SafeEncode, + { + self.encode_key_as_string(table_name, key).into() + } + + /// Hash the given key securely for the given tablename, using the store + /// cipher. + /// + /// The same as [`encode_key`], but stops short of converting the resulting + /// base64 string into a JsValue + pub fn encode_key_as_string(&self, table_name: &str, key: T) -> String + where + T: SafeEncode, + { + match &self.store_cipher { + Some(cipher) => key.as_secure_string(table_name, cipher), + None => key.as_encoded_string(), + } + } + + pub fn encode_to_range( + &self, + table_name: &str, + key: T, + ) -> Result + where + T: SafeEncode, + { + match &self.store_cipher { + Some(cipher) => key.encode_to_range_secure(table_name, cipher), + None => key.encode_to_range(), + } + .map_err(|e| IndexeddbCryptoStoreError::DomException { + code: 0, + name: "IdbKeyRangeMakeError".to_owned(), + message: e, + }) + } + + /// Encode the value for storage as a value in indexeddb. + /// + /// First, serialise the given value as JSON. + /// + /// Then, if a store cipher is enabled, encrypt the JSON string using the + /// configured store cipher, giving a byte array. Then, wrap the byte + /// array as a `JsValue`. + /// + /// If no cipher is enabled, deserialises the JSON string again giving a JS + /// object. + pub fn serialize_value(&self, value: &impl Serialize) -> Result { + if let Some(cipher) = &self.store_cipher { + let value = cipher.encrypt_value(value).map_err(CryptoStoreError::backend)?; + + // Turn the Vec into a Javascript-side `Array`. + // XXX Isn't there a way to do this that *doesn't* involve going via a JSON + // string? + Ok(JsValue::from_serde(&value)?) + } else { + // Turn the rust-side struct into a JS-side `Object`. + Ok(JsValue::from_serde(&value)?) + } + } + + /// Encode the value for storage as a value in indexeddb. + /// + /// This is the same algorithm as [`serialize_value`], but stops short of + /// encoding the resultant byte vector in a JsValue. + /// + /// Returns a byte vector which is either the JSON serialisation of the + /// value, or an encrypted version thereof. + pub fn serialize_value_as_bytes( + &self, + value: &impl Serialize, + ) -> Result, CryptoStoreError> { + match &self.store_cipher { + Some(cipher) => cipher.encrypt_value(value).map_err(CryptoStoreError::backend), + None => serde_json::to_vec(value).map_err(CryptoStoreError::backend), + } + } + + /// Decode a value that was previously encoded with [`serialize_value`] + pub fn deserialize_value( + &self, + value: JsValue, + ) -> Result { + if let Some(cipher) = &self.store_cipher { + // `value` is a JS-side array containing the byte values. Turn it into a + // rust-side Vec. + // XXX: Isn't there a way to do this that *doesn't* involve going via a JSON + // string? + let value: Vec = value.into_serde()?; + + cipher.decrypt_value(&value).map_err(CryptoStoreError::backend) + } else { + Ok(value.into_serde()?) + } + } + + /// Decode a value that was previously encoded with + /// [`serialize_value_as_bytes`] + pub fn deserialize_value_from_bytes( + &self, + value: &[u8], + ) -> Result { + if let Some(cipher) = &self.store_cipher { + cipher.decrypt_value(value).map_err(CryptoStoreError::backend) + } else { + serde_json::from_slice(value).map_err(CryptoStoreError::backend) + } + } +} diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs index 275fdd20150..935846bd7e7 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs @@ -38,13 +38,14 @@ use ruma::{ events::secret::request::SecretName, DeviceId, MilliSecondsSinceUnixEpoch, OwnedDeviceId, RoomId, TransactionId, UserId, }; -use serde::{de::DeserializeOwned, Serialize}; use tokio::sync::Mutex; use wasm_bindgen::JsValue; -use web_sys::IdbKeyRange; -use crate::{crypto_store::migrations::open_and_upgrade_db, safe_encode::SafeEncode}; +use crate::crypto_store::{ + indexeddb_serializer::IndexeddbSerializer, migrations::open_and_upgrade_db, +}; +mod indexeddb_serializer; mod migrations; mod keys { @@ -98,8 +99,7 @@ pub struct IndexeddbCryptoStore { name: String, pub(crate) inner: IdbDatabase, - store_cipher: Option>, - + serializer: IndexeddbSerializer, session_cache: SessionStore, save_changes_lock: Arc>, } @@ -163,6 +163,7 @@ impl IndexeddbCryptoStore { ) -> Result { let name = format!("{prefix:0}::matrix-sdk-crypto"); + let serializer = IndexeddbSerializer::new(store_cipher); let db = open_and_upgrade_db(&name).await?; let session_cache = SessionStore::new(); @@ -170,7 +171,7 @@ impl IndexeddbCryptoStore { name, session_cache, inner: db, - store_cipher, + serializer, static_account: RwLock::new(None), save_changes_lock: Default::default(), }) @@ -181,60 +182,6 @@ impl IndexeddbCryptoStore { IndexeddbCryptoStore::open_with_store_cipher("crypto", None).await } - /// Hash the given key securely for the given tablename, using the store - /// cipher. - /// - /// First calls [`SafeEncode::as_encoded_string`] - /// on the `key` to encode it into a formatted string. - /// - /// Then, if a cipher is configured, hashes the formatted key and returns - /// the hash encoded as unpadded base64. - /// - /// If no cipher is configured, just returns the formatted key. - /// - /// This is faster than [`serialize_value`] and reliably gives the same - /// output for the same input, making it suitable for index keys. - fn encode_key(&self, table_name: &str, key: T) -> JsValue - where - T: SafeEncode, - { - self.encode_key_as_string(table_name, key).into() - } - - /// Hash the given key securely for the given tablename, using the store - /// cipher. - /// - /// The same as [`encode_key`], but stops short of converting the resulting - /// base64 string into a JsValue - fn encode_key_as_string(&self, table_name: &str, key: T) -> String - where - T: SafeEncode, - { - match &self.store_cipher { - Some(cipher) => key.as_secure_string(table_name, cipher), - None => key.as_encoded_string(), - } - } - - fn encode_to_range( - &self, - table_name: &str, - key: T, - ) -> Result - where - T: SafeEncode, - { - match &self.store_cipher { - Some(cipher) => key.encode_to_range_secure(table_name, cipher), - None => key.encode_to_range(), - } - .map_err(|e| IndexeddbCryptoStoreError::DomException { - code: 0, - name: "IdbKeyRangeMakeError".to_owned(), - message: e, - }) - } - /// Open a new `IndexeddbCryptoStore` with given name and passphrase pub async fn open_with_passphrase(prefix: &str, passphrase: &str) -> Result { let name = format!("{prefix:0}::matrix-sdk-crypto-meta"); @@ -300,82 +247,21 @@ impl IndexeddbCryptoStore { IndexeddbCryptoStore::open_with_store_cipher(name, None).await } - /// Encode the value for storage as a value in indexeddb. - /// - /// First, serialise the given value as JSON. - /// - /// Then, if a store cipher is enabled, encrypt the JSON string using the - /// configured store cipher, giving a byte array. Then, wrap the byte - /// array as a `JsValue`. - /// - /// If no cipher is enabled, deserialises the JSON string again giving a JS - /// object. - fn serialize_value(&self, value: &impl Serialize) -> Result { - if let Some(cipher) = &self.store_cipher { - let value = cipher.encrypt_value(value).map_err(CryptoStoreError::backend)?; - - Ok(JsValue::from_serde(&value)?) - } else { - Ok(JsValue::from_serde(&value)?) - } - } - - /// Encode the value for storage as a value in indexeddb. - /// - /// This is the same algorithm as [`serialize_value`], but stops short of - /// encoding the resultant byte vector in a JsValue. - /// - /// Returns a byte vector which is either the JSON serialisation of the - /// value, or an encrypted version thereof. - fn serialize_value_as_bytes( - &self, - value: &impl Serialize, - ) -> Result, CryptoStoreError> { - match &self.store_cipher { - Some(cipher) => cipher.encrypt_value(value).map_err(CryptoStoreError::backend), - None => serde_json::to_vec(value).map_err(CryptoStoreError::backend), - } - } - - /// Decode a value that was previously encoded with [`serialize_value`] - fn deserialize_value( - &self, - value: JsValue, - ) -> Result { - if let Some(cipher) = &self.store_cipher { - let value: Vec = value.into_serde()?; - cipher.decrypt_value(&value).map_err(CryptoStoreError::backend) - } else { - Ok(value.into_serde()?) - } - } - - /// Decode a value that was previously encoded with - /// [`serialize_value_as_bytes`] - fn deserialize_value_from_bytes( - &self, - value: &[u8], - ) -> Result { - if let Some(cipher) = &self.store_cipher { - cipher.decrypt_value(value).map_err(CryptoStoreError::backend) - } else { - serde_json::from_slice(value).map_err(CryptoStoreError::backend) - } - } - fn get_static_account(&self) -> Option { self.static_account.read().unwrap().clone() } /// Transform a [`GossipRequest`] into a `JsValue` holding a - /// [`GossipRequestIndexedDbObject`], ready for storing + /// [`GossipRequestIndexedDbObject`], ready for storing. fn serialize_gossip_request(&self, gossip_request: &GossipRequest) -> Result { let obj = GossipRequestIndexedDbObject { // hash the info as a key so that it can be used in index lookups. - info: self.encode_key_as_string(keys::GOSSIP_REQUESTS, gossip_request.info.as_key()), + info: self + .serializer + .encode_key_as_string(keys::GOSSIP_REQUESTS, gossip_request.info.as_key()), // serialize and encrypt the data about the request - request: self.serialize_value_as_bytes(gossip_request)?, + request: self.serializer.serialize_value_as_bytes(gossip_request)?, unsent: !gossip_request.sent_out, }; @@ -384,11 +270,11 @@ impl IndexeddbCryptoStore { } /// Transform a JsValue holding a [`GossipRequestIndexedDbObject`] back into - /// a [`GossipRequest`] + /// a [`GossipRequest`]. fn deserialize_gossip_request(&self, stored_request: JsValue) -> Result { let idb_object: GossipRequestIndexedDbObject = serde_wasm_bindgen::from_value(stored_request)?; - Ok(self.deserialize_value_from_bytes(&idb_object.request)?) + Ok(self.serializer.deserialize_value_from_bytes(&idb_object.request)?) } } @@ -453,7 +339,7 @@ impl_crypto_store! { if let Some(a) = &account_pickle { tx.object_store(keys::CORE)? - .put_key_val(&JsValue::from_str(keys::ACCOUNT), &self.serialize_value(&a)?)?; + .put_key_val(&JsValue::from_str(keys::ACCOUNT), &self.serializer.serialize_value(&a)?)?; } tx.await.into_result()?; @@ -515,27 +401,27 @@ impl_crypto_store! { if let Some(next_batch) = changes.next_batch_token { tx.object_store(keys::CORE)?.put_key_val( &JsValue::from_str(keys::NEXT_BATCH_TOKEN), - &self.serialize_value(&next_batch)? + &self.serializer.serialize_value(&next_batch)? )?; } if let Some(i) = &private_identity_pickle { tx.object_store(keys::CORE)?.put_key_val( &JsValue::from_str(keys::PRIVATE_IDENTITY), - &self.serialize_value(i)?, + &self.serializer.serialize_value(i)?, )?; } if let Some(a) = &decryption_key_pickle { tx.object_store(keys::BACKUP_KEYS)?.put_key_val( &JsValue::from_str(keys::RECOVERY_KEY_V1), - &self.serialize_value(&a)?, + &self.serializer.serialize_value(&a)?, )?; } if let Some(a) = &backup_version { tx.object_store(keys::BACKUP_KEYS)? - .put_key_val(&JsValue::from_str(keys::BACKUP_KEY_V1), &self.serialize_value(&a)?)?; + .put_key_val(&JsValue::from_str(keys::BACKUP_KEY_V1), &self.serializer.serialize_value(&a)?)?; } if !changes.sessions.is_empty() { @@ -546,9 +432,9 @@ impl_crypto_store! { let session_id = session.session_id(); let pickle = session.pickle().await; - let key = self.encode_key(keys::SESSION, (&sender_key, session_id)); + let key = self.serializer.encode_key(keys::SESSION, (&sender_key, session_id)); - sessions.put_key_val(&key, &self.serialize_value(&pickle)?)?; + sessions.put_key_val(&key, &self.serializer.serialize_value(&pickle)?)?; } } @@ -558,10 +444,10 @@ impl_crypto_store! { for session in changes.inbound_group_sessions { let room_id = session.room_id(); let session_id = session.session_id(); - let key = self.encode_key(keys::INBOUND_GROUP_SESSIONS, (room_id, session_id)); + let key = self.serializer.encode_key(keys::INBOUND_GROUP_SESSIONS, (room_id, session_id)); let pickle = session.pickle().await; - sessions.put_key_val(&key, &self.serialize_value(&pickle)?)?; + sessions.put_key_val(&key, &self.serializer.serialize_value(&pickle)?)?; } } @@ -572,8 +458,8 @@ impl_crypto_store! { let room_id = session.room_id(); let pickle = session.pickle().await; sessions.put_key_val( - &self.encode_key(keys::OUTBOUND_GROUP_SESSIONS, room_id), - &self.serialize_value(&pickle)?, + &self.serializer.encode_key(keys::OUTBOUND_GROUP_SESSIONS, room_id), + &self.serializer.serialize_value(&pickle)?, )?; } } @@ -588,8 +474,8 @@ impl_crypto_store! { if !device_changes.new.is_empty() || !device_changes.changed.is_empty() { let device_store = tx.object_store(keys::DEVICES)?; for device in device_changes.new.iter().chain(&device_changes.changed) { - let key = self.encode_key(keys::DEVICES, (device.user_id(), device.device_id())); - let device = self.serialize_value(&device)?; + let key = self.serializer.encode_key(keys::DEVICES, (device.user_id(), device.device_id())); + let device = self.serializer.serialize_value(&device)?; device_store.put_key_val(&key, &device)?; } @@ -599,7 +485,7 @@ impl_crypto_store! { let device_store = tx.object_store(keys::DEVICES)?; for device in &device_changes.deleted { - let key = self.encode_key(keys::DEVICES, (device.user_id(), device.device_id())); + let key = self.serializer.encode_key(keys::DEVICES, (device.user_id(), device.device_id())); device_store.delete(&key)?; } } @@ -608,8 +494,8 @@ impl_crypto_store! { let identities = tx.object_store(keys::IDENTITIES)?; for identity in identity_changes.changed.iter().chain(&identity_changes.new) { identities.put_key_val( - &self.encode_key(keys::IDENTITIES, identity.user_id()), - &self.serialize_value(&identity)?, + &self.serializer.encode_key(keys::IDENTITIES, identity.user_id()), + &self.serializer.serialize_value(&identity)?, )?; } } @@ -618,7 +504,7 @@ impl_crypto_store! { let hashes = tx.object_store(keys::OLM_HASHES)?; for hash in &olm_hashes { hashes.put_key_val( - &self.encode_key(keys::OLM_HASHES, (&hash.sender_key, &hash.hash)), + &self.serializer.encode_key(keys::OLM_HASHES, (&hash.sender_key, &hash.hash)), &JsValue::TRUE, )?; } @@ -628,7 +514,7 @@ impl_crypto_store! { let gossip_requests = tx.object_store(keys::GOSSIP_REQUESTS)?; for gossip_request in &key_requests { - let key_request_id = self.encode_key(keys::GOSSIP_REQUESTS, gossip_request.request_id.as_str()); + let key_request_id = self.serializer.encode_key(keys::GOSSIP_REQUESTS, gossip_request.request_id.as_str()); let key_request_value = self.serialize_gossip_request(gossip_request)?; gossip_requests.put_key_val_owned( key_request_id, @@ -643,8 +529,8 @@ impl_crypto_store! { for (room_id, data) in withheld_session_info { for (session_id, event) in data { - let key = self.encode_key(keys::DIRECT_WITHHELD_INFO, (session_id, &room_id)); - withhelds.put_key_val(&key, &self.serialize_value(&event)?)?; + let key = self.serializer.encode_key(keys::DIRECT_WITHHELD_INFO, (session_id, &room_id)); + withhelds.put_key_val(&key, &self.serializer.serialize_value(&event)?)?; } } } @@ -653,8 +539,8 @@ impl_crypto_store! { let settings_store = tx.object_store(keys::ROOM_SETTINGS)?; for (room_id, settings) in &room_settings_changes { - let key = self.encode_key(keys::ROOM_SETTINGS, room_id); - let value = self.serialize_value(&settings)?; + let key = self.serializer.encode_key(keys::ROOM_SETTINGS, room_id); + let value = self.serializer.serialize_value(&settings)?; settings_store.put_key_val(&key, &value)?; } } @@ -663,8 +549,8 @@ impl_crypto_store! { let secrets_store = tx.object_store(keys::SECRETS_INBOX)?; for secret in changes.secrets { - let key = self.encode_key(keys::SECRETS_INBOX, (secret.secret_name.as_str(), secret.event.content.request_id.as_str())); - let value = self.serialize_value(&secret)?; + let key = self.serializer.encode_key(keys::SECRETS_INBOX, (secret.secret_name.as_str(), secret.event.content.request_id.as_str())); + let value = self.serializer.serialize_value(&secret)?; secrets_store.put_key_val(&key, &value)?; } @@ -712,14 +598,14 @@ impl_crypto_store! { IdbTransactionMode::Readonly, )? .object_store(keys::OUTBOUND_GROUP_SESSIONS)? - .get(&self.encode_key(keys::OUTBOUND_GROUP_SESSIONS, room_id))? + .get(&self.serializer.encode_key(keys::OUTBOUND_GROUP_SESSIONS, room_id))? .await? { Ok(Some( OutboundGroupSession::from_pickle( account_info.device_id, account_info.identity_keys, - self.deserialize_value(value)?, + self.serializer.deserialize_value(value)?, ) .map_err(CryptoStoreError::from)?, )) @@ -732,7 +618,7 @@ impl_crypto_store! { &self, request_id: &TransactionId, ) -> Result> { - let jskey = self.encode_key(keys::GOSSIP_REQUESTS, request_id.as_str()); + let jskey = self.serializer.encode_key(keys::GOSSIP_REQUESTS, request_id.as_str()); self .inner .transaction_on_one_with_mode(keys::GOSSIP_REQUESTS, IdbTransactionMode::Readonly)? @@ -751,7 +637,7 @@ impl_crypto_store! { .get(&JsValue::from_str(keys::ACCOUNT))? .await? { - let pickle = self.deserialize_value(pickle)?; + let pickle = self.serializer.deserialize_value(pickle)?; let account = Account::from_pickle(pickle).map_err(CryptoStoreError::from)?; @@ -771,7 +657,7 @@ impl_crypto_store! { .get(&JsValue::from_str(keys::NEXT_BATCH_TOKEN))? .await? { - let token = self.deserialize_value(serialized)?; + let token = self.serializer.deserialize_value(serialized)?; Ok(Some(token)) } else { Ok(None) @@ -786,7 +672,7 @@ impl_crypto_store! { .get(&JsValue::from_str(keys::PRIVATE_IDENTITY))? .await? { - let pickle = self.deserialize_value(pickle)?; + let pickle = self.serializer.deserialize_value(pickle)?; Ok(Some( PrivateCrossSigningIdentity::from_pickle(pickle) @@ -802,7 +688,7 @@ impl_crypto_store! { let account_info = self.get_static_account().ok_or(CryptoStoreError::AccountUnset)?; if self.session_cache.get(sender_key).is_none() { - let range = self.encode_to_range(keys::SESSION, sender_key)?; + let range = self.serializer.encode_to_range(keys::SESSION, sender_key)?; let sessions: Vec = self .inner .transaction_on_one_with_mode(keys::SESSION, IdbTransactionMode::Readonly)? @@ -810,7 +696,7 @@ impl_crypto_store! { .get_all_with_key(&range)? .await? .iter() - .filter_map(|f| self.deserialize_value(f).ok().map(|p| { + .filter_map(|f| self.serializer.deserialize_value(f).ok().map(|p| { Session::from_pickle( account_info.user_id.clone(), account_info.device_id.clone(), @@ -831,7 +717,7 @@ impl_crypto_store! { room_id: &RoomId, session_id: &str, ) -> Result> { - let key = self.encode_key(keys::INBOUND_GROUP_SESSIONS, (room_id, session_id)); + let key = self.serializer.encode_key(keys::INBOUND_GROUP_SESSIONS, (room_id, session_id)); if let Some(pickle) = self .inner .transaction_on_one_with_mode( @@ -842,7 +728,7 @@ impl_crypto_store! { .get(&key)? .await? { - let pickle = self.deserialize_value(pickle)?; + let pickle = self.serializer.deserialize_value(pickle)?; Ok(Some(InboundGroupSession::from_pickle(pickle).map_err(CryptoStoreError::from)?)) } else { Ok(None) @@ -860,7 +746,7 @@ impl_crypto_store! { .get_all()? .await? .iter() - .filter_map(|i| self.deserialize_value(i).ok()) + .filter_map(|i| self.serializer.deserialize_value(i).ok()) .filter_map(|p| InboundGroupSession::from_pickle(p).ok()) .collect()) } @@ -925,14 +811,14 @@ impl_crypto_store! { user_id: &UserId, device_id: &DeviceId, ) -> Result> { - let key = self.encode_key(keys::DEVICES, (user_id, device_id)); + let key = self.serializer.encode_key(keys::DEVICES, (user_id, device_id)); Ok(self .inner .transaction_on_one_with_mode(keys::DEVICES, IdbTransactionMode::Readonly)? .object_store(keys::DEVICES)? .get(&key)? .await? - .map(|i| self.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i)) .transpose()?) } @@ -940,7 +826,7 @@ impl_crypto_store! { &self, user_id: &UserId, ) -> Result> { - let range = self.encode_to_range(keys::DEVICES, user_id)?; + let range = self.serializer.encode_to_range(keys::DEVICES, user_id)?; Ok(self .inner .transaction_on_one_with_mode(keys::DEVICES, IdbTransactionMode::Readonly)? @@ -949,7 +835,7 @@ impl_crypto_store! { .await? .iter() .filter_map(|d| { - let d: ReadOnlyDevice = self.deserialize_value(d).ok()?; + let d: ReadOnlyDevice = self.serializer.deserialize_value(d).ok()?; Some((d.device_id().to_owned(), d)) }) .collect::>()) @@ -960,9 +846,9 @@ impl_crypto_store! { .inner .transaction_on_one_with_mode(keys::IDENTITIES, IdbTransactionMode::Readonly)? .object_store(keys::IDENTITIES)? - .get(&self.encode_key(keys::IDENTITIES, user_id))? + .get(&self.serializer.encode_key(keys::IDENTITIES, user_id))? .await? - .map(|i| self.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i)) .transpose()?) } @@ -971,7 +857,7 @@ impl_crypto_store! { .inner .transaction_on_one_with_mode(keys::OLM_HASHES, IdbTransactionMode::Readonly)? .object_store(keys::OLM_HASHES)? - .get(&self.encode_key(keys::OLM_HASHES, (&hash.sender_key, &hash.hash)))? + .get(&self.serializer.encode_key(keys::OLM_HASHES, (&hash.sender_key, &hash.hash)))? .await? .is_some()) } @@ -980,7 +866,7 @@ impl_crypto_store! { &self, secret_name: &SecretName, ) -> Result> { - let range = self.encode_to_range(keys::SECRETS_INBOX, secret_name.as_str())?; + let range = self.serializer.encode_to_range(keys::SECRETS_INBOX, secret_name.as_str())?; self .inner @@ -990,7 +876,7 @@ impl_crypto_store! { .await? .iter() .map(|d| { - let secret = self.deserialize_value(d)?; + let secret = self.serializer.deserialize_value(d)?; Ok(secret) }).collect() } @@ -999,7 +885,7 @@ impl_crypto_store! { &self, secret_name: &SecretName, ) -> Result<()> { - let range = self.encode_to_range(keys::SECRETS_INBOX, secret_name.as_str())?; + let range = self.serializer.encode_to_range(keys::SECRETS_INBOX, secret_name.as_str())?; self .inner @@ -1014,7 +900,7 @@ impl_crypto_store! { &self, key_info: &SecretInfo, ) -> Result> { - let key = self.encode_key(keys::GOSSIP_REQUESTS, key_info.as_key()); + let key = self.serializer.encode_key(keys::GOSSIP_REQUESTS, key_info.as_key()); let val = self .inner @@ -1054,7 +940,7 @@ impl_crypto_store! { } async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> { - let jskey = self.encode_key(keys::GOSSIP_REQUESTS, request_id); + let jskey = self.serializer.encode_key(keys::GOSSIP_REQUESTS, request_id); let tx = self.inner.transaction_on_one_with_mode(keys::GOSSIP_REQUESTS, IdbTransactionMode::Readwrite)?; tx.object_store(keys::GOSSIP_REQUESTS)?.delete_owned(jskey)?; tx.await.into_result().map_err(|e| e.into()) @@ -1070,13 +956,13 @@ impl_crypto_store! { let backup_version = store .get(&JsValue::from_str(keys::BACKUP_KEY_V1))? .await? - .map(|i| self.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i)) .transpose()?; let decryption_key = store .get(&JsValue::from_str(keys::RECOVERY_KEY_V1))? .await? - .map(|i| self.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i)) .transpose()?; BackupKeys { backup_version, decryption_key } @@ -1090,7 +976,7 @@ impl_crypto_store! { room_id: &RoomId, session_id: &str, ) -> Result> { - let key = self.encode_key(keys::DIRECT_WITHHELD_INFO, (session_id, room_id)); + let key = self.serializer.encode_key(keys::DIRECT_WITHHELD_INFO, (session_id, room_id)); if let Some(pickle) = self .inner .transaction_on_one_with_mode( @@ -1101,7 +987,7 @@ impl_crypto_store! { .get(&key)? .await? { - let info = self.deserialize_value(pickle)?; + let info = self.serializer.deserialize_value(pickle)?; Ok(Some(info)) } else { Ok(None) @@ -1109,14 +995,14 @@ impl_crypto_store! { } async fn get_room_settings(&self, room_id: &RoomId) -> Result> { - let key = self.encode_key(keys::ROOM_SETTINGS, room_id); + let key = self.serializer.encode_key(keys::ROOM_SETTINGS, room_id); Ok(self .inner .transaction_on_one_with_mode(keys::ROOM_SETTINGS, IdbTransactionMode::Readonly)? .object_store(keys::ROOM_SETTINGS)? .get(&key)? .await? - .map(|v| self.deserialize_value(v)) + .map(|v| self.serializer.deserialize_value(v)) .transpose()?) } @@ -1127,7 +1013,7 @@ impl_crypto_store! { .object_store(keys::CORE)? .get(&JsValue::from_str(key))? .await? - .map(|v| self.deserialize_value(v)) + .map(|v| self.serializer.deserialize_value(v)) .transpose()?) } @@ -1136,7 +1022,7 @@ impl_crypto_store! { .inner .transaction_on_one_with_mode(keys::CORE, IdbTransactionMode::Readwrite)? .object_store(keys::CORE)? - .put_key_val(&JsValue::from_str(key), &self.serialize_value(&value)?)?; + .put_key_val(&JsValue::from_str(key), &self.serializer.serialize_value(&value)?)?; Ok(()) } @@ -1175,16 +1061,16 @@ impl_crypto_store! { let prev = object_store.get(&key)?.await?; match prev { Some(prev) => { - let lease: Lease = self.deserialize_value(prev)?; + let lease: Lease = self.serializer.deserialize_value(prev)?; if lease.holder == holder || lease.expiration_ts < now_ts { - object_store.put_key_val(&key, &self.serialize_value(&Lease { holder: holder.to_owned(), expiration_ts })?)?; + object_store.put_key_val(&key, &self.serializer.serialize_value(&Lease { holder: holder.to_owned(), expiration_ts })?)?; Ok(true) } else { Ok(false) } } None => { - object_store.put_key_val(&key, &self.serialize_value(&Lease { holder: holder.to_owned(), expiration_ts })?)?; + object_store.put_key_val(&key, &self.serializer.serialize_value(&Lease { holder: holder.to_owned(), expiration_ts })?)?; Ok(true) } }