burrito_secrets/waiters/
burrito_box.rs1use crate::database::{Entry, Metadata};
7use crate::encryption::EncryptionWaiter;
8use bson::doc;
9use bson::spec::BinarySubtype;
10use dryoc::dryocbox::protected::{PublicKey, SecretKey};
11use serde::{Deserialize, Serialize};
12use std::collections::BTreeMap;
13use crate::waiters::Waiter;
14
15#[derive(Serialize, Deserialize)]
16#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
17pub struct BurritoBox {
18 encrypted: bson::Binary,
19 ephemeral_public_key: bson::Binary,
20 mac: bson::Binary,
21 #[serde(flatten)]
22 additional_fields: BTreeMap<String, bson::Bson>,
23}
24
25impl BurritoBox {
26 pub fn from_encrypted(encrypted: dryoc::dryocbox::VecBox) -> Self {
27 let (mac, encrypted, Some(key)) = encrypted.into_parts() else {
28 panic!("encrypted box is non-standard");
30 };
31
32 let encrypted = bson::Binary {
33 subtype: BinarySubtype::Encrypted,
34 bytes: encrypted,
35 };
36
37 let mac = bson::Binary {
38 subtype: BinarySubtype::Sensitive,
39 bytes: mac.to_vec(),
40 };
41
42 let ephemeral_public_key = bson::Binary {
43 subtype: BinarySubtype::Sensitive,
44 bytes: key.to_vec(),
45 };
46
47 Self {
48 encrypted,
49 mac,
50 ephemeral_public_key,
51 additional_fields: BTreeMap::new(),
52 }
53 .and_defaults::<Self>()
54 }
55}
56
57impl Waiter for BurritoBox {
58 fn name() -> String {
59 "burrito_asymmetric_box".to_string()
60 }
61
62 fn version() -> String {
63 "0.0.0".to_string()
64 }
65
66 fn into_entry(self) -> Entry {
67 bson::to_document(&self).unwrap().and_defaults::<Self>()
68 }
69
70 fn from_entry(entry: Entry) -> anyhow::Result<Self> {
71 Self::verify_version(&entry)?;
72
73 let burrito_box = bson::from_document(entry)?;
74
75 Ok(burrito_box)
76 }
77}
78
79impl Metadata for BurritoBox {
80 fn get_meta(&self, key: &str) -> Option<&bson::Bson> {
81 self.additional_fields.get(key)
82 }
83
84 fn set_meta(&mut self, metadata: (&str, impl Serialize)) {
85 self.additional_fields.insert(metadata.0.to_string(), bson::to_bson(&metadata.1).unwrap());
86 }
87}
88
89impl EncryptionWaiter for BurritoBox {
90 fn encrypt(entry: Entry, key: PublicKey) -> anyhow::Result<Self> {
91 use dryoc::dryocbox::VecBox;
92
93 let entry_bytes = bson::to_vec(&entry)?;
94 let secret_box = VecBox::seal(&entry_bytes, &key)?;
95
96 Ok(Self::from_encrypted(secret_box))
97 }
98
99 fn decrypt(self, key: SecretKey) -> anyhow::Result<Entry> {
100 use dryoc::dryocbox::VecBox;
101 use dryoc::dryocbox::protected::SecretKey;
102 use dryoc::dryocbox::PublicKey;
103 use dryoc::dryocbox::Mac;
104 use dryoc::keypair::KeyPair;
105
106 let keypair: KeyPair<PublicKey, SecretKey> = KeyPair::from_secret_key(key);
107
108 let mac = self.mac.bytes;
109 let mac = Mac::try_from(mac.as_slice())?;
110
111 let encrypted = self.encrypted.bytes;
112
113 let ephemeral_public_key = self.ephemeral_public_key.bytes;
114 let ephemeral_public_key = PublicKey::try_from(ephemeral_public_key.as_slice())?;
115
116 let encrypted = VecBox::from_parts(mac, encrypted, Some(ephemeral_public_key));
117
118 let unencrypted = encrypted.unseal_to_vec(&keypair)?;
119 let unencrypted = bson::from_slice(&unencrypted)?;
120
121
122 Ok(unencrypted)
123 }
124}