sync15/client/
collection_keys.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use crate::error::Result;
6use crate::record_types::CryptoKeysRecord;
7use crate::{EncryptedPayload, KeyBundle, ServerTimestamp};
8use std::collections::HashMap;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct CollectionKeys {
12    pub timestamp: ServerTimestamp,
13    pub default: KeyBundle,
14    pub collections: HashMap<String, KeyBundle>,
15}
16
17impl CollectionKeys {
18    pub fn new_random() -> Result<CollectionKeys> {
19        let default = KeyBundle::new_random()?;
20        Ok(CollectionKeys {
21            timestamp: ServerTimestamp(0),
22            default,
23            collections: HashMap::new(),
24        })
25    }
26
27    pub fn from_encrypted_payload(
28        record: EncryptedPayload,
29        timestamp: ServerTimestamp,
30        root_key: &KeyBundle,
31    ) -> Result<CollectionKeys> {
32        let keys: CryptoKeysRecord = record.decrypt_into(root_key)?;
33        Ok(CollectionKeys {
34            timestamp,
35            default: KeyBundle::from_base64(&keys.default[0], &keys.default[1])?,
36            collections: keys
37                .collections
38                .into_iter()
39                .map(|kv| Ok((kv.0, KeyBundle::from_base64(&kv.1[0], &kv.1[1])?)))
40                .collect::<Result<HashMap<String, KeyBundle>>>()?,
41        })
42    }
43
44    pub fn to_encrypted_payload(&self, root_key: &KeyBundle) -> Result<EncryptedPayload> {
45        let record = CryptoKeysRecord {
46            id: "keys".into(),
47            collection: "crypto".into(),
48            default: self.default.to_b64_array(),
49            collections: self
50                .collections
51                .iter()
52                .map(|kv| (kv.0.clone(), kv.1.to_b64_array()))
53                .collect(),
54        };
55        EncryptedPayload::from_cleartext_payload(root_key, &record)
56    }
57
58    pub fn key_for_collection<'a>(&'a self, collection: &str) -> &'a KeyBundle {
59        self.collections.get(collection).unwrap_or(&self.default)
60    }
61}