use std::sync::Arc;
use crate::error::Result;
use crate::manager::EncryptionManager;
#[derive(Debug, Clone)]
pub struct Guard {
manager: Arc<EncryptionManager>,
}
impl Guard {
pub fn new(manager: EncryptionManager) -> Self {
Self {
manager: Arc::new(manager),
}
}
pub fn from_master_key(master_key: &[u8], default_identifier: &str) -> Result<Self> {
Ok(Self::new(
crate::factory::EncryptionManagerFactory::from_master_key(
master_key,
default_identifier,
)?,
))
}
pub fn manager(&self) -> &EncryptionManager {
&self.manager
}
pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
self.manager.encrypt(plaintext)
}
pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
self.manager.decrypt(ciphertext)
}
pub fn encrypt_with(&self, identifier: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
self.manager.encrypt_with(identifier, plaintext)
}
pub fn decrypt_with(&self, identifier: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
self.manager.decrypt_with(identifier, ciphertext)
}
pub fn identifiers(&self) -> Vec<&str> {
self.manager.registry().identifiers()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn guard() -> Guard {
Guard::from_master_key(&[7u8; 32], "aes-256-gcm").unwrap()
}
#[test]
fn wraps_the_factory_and_forwards() {
let guard = guard();
assert_eq!(guard.identifiers().len(), 5);
assert_eq!(guard.manager().default_identifier(), "aes-256-gcm");
let blob = guard.encrypt(b"phone").unwrap();
assert_eq!(guard.decrypt(&blob).unwrap(), b"phone");
let blob = guard.encrypt_with("sm4-cbc", b"phone").unwrap();
assert_eq!(guard.decrypt_with("sm4-cbc", &blob).unwrap(), b"phone");
}
#[test]
fn clones_share_one_manager() {
let guard = guard();
let clone = guard.clone();
let blob = guard.encrypt(b"shared").unwrap();
assert_eq!(clone.decrypt(&blob).unwrap(), b"shared");
assert_eq!(Arc::strong_count(&guard.manager), 2);
}
#[test]
fn invalid_master_key_fails_at_construction() {
assert!(Guard::from_master_key(&[0u8; 16], "aes-256-gcm").is_err());
assert!(Guard::from_master_key(&[0u8; 32], "no-such-algorithm").is_err());
}
}