//! AES file container operations //! //! Should operate on streams to produce/consume instances of `format::key::aes::AesBody`. use super::*; use std::{ path::Path, }; use tokio::{ io::BufReader, fs::OpenOptions, }; /// Read an `AesBody` from a file. /// /// Detect the container type if possible and then decode the AES key. Returning it as `format::key::aes::AesBody`. #[instrument(skip(path), err, fields(path = ?path.as_ref()))] pub async fn read_aes_container(path: impl AsRef, passwd: (config::op::Password, Option<&str>)) -> eyre::Result { // password function let passwd = passwd.0.into_password(passwd.1.unwrap_or("Enter password for input key: "))?; macro_rules! passwdfn { () => (|salt| passwd.as_ref().map(|string| crypto::password::Password::derive(string, salt))) } // read from `path` use config::op::KeyFormat; let aesbody = match resolve::find_key_format(&path, false).await .wrap_err(eyre!("Failed to detect file format for key")) .with_section(|| format!("{:?}", path.as_ref()).header("Path was")) .with_suggestion(|| "Are you sure this file is valid?")? { #[cold] KeyFormat::PEM => unreachable!(), other => { let mut file = OpenOptions::new() .read(true) .open(path).await .wrap_err(eyre!("Failed to open file for reading a second time.")) .with_suggestion(|| "Has the file just been/is being modified as we are reading it?") .with_section(|| format!("{:?}", other).header("File format was successfully detected as"))?; match other { KeyFormat::Bin => { let sh = format::SuperHeader::::read_bytes(&mut file, passwdfn!()).await .wrap_err(eyre!("Failed to read key super-header"))?; trace!("Read super {:?}", sh); let h = format::key::KeyHeader::read_bytes(&mut file, passwdfn!()).await .wrap_err(eyre!("Failed to read key header"))?; trace!("Read header {:?}", h); format::key::aes::AesBody::read_bytes(&mut file, h.body_key()).await .wrap_err(eyre!("Failed to read key body"))? }, KeyFormat::Text => { let mut file = BufReader::new(file); let sh = format::SuperHeader::::read_text(&mut file, passwdfn!()).await .wrap_err(eyre!("Failed to read key super-header"))?; trace!("Read super {:?}", sh); let h = format::key::KeyHeader::read_text(&mut file, passwdfn!()).await .wrap_err(eyre!("Failed to read key header"))?; trace!("Read header {:?}", h); format::key::aes::AesBody::read_text(&mut file, h.body_key()).await .wrap_err(eyre!("Failed to read key body"))? }, #[cold] _ => unreachable!(), } }, }; debug!("Read body {:?}", aesbody); Ok(aesbody) }