bc_envelope/extension/
secret.rs

1use anyhow::{ bail, Result };
2use bc_components::{ KeyDerivationMethod, SymmetricKey, EncryptedKey };
3use crate::{ Envelope, Error };
4use known_values;
5
6impl Envelope {
7    pub fn lock_subject(&self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>) -> Self {
8        let content_key = SymmetricKey::new();
9        // Lock the content key using the specified derivation method
10        let encrypted_key = EncryptedKey::lock(method, secret, &content_key);
11        // Add a hasSecret assertion with the EncryptedKey
12        self.encrypt_subject(&content_key)
13            .expect("Failed to encrypt subject")
14            .add_assertion(known_values::HAS_SECRET, encrypted_key)
15    }
16
17    pub fn unlock_subject(&self, secret: impl AsRef<[u8]>) -> Result<Self> {
18        // Find and attempt to unlock each EncryptedKey in hasSecret assertions
19        for assertion in self.assertions_with_predicate(known_values::HAS_SECRET) {
20            let obj = assertion.as_object().unwrap();
21            if !obj.is_obscured() {
22                let encrypted_key = obj.extract_subject::<EncryptedKey>()?;
23                if let Ok(content_key) = encrypted_key.unlock(secret.as_ref()) {
24                    return self.decrypt_subject(&content_key);
25                }
26            }
27        }
28        // No matching secret unlock succeeded
29        bail!(Error::UnknownSecret)
30    }
31
32    pub fn add_secret(
33        &self,
34        method: KeyDerivationMethod,
35        secret: impl AsRef<[u8]>,
36        content_key: &SymmetricKey
37    ) -> Self {
38        // Lock the content key using the specified derivation method
39        let encrypted_key = EncryptedKey::lock(method, secret, content_key);
40        // Add a hasSecret assertion with the EncryptedKey
41        self.add_assertion(known_values::HAS_SECRET, encrypted_key)
42    }
43}
44
45impl Envelope {
46    pub fn lock(&self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>) -> Self {
47        self.wrap_envelope().lock_subject(method, secret)
48    }
49
50    pub fn unlock(&self, secret: impl AsRef<[u8]>) -> Result<Self> {
51        self.unlock_subject(secret)?.unwrap_envelope()
52    }
53}