Skip to main content

object_rainbow_encrypted_store/
lib.rs

1use object_rainbow::{DiffHashes, ToOutput, WithHash};
2use object_rainbow_encrypted::Key;
3use object_rainbow_store::ExternalStore;
4
5#[derive(Clone, PartialEq)]
6pub struct EncryptedStore<S, K> {
7    store: S,
8    key: K,
9}
10
11impl<S, K> EncryptedStore<S, K> {
12    pub fn new(store: S, key: K) -> Self {
13        Self { store, key }
14    }
15}
16
17impl<S: ExternalStore, K: Key> ExternalStore for EncryptedStore<S, K> {
18    type Id = S::Id;
19
20    async fn save_data(
21        &self,
22        data: &[u8],
23        refs: &[Self::Id],
24        wh: WithHash<'_, impl ToOutput>,
25    ) -> object_rainbow::Result<Self::Id> {
26        let encrypted = &self.key.encrypt(data);
27        let diff = DiffHashes {
28            tags: Default::default(),
29            topology: refs.data_hash(),
30            mangle: (self.key.mangle_prefix().data_hash(), wh.data.data_hash()).data_hash(),
31        };
32        self.store
33            .save_data(
34                encrypted,
35                refs,
36                WithHash {
37                    diff: diff.data_hash(),
38                    data: encrypted,
39                },
40            )
41            .await
42    }
43
44    async fn contains_data(
45        &self,
46        data: &[u8],
47        refs: &[Self::Id],
48        wh: WithHash<'_, impl Send + Sync + ToOutput>,
49    ) -> object_rainbow::Result<bool> {
50        let encrypted = &self.key.encrypt(data);
51        let diff = DiffHashes {
52            tags: Default::default(),
53            topology: refs.data_hash(),
54            mangle: (self.key.mangle_prefix().data_hash(), wh.data.data_hash()).data_hash(),
55        };
56        self.store
57            .contains_data(
58                encrypted,
59                refs,
60                WithHash {
61                    diff: diff.data_hash(),
62                    data: encrypted,
63                },
64            )
65            .await
66    }
67
68    async fn contains(&self, id: &Self::Id) -> object_rainbow::Result<bool> {
69        self.store.contains(id).await
70    }
71
72    #[expect(refining_impl_trait)]
73    async fn fetch(&self, id: &Self::Id) -> object_rainbow::Result<Vec<u8>> {
74        self.key
75            .decrypt(self.store.fetch(id).await?.as_ref())
76            .map_err(object_rainbow::Error::consistency)
77    }
78}
79
80#[cfg(test)]
81mod test {
82    use std::convert::Infallible;
83
84    use macro_rules_attribute::apply;
85    use object_rainbow::{FullHash, Hash, ToOutput, WithHash};
86    use object_rainbow_encrypted::{Key, encrypt};
87    use object_rainbow_point::IntoPoint;
88    use object_rainbow_store::ExternalStore;
89    use smol_macros::test;
90
91    use crate::EncryptedStore;
92
93    #[derive(Clone, PartialEq)]
94    struct NormalStore;
95
96    impl ExternalStore for NormalStore {
97        type Id = Hash;
98
99        async fn save_data(
100            &self,
101            _: &[u8],
102            _: &[Self::Id],
103            wh: WithHash<'_, impl Send + Sync + ToOutput>,
104        ) -> object_rainbow::Result<Self::Id> {
105            Ok(wh.data_hash())
106        }
107
108        async fn contains_data(
109            &self,
110            _: &[u8],
111            _: &[Self::Id],
112            _: WithHash<'_, impl Send + Sync + ToOutput>,
113        ) -> object_rainbow::Result<bool> {
114            unimplemented!()
115        }
116
117        async fn contains(&self, _: &Self::Id) -> object_rainbow::Result<bool> {
118            unimplemented!()
119        }
120
121        #[expect(refining_impl_trait)]
122        async fn fetch(&self, _: &Self::Id) -> object_rainbow::Result<Vec<u8>> {
123            unimplemented!()
124        }
125    }
126
127    #[derive(Clone, Copy, PartialEq, Eq)]
128    struct InverseKey;
129
130    impl Key for InverseKey {
131        type Error = Infallible;
132
133        fn encrypt(&self, data: &[u8]) -> Vec<u8> {
134            data.iter().copied().map(|x| !x).collect()
135        }
136
137        fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, Self::Error> {
138            Ok(data.iter().copied().map(|x| !x).collect())
139        }
140    }
141
142    #[apply(test!)]
143    async fn equivalent_to_normal() -> object_rainbow::Result<()> {
144        let o = ((*b"a"), ((*b"b"), (*b"c").point()).point());
145        let e = encrypt(InverseKey, o.clone()).await?;
146        let f = e.full_hash();
147        let s = EncryptedStore::new(NormalStore, InverseKey);
148        let h = s.store_object(o).await?;
149        assert_eq!(f, h);
150        Ok(())
151    }
152}