You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
2.7 KiB

//! 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<Path>, passwd: (config::op::Password, Option<&str>)) -> eyre::Result<format::key::aes::AesBody>
{
// 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::<format::key::KeyHeader>::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::<format::key::KeyHeader>::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)
}