sec_store/
lib.rs

1//!Minimalistic encrypted storage for arbitrary values.
2
3#![warn(missing_docs)]
4#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
5
6use std::collections::BTreeMap;
7use xxhash_rust::xxh3::xxh3_128;
8
9use core::ptr;
10
11mod enc;
12
13///Secure storage API
14///
15///Values are stored in memory encrypted, user can save storages manually
16///and lately restore it using `serde`
17///
18///`Key` is stored as hash, while `Value` is stored as encrypted bytes.
19pub struct Store {
20    ///Values are stored as hash(key), encrypted data(value)
21    ///
22    ///Technically it is possible to reverse hash, but in practice it is unlikely to happen.
23    ///Only value itself is supposed to be sensitive in our case
24    inner: BTreeMap<u128, Vec<u8>>,
25    enc: enc::Manager,
26}
27
28impl Store {
29    #[inline]
30    ///Creates new instance using creds.
31    ///
32    ///Parameters:
33    ///
34    ///- `user` - user specific information that can distinguish him from others.
35    ///- `pass` - can be any number of arbitrary bytes except it MUST NOT be zero length.
36    pub fn new(user: &[u8], pass: &[u8]) -> Self {
37        Self::from_inner(Default::default(), user, pass)
38    }
39
40    #[inline]
41    ///Creates new instance using provided storage and pass.
42    ///
43    ///Parameters:
44    ///
45    ///- `storage` - already initialized storage, only can work with storage that is returned by `Self::inner`.
46    ///- `user`    - user specific information that can distinguish him from others.
47    ///- `pass`    - can be any number of arbitrary bytes except it MUST NOT be zero length.
48    pub fn from_inner(inner: BTreeMap<u128, Vec<u8>>, user: &[u8], pass: &[u8]) -> Self {
49        assert_ne!(user.len(), 0);
50        assert_ne!(pass.len(), 0);
51
52        Self {
53            inner,
54            enc: enc::Manager::new(enc::generate_key(user, pass))
55        }
56    }
57
58    #[inline]
59    ///Accesses inner representation of storage, allowing to serialize it.
60    pub fn inner(&self) -> &BTreeMap<u128, Vec<u8>> {
61        &self.inner
62    }
63
64    #[inline]
65    ///Consumes self, returning underlying storage.
66    pub fn into_inner(self) -> BTreeMap<u128, Vec<u8>> {
67        self.inner
68    }
69
70    #[inline]
71    ///Returns number of key-value pairs
72    pub fn len(&self) -> usize {
73        self.inner.len()
74    }
75
76    fn inner_get_to(&self, key: u128, dest: &mut [u8]) -> Result<usize, ()> {
77        match self.inner.get(&key) {
78            Some(value) => {
79                if value.len() > dest.len() {
80                    return Ok(0);
81                }
82
83                unsafe {
84                    ptr::copy_nonoverlapping(value.as_ptr(), dest.as_mut_ptr(), value.len());
85                }
86
87                match self.enc.decrypt(key, &mut dest[..value.len()]) {
88                    Some(written) => {
89                        Ok(written.len())
90                    },
91                    None => Err(())
92                }
93            },
94            None => Err(())
95        }
96    }
97
98    fn inner_get_to_vec(&self, key: u128, dest: &mut Vec<u8>) -> Result<usize, ()> {
99        match self.inner.get(&key) {
100            Some(value) => {
101                dest.truncate(0);
102                dest.extend_from_slice(&value);
103                match self.enc.decrypt(key, dest) {
104                    Some(written) => {
105                        let len = written.len();
106                        dest.truncate(len);
107                        dest.shrink_to_fit();
108                        Ok(dest.len())
109                    },
110                    None => Err(())
111                }
112            },
113            None => Err(()),
114        }
115    }
116
117    #[inline]
118    ///Retrieves value for `key`, storing decrypted value in `dest`.
119    ///
120    ///Returns `Err` when key doesn't exist or user has no permission to read it.
121    ///Otherwise returns number of bytes written, or '0' in case of insufficient storage.
122    pub fn get_to(&self, key: &[u8], dest: &mut [u8]) -> Result<usize, ()> {
123        let key = xxh3_128(key).to_le();
124
125        self.inner_get_to(key, dest)
126    }
127
128    #[inline]
129    ///Retrieves value for `key` to store in `dest`, resulting in it being overwritten.
130    ///
131    ///Returns `Err` when key doesn't exist or user has no permission to read it.
132    ///Otherwise returns number of bytes written.
133    pub fn get_to_vec(&self, key: &[u8], dest: &mut Vec<u8>) -> Result<usize, ()> {
134        let key = xxh3_128(key).to_le();
135
136        self.inner_get_to_vec(key, dest)
137    }
138
139    #[inline]
140    ///Retrieves value for `key`
141    ///
142    ///Returns `None` if decryption failed.
143    pub fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
144        let mut result = Vec::new();
145        match self.get_to_vec(key, &mut result) {
146            Ok(_) => Some(result),
147            Err(_) => None,
148        }
149    }
150
151    #[inline]
152    ///Checks for `key` presence within storage
153    pub fn contains(&self, key: &[u8]) -> bool {
154        let key = xxh3_128(key).to_le();
155
156        self.inner().contains_key(&key)
157    }
158
159    ///Inserts new owned `value` for `key`, returning previous one, if any.
160    pub fn insert_owned(&mut self, key: &[u8], mut value: Vec<u8>) -> Option<Vec<u8>> {
161        assert_ne!(value.len(), 0);
162
163        let key = xxh3_128(key).to_le();
164
165        assert!(self.enc.encrypt(key, &mut value));
166
167        self.inner.insert(key, value).and_then(|mut value| {
168            match self.enc.decrypt(key, &mut value) {
169                Some(written) => {
170                    let len = written.len();
171                    value.truncate(len);
172                    value.shrink_to_fit();
173                    Some(value)
174                },
175                None => None
176            }
177        })
178    }
179
180    #[inline]
181    ///Inserts new `value` for `key`, returning previous one, if any.
182    pub fn insert(&mut self, key: &[u8], value: &[u8]) -> Option<Vec<u8>> {
183        self.insert_owned(key, value.to_owned())
184    }
185
186    ///Extracts value under `key` to specified `dest`
187    ///
188    ///Returns `Err` when key doesn't exist, or user has no permission to read it.
189    ///Otherwise returns number of bytes written, or '0' in case of insufficient storage.
190    ///
191    ///Note that value is removed only if `Ok(size) >= Ok(1)`
192    pub fn remove_to(&mut self, key: &[u8], dest: &mut [u8]) -> Result<usize, ()> {
193        let key = xxh3_128(key).to_le();
194
195        match self.inner_get_to(key, dest) {
196            Ok(0) => Ok(0),
197            Ok(result) => {
198                let _ = self.inner.remove(&key);
199                Ok(result)
200            },
201            Err(_) => Err(()),
202        }
203    }
204
205    ///Extracts value under `key` to specified `dest`
206    ///
207    ///Returns `Err` when key doesn't exist, or user has no permission to read it.
208    ///Otherwise returns number of bytes written.
209    pub fn remove_to_vec(&mut self, key: &[u8], dest: &mut Vec<u8>) -> Result<usize, ()> {
210        let key = xxh3_128(key).to_le();
211
212        match self.inner_get_to_vec(key, dest) {
213            Ok(result) => {
214                let _ = self.inner.remove(&key);
215                Ok(result)
216            },
217            Err(_) => Err(()),
218        }
219    }
220
221    #[inline]
222    ///Removes `key`, returning previous value, if any.
223    ///
224    ///Failing to decrypt, doesn't remove value.
225    pub fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
226        let mut result = Vec::new();
227        match self.remove_to_vec(key, &mut result) {
228            Ok(_) => Some(result),
229            Err(_) => None,
230        }
231    }
232
233    #[inline]
234    ///Removes `key`, returning whether it was set previously.
235    ///
236    ///Note that it only removes value, without checking if you can read it.
237    pub fn remove_key(&mut self, key: &[u8]) -> bool {
238        let key = xxh3_128(key).to_le();
239        self.inner.remove(&key).is_some()
240    }
241}