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}