burrito_secrets/waiters/
burrito_box_sym.rs1use crate::database::{Entry, Metadata};
7use crate::encryption::EncryptionWaiterSymmetric;
8use crate::waiters::Waiter;
9use bson::spec::BinarySubtype;
10use dryoc::dryocbox::protected::SecretKey;
11use dryoc::dryocsecretbox::Nonce;
12use dryoc::types::NewByteArray;
13use serde::{Deserialize, Serialize};
14use std::collections::BTreeMap;
15
16#[derive(Serialize, Deserialize)]
17#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
18pub struct BurritoBoxSym {
19 pub encrypted: bson::Binary,
20 pub mac: bson::Binary,
21 pub nonce: bson::Binary,
22 #[serde(flatten)]
23 pub additional_fields: BTreeMap<String, bson::Bson>,
24}
25
26impl BurritoBoxSym {
27 pub fn of_password(entry: Entry, mut password: String) -> Self {
28 use dryoc::dryocbox::protected::SecretKey;
29 use dryoc::dryocbox::protected::PublicKey;
30 use dryoc::keypair::KeyPair;
31 use dryoc::dryocsecretbox::VecBox;
32
33 let nonce = Nonce::gen();
34 let salt = nonce.to_vec();
35 let config = dryoc::pwhash::Config::interactive();
36 let keypair: KeyPair<PublicKey, SecretKey> = dryoc::pwhash::PwHash::derive_keypair(unsafe { password.as_mut_vec() }, salt, config).unwrap();
37 let secret_key = &keypair.secret_key;
38
39 let entry_bytes = bson::to_vec(&entry).unwrap();
40 let encrypted = VecBox::encrypt(&entry_bytes, &nonce, secret_key);
41 let (mac, encrypted) = encrypted.into_parts();
42
43 let encrypted = bson::Binary {
44 subtype: BinarySubtype::Encrypted,
45 bytes: encrypted,
46 };
47
48 let mac = bson::Binary {
49 subtype: BinarySubtype::Sensitive,
50 bytes: mac.to_vec(),
51 };
52
53 let nonce = bson::Binary {
54 subtype: BinarySubtype::Sensitive,
55 bytes: nonce.to_vec(),
56 };
57
58 Self {
59 encrypted,
60 mac,
61 nonce,
62 additional_fields: BTreeMap::new(),
63 }
64 .and_defaults::<Self>()
65 }
66
67 pub fn decrypt_password(self, mut password: String) -> anyhow::Result<Entry> {
68 use dryoc::dryocbox::protected::SecretKey;
69 use dryoc::dryocbox::protected::PublicKey;
70 use dryoc::keypair::KeyPair;
71 use dryoc::dryocsecretbox::VecBox;
72 use dryoc::dryocsecretbox::Mac;
73
74 let salt = self.nonce.bytes;
75 let nonce = Nonce::try_from(salt.as_slice())?;
76
77
78 let config = dryoc::pwhash::Config::interactive();
79 let keypair: KeyPair<PublicKey, SecretKey> = dryoc::pwhash::PwHash::derive_keypair(unsafe { password.as_mut_vec() }, salt, config)?;
80
81 let mac = Mac::try_from(self.mac.bytes.as_slice())?;
82
83 let encrypted = VecBox::from_parts(mac, self.encrypted.bytes);
84
85 let decrypted = encrypted.decrypt_to_vec(&nonce, &keypair.secret_key)?;
86 let entry = bson::from_slice(&decrypted)?;
87
88 Ok(entry)
89 }
90}
91
92impl Waiter for BurritoBoxSym {
93 fn name() -> String {
94 "burrito_symmetric_box".to_string()
95 }
96
97 fn version() -> String {
98 "0.0.0".to_string()
99 }
100
101 fn into_entry(self) -> Entry {
102 bson::to_document(&self)
103 .unwrap()
104 .and_defaults::<Self>()
105 }
106
107 fn from_entry(entry: Entry) -> anyhow::Result<Self> {
108 Self::verify_version(&entry)?;
109
110 let burrito = bson::from_document(entry)?;
111
112 Ok(burrito)
113 }
114}
115
116impl Metadata for BurritoBoxSym {
117 fn get_meta(&self, key: &str) -> Option<&bson::Bson> {
118 self.additional_fields.get(key)
119 }
120
121 fn set_meta(&mut self, metadata: (&str, impl Serialize)) {
122 self.additional_fields.insert(metadata.0.to_string(), bson::to_bson(&metadata.1).unwrap());
123 }
124}
125
126impl EncryptionWaiterSymmetric for BurritoBoxSym {
127 fn encrypt_sym(entry: Entry, key: SecretKey) -> anyhow::Result<Self> {
128 use dryoc::dryocsecretbox::VecBox;
129 use dryoc::dryocsecretbox::Nonce;
130
131 let entry_bytes = bson::to_vec(&entry)?;
132 let nonce = Nonce::gen();
133 let encrypted = VecBox::encrypt(&entry_bytes, &nonce, &key);
134 let (mac, encrypted) = encrypted.into_parts();
135
136 let encrypted = bson::Binary {
137 subtype: BinarySubtype::Encrypted,
138 bytes: encrypted,
139 };
140
141 let mac = bson::Binary {
142 subtype: BinarySubtype::Sensitive,
143 bytes: mac.to_vec(),
144 };
145
146 let nonce = bson::Binary {
147 subtype: BinarySubtype::Sensitive,
148 bytes: nonce.to_vec(),
149 };
150
151 Ok(
152 Self {
153 encrypted,
154 mac,
155 nonce,
156 additional_fields: BTreeMap::new(),
157 }
158 .and_defaults::<Self>()
159 )
160 }
161
162 fn decrypt_sym(self, key: SecretKey) -> anyhow::Result<Entry> {
163 use dryoc::dryocsecretbox::VecBox;
164 use dryoc::dryocsecretbox::Mac;
165
166 let mac = Mac::try_from(self.mac.bytes.as_slice())?;
167 let encrypted = self.encrypted.bytes;
168 let nonce = self.nonce.bytes;
169
170 let encrypted = VecBox::from_parts(mac, encrypted);
171 let decrypted = encrypted.decrypt_to_vec(&nonce, &key)?;
172
173 let entry = bson::from_slice(&decrypted)?;
174
175 Ok(entry)
176 }
177}