1use crate::errors::DatabaseError;
2use num_traits::cast::ToPrimitive;
3use ring::rand::SecureRandom;
4use ring::rand::SystemRandom;
5use ring::{
6 aead::{Aad, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey},
7 error::Unspecified,
8};
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use serde_bytes::ByteBuf;
11use sqlx::types::BigDecimal;
12use zeroize::{Zeroize, ZeroizeOnDrop};
13
14use crate::consts::KEYFILE_PATH;
15
16#[derive(sqlx::FromRow, Zeroize, ZeroizeOnDrop)]
17pub struct EncryptedSecret {
18 pub key: String,
19 #[sqlx(try_from = "BigDecimal")]
20 pub nonce: U64Wrapper,
21 pub ciphertext: Vec<u8>,
22 tags: Vec<String>,
23 access_level: i32,
24 role_whitelist: Vec<String>,
25}
26
27#[derive(Default)]
28pub struct EncryptedSecretBuilder {
29 pub key: String,
30 value: String,
31 tags: Option<Vec<String>>,
32 access_level: Option<i32>,
33 role_whitelist: Option<Vec<String>>,
34}
35
36impl EncryptedSecretBuilder {
37 pub fn new(key: String, value: String) -> Self {
38 Self {
39 key,
40 value,
41 ..Default::default()
42 }
43 }
44
45 pub fn with_tags(mut self, tags: Option<Vec<String>>) -> Self {
46 if let Some(tags) = tags {
47 self.tags = Some(tags);
48 }
49 self
50 }
51
52 pub fn with_access_level(mut self, access_level: Option<i32>) -> Self {
53 if let Some(access_level) = access_level {
54 self.access_level = Some(access_level);
55 }
56 self
57 }
58
59 pub fn with_whitelist(mut self, role_whitelist: Option<Vec<String>>) -> Self {
60 if let Some(role_whitelist) = role_whitelist {
61 self.role_whitelist = Some(role_whitelist);
62 }
63 self
64 }
65
66 pub fn build(
67 self,
68 mut sealing_key: SealingKey<NonceCounter>,
69 nonce_num: u64,
70 ) -> EncryptedSecret {
71 let aad = Aad::empty();
72
73 let mut transformed_in_place: Vec<u8> = self.value.into_bytes();
74
75 sealing_key
76 .seal_in_place_append_tag(aad, &mut transformed_in_place)
77 .unwrap();
78
79 EncryptedSecret {
80 key: self.key,
81 nonce: U64Wrapper(nonce_num),
82 ciphertext: transformed_in_place,
83 tags: if let Some(tags) = self.tags {
84 tags
85 } else {
86 Vec::new()
87 },
88 access_level: if let Some(access_level) = self.access_level {
89 access_level
90 } else {
91 0
92 },
93 role_whitelist: if let Some(whitelist) = self.role_whitelist {
94 whitelist
95 } else {
96 Vec::new()
97 },
98 }
99 }
100}
101
102#[derive(sqlx::FromRow)]
103pub struct Secret {
104 #[sqlx(try_from = "BigDecimal")]
105 pub nonce: U64Wrapper,
106 pub ciphertext: Vec<u8>,
107}
108
109impl Secret {
110 pub fn decrypt(&self, mut seq: OpeningKey<NonceCounter>) -> String {
111 let aad = Aad::empty();
112
113 let mut tag = self.ciphertext.clone();
114
115 let plaintext = seq.open_in_place(aad, &mut tag).unwrap();
116
117 String::from_utf8(plaintext.to_vec()).unwrap()
118 }
119}
120
121#[derive(sqlx::FromRow, Clone, Serialize, Deserialize, Debug)]
122pub struct SecretInfo {
123 pub key: String,
124 pub tags: Vec<String>,
125 pub access_level: i32,
126 pub role_whitelist: Vec<String>,
127}
128
129impl<'a> EncryptedSecret {
130 pub fn key(&'a self) -> &'a str {
131 &self.key
132 }
133
134 pub fn nonce(&self) -> u64 {
135 self.nonce.0
136 }
137
138 pub fn ciphertext(&self) -> &[u8] {
139 &self.ciphertext
140 }
141
142 pub fn tags(&'a self) -> Vec<&'a str> {
143 self.tags.iter().map(AsRef::as_ref).collect()
144 }
145
146 pub fn remove_all_tags(mut self) {
147 self.tags = Vec::new();
148 }
149
150 pub fn add_tag(mut self, string: &str) {
151 self.tags.push(string.to_owned());
152 }
153
154 pub fn replace_tags(&mut self, tags: Vec<String>) {
155 self.tags = tags;
156 }
157
158 pub fn remove_tag(mut self, tag: &str) {
159 self.tags.retain(|x| x == tag);
160 }
161
162 pub fn access_level(&self) -> i32 {
163 self.access_level
164 }
165
166 pub fn set_access_level(&mut self, level: Option<i32>) {
167 if let Some(level) = level {
168 self.access_level = level;
169 }
170 }
171
172 pub fn role_whitelist(&'a self) -> Vec<&'a str> {
173 self.role_whitelist.iter().map(AsRef::as_ref).collect()
174 }
175
176 pub fn set_role_whitelist(&mut self, whitelist: Option<Vec<String>>) {
177 if let Some(mut whitelist) = whitelist {
178 self.role_whitelist.append(&mut whitelist);
179 }
180 }
181
182 pub fn add_role_to_whitelist(&mut self, role: String) {
183 self.role_whitelist.push(role);
184 }
185
186 pub fn remove_role_from_whitelist(&mut self, role: String) {
187 self.role_whitelist.retain(|x| x != &role);
188 }
189
190 pub fn reencrypt(
191 &mut self,
192 mut open_key: OpeningKey<NonceCounter>,
193 mut sealing_key: SealingKey<NonceCounter>
194 ) {
195 let aad = Aad::empty();
196
197 let mut tag = self.ciphertext.clone();
198
199 let key = open_key.open_in_place(aad, &mut tag).unwrap();
200
201 let plaintext = String::from_utf8(key.to_vec()).unwrap();
202
203 let mut transformed_in_place: Vec<u8> = plaintext.into_bytes();
204
205 sealing_key
206 .seal_in_place_append_tag(aad, &mut transformed_in_place)
207 .unwrap();
208
209 self.ciphertext = transformed_in_place;
210
211 }
212}
213
214#[derive(Zeroize, ZeroizeOnDrop)]
215pub struct SerializeKey(pub Vec<u8>);
216
217impl SerializeKey {
218 pub fn new() -> Self {
219 let rand = SystemRandom::new();
220 let mut key: [u8; 32] = [0u8; 32];
221 let _ = rand.fill(&mut key);
222 Self(key.to_vec())
223 }
224
225 pub fn make_key(&self) -> ring::aead::UnboundKey {
226 ring::aead::UnboundKey::new(&ring::aead::AES_256_GCM, &self.0).unwrap()
227 }
228}
229
230impl Default for SerializeKey {
231 fn default() -> Self {
232 Self::new()
233 }
234}
235
236impl Serialize for SerializeKey {
237 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
238 where
239 S: Serializer,
240 {
241 let vec = self.0.to_vec();
242 serializer.serialize_bytes(&vec)
243 }
244}
245
246impl<'de> Deserialize<'de> for SerializeKey {
247 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
248 where
249 D: Deserializer<'de>,
250 {
251 let bytes = Deserialize::deserialize(deserializer)
252 .map(ByteBuf::into_vec)
253 .unwrap();
254
255 Ok(Self(bytes))
256 }
257}
258
259#[derive(Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
260pub struct KeyFile {
261 unlock_key: String,
262 crypto_key: SerializeKey,
263 pub nonce_number: u64,
264}
265
266impl<'b> KeyFile {
267 pub fn new() -> Self {
268 Self {
269 unlock_key: nanoid::nanoid!(100),
270 crypto_key: SerializeKey::new(),
271 nonce_number: 1,
272 }
273 }
274
275 pub fn crypto_key(&'b self) -> &'b SerializeKey {
276 &self.crypto_key
277 }
278
279 pub fn from_key(string: &str) -> Self {
280 Self {
281 unlock_key: string.to_owned(),
282 crypto_key: SerializeKey::new(),
283 nonce_number: 1,
284 }
285 }
286
287 pub fn unseal_key(&'b self) -> &'b str {
288 &self.unlock_key
289 }
290
291 pub fn save(&self) -> Result<(), DatabaseError> {
292 let _thing = self;
293 let encoded = bincode::serialize(&self).unwrap();
294
295 match std::fs::write(KEYFILE_PATH, encoded) {
296 Ok(res) => res,
297 Err(e) => return Err(DatabaseError::IoError(e)),
298 };
299 Ok(())
300 }
301
302 pub fn get_crypto_seal_key(&mut self) -> SealingKey<NonceCounter> {
303 let nonce_sequence = NonceCounter(self.nonce_number);
304
305 let unbound_key = self.crypto_key.make_key();
306 self.nonce_number += 1;
307
308 let _ = self.save();
309 SealingKey::new(unbound_key, nonce_sequence)
310 }
311
312 pub fn get_crypto_open_key(&self, num: u64) -> OpeningKey<NonceCounter> {
313 let nonce_sequence = NonceCounter(num);
314
315 let unbound_key = self.crypto_key.make_key();
316 OpeningKey::new(unbound_key, nonce_sequence)
317 }
318}
319
320impl Default for KeyFile {
321 fn default() -> Self {
322 Self::new()
323 }
324}
325
326#[derive(Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
327pub struct U64Wrapper(pub u64);
328
329impl U64Wrapper {
330 pub fn inner(&self) -> u64 {
331 self.0
332 }
333}
334
335impl From<BigDecimal> for U64Wrapper {
336 fn from(decimal: BigDecimal) -> Self {
337 Self(decimal.to_u64().unwrap())
338 }
339}
340
341pub struct NonceCounter(u64);
342
343impl Default for NonceCounter {
344 fn default() -> Self {
345 Self::new()
346 }
347}
348
349impl NonceCounter {
350 pub fn new() -> Self {
351 Self(1)
352 }
353
354 pub fn from_num(num: u64) -> Self {
355 Self(num)
356 }
357}
358
359impl NonceSequence for NonceCounter {
360 fn advance(&mut self) -> Result<Nonce, Unspecified> {
362 let mut nonce_bytes: [u8; 12] = [0; 12];
363
364 let bytes = self.0.to_be_bytes();
365 nonce_bytes[4..].copy_from_slice(&bytes);
366
367 self.0 += 1; Ok(Nonce::try_assume_unique_for_key(&nonce_bytes).unwrap())
369 }
370}