use crate::types::{ObjectId, Result, SealError, CEK};
use saorsa_fec::crypto::{CryptoEngine, EncryptionKey};
pub struct ContentEncryptor {
crypto_engine: CryptoEngine,
cek: CEK,
}
impl ContentEncryptor {
pub fn new(cek: CEK, _object_id: ObjectId) -> Result<Self> {
let crypto_engine = CryptoEngine::new();
Ok(Self { crypto_engine, cek })
}
pub fn encrypt(&mut self, plaintext: &[u8]) -> Result<Vec<u8>> {
let key_bytes = *self.cek.as_bytes();
let encryption_key = EncryptionKey::new(key_bytes);
let result = self
.crypto_engine
.encrypt(plaintext, &encryption_key)
.map_err(|e| SealError::EncryptionError(e.to_string()))?;
Ok(result)
}
pub fn decrypt(&mut self, ciphertext: &[u8]) -> Result<Vec<u8>> {
let key_bytes = *self.cek.as_bytes();
let encryption_key = EncryptionKey::new(key_bytes);
let plaintext = self
.crypto_engine
.decrypt(ciphertext, &encryption_key)
.map_err(|e| SealError::DecryptionError(e.to_string()))?;
Ok(plaintext)
}
}
pub fn compute_cek_commitment(cek: &CEK) -> [u8; 32] {
let mut hasher = blake3::Hasher::new();
hasher.update(b"cek");
hasher.update(cek.as_bytes());
*hasher.finalize().as_bytes()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_content_encryption() {
let cek = CEK::generate();
let object_id = [1u8; 32];
let mut encryptor = ContentEncryptor::new(cek.clone(), object_id).unwrap();
let plaintext = b"Hello, World!";
let ciphertext = encryptor.encrypt(plaintext).unwrap();
assert_ne!(ciphertext, plaintext);
let decrypted = encryptor.decrypt(&ciphertext).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_cek_commitment() {
let cek = CEK::from_bytes([5u8; 32]);
let commitment1 = compute_cek_commitment(&cek);
let commitment2 = compute_cek_commitment(&cek);
assert_eq!(commitment1, commitment2);
let different_cek = CEK::from_bytes([6u8; 32]);
let different_commitment = compute_cek_commitment(&different_cek);
assert_ne!(commitment1, different_commitment);
}
}