use bc_components::{EncryptedKey, KeyDerivationMethod, SymmetricKey};
use known_values;
use crate::{Envelope, Error, Result};
impl Envelope {
pub fn lock_subject(
&self,
method: KeyDerivationMethod,
secret: impl AsRef<[u8]>,
) -> Result<Self> {
let content_key = SymmetricKey::new();
let encrypted_key = EncryptedKey::lock(method, secret, &content_key)?;
Ok(self
.encrypt_subject(&content_key)
.expect("Encrypt subject")
.add_assertion(known_values::HAS_SECRET, encrypted_key))
}
pub fn unlock_subject(&self, secret: impl AsRef<[u8]>) -> Result<Self> {
for assertion in
self.assertions_with_predicate(known_values::HAS_SECRET)
{
let obj = assertion.as_object().unwrap();
if !obj.is_obscured() {
let encrypted_key = obj.extract_subject::<EncryptedKey>()?;
if let Ok(content_key) = encrypted_key.unlock(secret.as_ref()) {
return self.decrypt_subject(&content_key);
}
}
}
Err(Error::UnknownSecret)
}
pub fn is_locked_with_password(&self) -> bool {
self.assertions_with_predicate(known_values::HAS_SECRET)
.iter()
.any(|assertion| {
let obj = assertion.as_object().unwrap();
if let Ok(encrypted_key) = obj.extract_subject::<EncryptedKey>()
{
encrypted_key.is_password_based()
} else {
false
}
})
}
pub fn is_locked_with_ssh_agent(&self) -> bool {
self.assertions_with_predicate(known_values::HAS_SECRET)
.iter()
.any(|assertion| {
let obj = assertion.as_object().unwrap();
if let Ok(encrypted_key) = obj.extract_subject::<EncryptedKey>()
{
encrypted_key.is_ssh_agent()
} else {
false
}
})
}
pub fn add_secret(
&self,
method: KeyDerivationMethod,
secret: impl AsRef<[u8]>,
content_key: &SymmetricKey,
) -> Result<Self> {
let encrypted_key = EncryptedKey::lock(method, secret, content_key)?;
Ok(self.add_assertion(known_values::HAS_SECRET, encrypted_key))
}
}
impl Envelope {
pub fn lock(
&self,
method: KeyDerivationMethod,
secret: impl AsRef<[u8]>,
) -> Result<Self> {
self.wrap().lock_subject(method, secret)
}
pub fn unlock(&self, secret: impl AsRef<[u8]>) -> Result<Self> {
self.unlock_subject(secret)?.try_unwrap()
}
}