saorsa-seal 0.1.3

Threshold sealing for group data in the Saorsa network
Documentation
//! AEAD content encryption using saorsa-fec CryptoEngine

use crate::types::{ObjectId, Result, SealError, CEK};
use saorsa_fec::crypto::{CryptoEngine, EncryptionKey};

/// Content encryptor using saorsa-fec CryptoEngine
pub struct ContentEncryptor {
    crypto_engine: CryptoEngine,
    cek: CEK,
}

impl ContentEncryptor {
    /// Create a new content encryptor using saorsa-fec CryptoEngine
    pub fn new(cek: CEK, _object_id: ObjectId) -> Result<Self> {
        let crypto_engine = CryptoEngine::new();

        Ok(Self { crypto_engine, cek })
    }

    /// Encrypt data using saorsa-fec CryptoEngine
    pub fn encrypt(&mut self, plaintext: &[u8]) -> Result<Vec<u8>> {
        // Create encryption key from CEK
        let key_bytes = *self.cek.as_bytes();
        let encryption_key = EncryptionKey::new(key_bytes);

        // Encrypt using saorsa-fec CryptoEngine
        let result = self
            .crypto_engine
            .encrypt(plaintext, &encryption_key)
            .map_err(|e| SealError::EncryptionError(e.to_string()))?;

        Ok(result)
    }

    /// Decrypt data using saorsa-fec CryptoEngine
    pub fn decrypt(&mut self, ciphertext: &[u8]) -> Result<Vec<u8>> {
        // Create encryption key from CEK
        let key_bytes = *self.cek.as_bytes();
        let encryption_key = EncryptionKey::new(key_bytes);

        // Decrypt using saorsa-fec CryptoEngine
        let plaintext = self
            .crypto_engine
            .decrypt(ciphertext, &encryption_key)
            .map_err(|e| SealError::DecryptionError(e.to_string()))?;

        Ok(plaintext)
    }
}

/// Compute CEK commitment
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);
    }
}