From 5b0c4e7ae06e06178ab5ce4d1ad15c24ac4c8f22 Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 29 Oct 2020 14:36:20 +0000 Subject: [PATCH] read aes container --- src/container/aes.rs | 67 +++++++++++++++++++++++++++++++++++++++++++ src/container/mod.rs | 4 +++ src/format/key/mod.rs | 1 + src/main.rs | 6 ++-- 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/container/aes.rs create mode 100644 src/container/mod.rs diff --git a/src/container/aes.rs b/src/container/aes.rs new file mode 100644 index 0000000..aad1b82 --- /dev/null +++ b/src/container/aes.rs @@ -0,0 +1,67 @@ +//! 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) -> eyre::Result +{ + // password function + let passwd = passwd.into_password()?; + 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) +} diff --git a/src/container/mod.rs b/src/container/mod.rs new file mode 100644 index 0000000..a9f2e4b --- /dev/null +++ b/src/container/mod.rs @@ -0,0 +1,4 @@ +//! File containers reading + writing. +use super::*; + +pub mod aes; diff --git a/src/format/key/mod.rs b/src/format/key/mod.rs index b613ca1..0a06d6b 100644 --- a/src/format/key/mod.rs +++ b/src/format/key/mod.rs @@ -123,6 +123,7 @@ impl TryFrom for KeyHeaderKind } +/// Header for all keys #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)] pub struct KeyHeader { diff --git a/src/main.rs b/src/main.rs index dbc4551..25f4745 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use std::{ }; use color_eyre::{ eyre::{ + eyre, self, WrapErr, }, @@ -99,6 +100,7 @@ mod resolve; mod args; mod format; +mod container; mod work; pub mod timestamp @@ -191,11 +193,9 @@ async fn work(op: config::Operation) -> Result<(), eyre::Report> config::Operation::GenerateKey(config::op::GenerateKey::Aes(aes)) => { let input_aes = match aes.input { Some((path, passwd)) => { - let passwd = passwd.into_password()?; - // read from `path` }, - _ => None, + _ => (), }; }, config::Operation::GenerateKey(config::op::GenerateKey::Rsa(rsa)) => {