use std::{collections::BTreeMap, path::PathBuf}; use chrono::Utc; use sett::{ decrypt::{decrypt, DecryptOpts}, encrypt::{encrypt, EncryptOpts}, openpgp::{certstore::CertStore, keystore::KeyStore}, package::{Package, CHECKSUM_FILE, CONTENT_FOLDER}, task::Mode, utils::Progress, }; const PASSWORD: &[u8] = b"secret"; struct ProgressNoop; impl Progress for ProgressNoop { fn set_length(&mut self, _len: u64) {} fn inc(&mut self, _delta: u64) {} fn finish(&mut self) {} } async fn encrypt_password_prompt( _hint: sett::openpgp::types::PasswordHint, ) -> sett::openpgp::types::Password { PASSWORD.into() } fn decrypt_password_prompt( _hint: sett::openpgp::types::PasswordHint, ) -> sett::openpgp::types::Password { PASSWORD.into() } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn roundtrip() { encrypt_and_decrypt(BTreeMap::from([ ("foo".into(), "bar".into()), ("baz".into(), "qux".into()), ])) .await; encrypt_and_decrypt(Default::default()).await; } async fn encrypt_and_decrypt(extra_metadata: BTreeMap) { const PASSWORD: &[u8] = b"secret"; const MESSAGE: &[u8] = b"A very secret message!"; let mut cert_store = CertStore::open_ephemeral(); let mut key_store = KeyStore::open_ephemeral().await.unwrap(); let (cert, _rev) = sett::openpgp::cert::CertBuilder::new() .add_userid("Chuck ") .set_password(Some(PASSWORD.into())) .generate() .unwrap(); cert_store.import(&cert).unwrap(); key_store.import(cert.clone()).await.unwrap(); let tmp_dir = tempfile::tempdir().unwrap(); let test_file = tmp_dir.path().join("test.txt"); std::fs::write(&test_file, MESSAGE).unwrap(); let status = encrypt( EncryptOpts { files: vec![test_file.to_path_buf()], recipients: vec![cert.fingerprint()], signer: cert.fingerprint(), cert_store, key_store, password: encrypt_password_prompt, compression_algorithm: Default::default(), mode: Mode::Run, progress: None::, purpose: None, transfer_id: None, timestamp: Utc::now(), prefix: None, extra_metadata: extra_metadata.clone(), }, sett::destination::Local::new(tmp_dir.path(), None::) .unwrap() .into(), ) .await .unwrap(); let package_path = match status { sett::task::Status::Completed { destination, .. } => destination, _ => panic!("Expected completed status"), }; let mut cert_store = CertStore::open_ephemeral(); cert_store.import(&cert).unwrap(); let mut key_store = KeyStore::open_ephemeral().await.unwrap(); key_store.import(cert.clone()).await.unwrap(); let decrypt_opts = DecryptOpts { package: Package::open(package_path).await.unwrap(), key_store, cert_store, password: decrypt_password_prompt, output: Some(tmp_dir.path().to_path_buf()), mode: Mode::Run, decrypt_only: false, progress: None::, }; let package = decrypt_opts .package .clone() .verify(&decrypt_opts.cert_store) .await .unwrap(); let pkg_metadata = package.metadata().await.unwrap(); let status = decrypt(decrypt_opts).await.unwrap(); let unpacked_package = match status { sett::task::Status::Completed { destination, .. } => PathBuf::from(destination), _ => panic!("Expected completed status"), }; assert!(unpacked_package.join(CHECKSUM_FILE).exists()); let decrypted_file_path = unpacked_package.join(CONTENT_FOLDER).join("test.txt"); assert_eq!(std::fs::read(decrypted_file_path).unwrap(), MESSAGE); assert_eq!(pkg_metadata.extra, extra_metadata); } }