use config::app::{AppConfig, AppKeyAlgorithm, AppKeyConfig, SecretMaterial}; use crate::error::{CryptError, CryptResult}; use crate::key::{RsaDecryptor, RsaEncryptor, RsaKeyPair}; pub fn encryptor(config: &AppConfig) -> CryptResult { let key = config .encryption_key() .ok_or_else(|| CryptError::KeyNotFound(config.active_key_id.clone()))?; encryptor_for(key) } pub fn encryptor_for(key: &AppKeyConfig) -> CryptResult { check_algorithm(key)?; let pem = resolve(&key.public_key, &key.key_id)?; RsaEncryptor::from_public_pem(key.key_id.clone(), &pem) } pub fn encryptor_from_public_pem( key_id: impl Into, pem: &str, ) -> CryptResult { RsaEncryptor::from_public_pem(key_id, pem) } pub fn decryptor(config: &AppConfig) -> CryptResult { let mut keys = Vec::new(); for key in config.decryption_keys() { check_algorithm(key)?; let private = key .private_key .as_ref() .ok_or_else(|| CryptError::KeyNotFound(key.key_id.clone()))?; let private_pem = resolve(private, &key.key_id)?; let public_pem = resolve(&key.public_key, &key.key_id)?; keys.push(RsaKeyPair::from_pem_pair( key.key_id.clone(), &private_pem, &public_pem, )?); } RsaDecryptor::new(keys) } pub fn fingerprint_for(key: &AppKeyConfig) -> CryptResult { Ok(encryptor_for(key)?.fingerprint()) } fn resolve(material: &SecretMaterial, key_id: &str) -> CryptResult { material .resolve() .map_err(|error| CryptError::Config(format!("key `{key_id}`: {error}"))) } fn check_algorithm(key: &AppKeyConfig) -> CryptResult<()> { match key.algorithm { AppKeyAlgorithm::RsaOaep256A256Gcm => Ok(()), } }