core_crypto_keystore/
lib.rs

1#![doc = include_str!("../README.md")]
2#![doc = include_str!("../../docs/KEYSTORE_IMPLEMENTATION.md")]
3
4mod error;
5pub use error::*;
6
7pub mod connection;
8pub use connection::{Connection, ConnectionType, DatabaseKey};
9pub mod entities;
10pub mod transaction;
11
12pub(crate) mod mls;
13pub use self::mls::CryptoKeystoreMls;
14pub use self::mls::{deser, ser};
15
16cfg_if::cfg_if! {
17    if #[cfg(feature = "proteus-keystore")] {
18        pub(crate) mod proteus;
19        pub use self::proteus::CryptoKeystoreProteus;
20    }
21}
22
23#[cfg(not(target_family = "wasm"))]
24use sha2::{Digest, Sha256};
25
26#[cfg(feature = "dummy-entity")]
27pub mod dummy_entity {
28    use crate::{
29        CryptoKeystoreResult, MissingKeyErrorKind,
30        entities::{Entity, EntityBase, EntityFindParams, StringEntityId},
31    };
32
33    #[derive(Debug, Eq, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
34    pub struct DummyStoreValue;
35    #[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
36    #[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
37    impl EntityBase for DummyStoreValue {
38        type ConnectionType = crate::connection::KeystoreDatabaseConnection;
39        type AutoGeneratedFields = ();
40        const COLLECTION_NAME: &'static str = "";
41
42        fn to_missing_key_err_kind() -> MissingKeyErrorKind {
43            MissingKeyErrorKind::PersistedMlsGroup
44        }
45
46        fn to_transaction_entity(self) -> crate::transaction::dynamic_dispatch::Entity {
47            unimplemented!("Not implemented")
48        }
49    }
50
51    #[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
52    #[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
53    impl Entity for DummyStoreValue {
54        fn id_raw(&self) -> &[u8] {
55            b""
56        }
57
58        async fn find_all(
59            _conn: &mut Self::ConnectionType,
60            _params: EntityFindParams,
61        ) -> CryptoKeystoreResult<Vec<Self>> {
62            Ok(vec![])
63        }
64        async fn find_one(
65            _conn: &mut Self::ConnectionType,
66            _id: &StringEntityId,
67        ) -> CryptoKeystoreResult<Option<Self>> {
68            Ok(Some(DummyStoreValue))
69        }
70        async fn find_many(conn: &mut Self::ConnectionType, ids: &[StringEntityId]) -> CryptoKeystoreResult<Vec<Self>> {
71            // Default, inefficient & naive method
72            let mut ret = Vec::with_capacity(ids.len());
73            for id in ids {
74                if let Some(entity) = Self::find_one(conn, id).await? {
75                    ret.push(entity);
76                }
77            }
78
79            Ok(ret)
80        }
81        async fn count(_conn: &mut Self::ConnectionType) -> CryptoKeystoreResult<usize> {
82            Ok(0)
83        }
84
85        #[cfg(target_family = "wasm")]
86        fn encrypt(&mut self, _cipher: &aes_gcm::Aes256Gcm) -> CryptoKeystoreResult<()> {
87            Ok(())
88        }
89        #[cfg(target_family = "wasm")]
90        fn decrypt(&mut self, _cipher: &aes_gcm::Aes256Gcm) -> CryptoKeystoreResult<()> {
91            Ok(())
92        }
93    }
94
95    #[derive(Debug, Clone, PartialEq, Eq)]
96    pub struct DummyValue(Vec<u8>);
97
98    impl From<&str> for DummyValue {
99        fn from(id: &str) -> Self {
100            DummyValue(format!("dummy value {id}").into_bytes())
101        }
102    }
103}
104
105/// Used to calculate ID hashes for some MlsEntities' SQLite tables (not used on wasm).
106/// We only use sha256 on platforms where we use SQLite.
107/// On wasm, we use IndexedDB, a key-value store, via the idb crate.
108#[cfg(not(target_family = "wasm"))]
109pub(crate) fn sha256(data: &[u8]) -> String {
110    let mut hasher = Sha256::new();
111    hasher.update(data);
112    format!("{:x}", hasher.finalize())
113}