#![cfg_attr(nightly, feature(label_break_value))] #![cfg_attr(nightly, feature(const_fn))] #![cfg_attr(nightly, feature(const_fn_transmute))] #![cfg_attr(nightly, feature(never_type))] #![cfg_attr(nightly, feature(test))] #![cfg_attr(nightly, feature(untagged_unions))] #![allow(dead_code)] #![allow(unused_macros)] #[macro_use] extern crate tracing; #[macro_use] extern crate pin_project; #[cfg(nightly)] extern crate test; //#[macro_use] extern crate async_trait; use std::{ convert::{TryFrom, TryInto}, }; use color_eyre::{ eyre::{ eyre, self, WrapErr, }, Help, SectionExt, }; use lazy_static::lazy_static; use serde::{Serialize, Deserialize}; use tracing_futures::Instrument; use futures::{ future::{ FutureExt as _, BoxFuture, LocalBoxFuture, }, }; use serialise::{ TextSerialiseable as _, BinarySerialisable as _, Serialisable as _, }; macro_rules! cfg_debug { (if {$($if:tt)*} else {$($else:tt)*}) => { { cfg_if::cfg_if!{ if #[cfg(debug_assertions)] { $($if)* } else { $($else)* } } } }; } macro_rules! nightly { (else $($else:tt)*) => { cfg_if::cfg_if! { if #[cfg(not(nightly))] { $($else)* } } }; (if {$($if:tt)*} else {$($else:tt)*}) => { cfg_if::cfg_if!{ if #[cfg(nightly)] { $($if)* } else { $($else)* } } }; ($($tt:tt)*) => { cfg_if::cfg_if! { if #[cfg(nightly)] { $($tt)* } } } } macro_rules! static_assert { ($expr:expr) => { const _: [(); 1] = [(); ((!!$expr) as bool) as usize]; }; ($expr:expr, $lit:literal) => { static_assert!{$expr} } } pub const CURRENT_VERSION: version::Version = version::Version::new(0,0,0,version::Tag::Prerelease); mod bytes; mod ext; use ext::*; mod version; mod config; mod resolve; mod args; mod format; mod container; mod work; pub mod timestamp { use chrono::prelude::*; /// Get the current timestamp pub fn now() -> i64 { #[cfg(feature="local-time")] return Local::now().timestamp(); #[cfg(not(feature="local-time"))] Utc::now().timestamp() } } pub mod serialise; /*/// Dispatch params operations that can be handled at top level (i.e. `Help`) async fn dispatch_args() -> Result { match args::parse_args().await .with_section(move || std::env::args().skip(1).join("\n").header("Input args were:"))? { } }*/ fn install_tracing() { use tracing_error::ErrorLayer; use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; let fmt_layer = fmt::layer().with_target(false); let filter_layer = EnvFilter::try_from_default_env() .or_else(|_| EnvFilter::try_new("info")) .unwrap(); tracing_subscriber::registry() .with(filter_layer) .with(fmt_layer) .with(ErrorLayer::default()) .init(); } #[instrument] async fn fuck() -> eyre::Result<()> { use format::*; use format::key::*; use crypto::password::Password; let header = KeyHeader::new_now(KeyHeaderKind::Aes, config::op::KeyDescription{ name: "Name!".to_owned(), description: "Some description".to_owned(), ..Default::default() }, Default::default()); let body = key::aes::AesBody::new_key(crypto::aes::AesKey::generate().unwrap()); let mut ser = Vec::new(); let password = "hello world. I am a password"; let superheader = SuperHeader::::new_for(&header); println!("Writing: {:?}\n\t{:?}\n\t{:?}", superheader, header, body); let mut written = superheader.write_text(&mut ser, |salt| Some(Password::derive(password, salt.as_ref()))).await?; ser.extend(header.into_memory(serialise::Mode::Text, |salt| Some(Password::derive(password, salt.as_ref())))?); //header.write_text(&mut ser).await?; written += body.write_text(&mut ser, header.body_key()).await?; println!("Wrote {} bytes", written); println!("{}\n", ser.fmt_view()); println!("As text:\n{}\n", ser.fmt_ascii()); let mut read = &ser[..]; let (reads, readn) = SuperHeader::from_memory(&mut read, serialise::Mode::Text, |salt| Some(Password::derive(password, salt)))?; // SuperHeader::read_text(read).await?; let mut read = &read[readn..]; println!("Read super: {:?}", reads); let readheader = KeyHeader::read_text(&mut read, |salt| Some(Password::derive(password, salt))).await?; println!("Read real: {:?}", readheader); let readbody = key::aes::AesBody::read_text(&mut read, readheader.body_key()).await?; println!("Read body: {:?}", readbody); reads.verify_for(&header)?; reads.verify_for(&readheader)?; assert_eq!(readheader, header); assert_eq!(reads, superheader); assert_eq!(readbody, body); info!("All okay!"); Ok(()) } #[instrument] async fn work(op: config::Operation) -> Result<(), eyre::Report> { debug!("Got op"); match op { config::Operation::Help => args::usage(), config::Operation::GenerateKey(config::op::GenerateKey::Aes(aes)) => { // read input aes key if provided let input_aes = match aes.input { Some((path, passwd)) => { Some(container::aes::read_aes_container(&path, (passwd, None)).await .wrap_err(eyre!("Failed to read input AES container from file")) .with_section(|| format!("{:?}", path).header("Path was"))?) }, _ => None, }; //TODO: Generate new key //TODO: Save new key to file, in provided format, with password if needed }, config::Operation::GenerateKey(config::op::GenerateKey::Rsa(rsa)) => { }, _ => todo!(), } Ok(()) } #[instrument] #[tokio::main] async fn main() -> Result<(), eyre::Report> { install_tracing(); color_eyre::install()?; //fuck().await?; //return Ok(()); trace!("Parsing args"); let args = args::parse_args().await?; work(args).await .with_suggestion(|| "Run with `RUST_LOG=\"debug\"` environment variable for more detailed logging") .with_suggestion(|| "Run with `RUST_LOG=\"trace\"` environment variable for extremely detailed logging")?; Ok(()) }