diff --git a/Cargo.lock b/Cargo.lock index 34f452ed..c624f55d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,55 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -125,6 +174,52 @@ dependencies = [ "inout", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -593,6 +688,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "libc" version = "0.2.155" @@ -655,6 +756,7 @@ dependencies = [ "awesome-glib", "awesome-gtk", "cbc", + "clap", "deflate", "embed-resource", "futures", @@ -817,6 +919,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.66" @@ -924,6 +1032,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version-compare" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 338eb4b7..eedde872 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "LGPL-3.0-or-later" description = "Password storing program" readme = "README.md" +default-run = "password-storage" [dependencies] futures = "0.3" @@ -26,6 +27,8 @@ gtk = { package = "gtk4", version = "0.8", features = ["v4_12"] } awesome-glib = "0.4" awesome-gtk = "0.4" +clap = { version = "4.5.4", features = ["derive"] } + [build-dependencies] glib-build-tools = "0.19" diff --git a/src/bin/revelation-decode.rs b/src/bin/revelation-decode.rs new file mode 100644 index 00000000..09331d70 --- /dev/null +++ b/src/bin/revelation-decode.rs @@ -0,0 +1,41 @@ +use clap::Parser; +use password_storage::format::revelation; +use std::error::Error; +use std::fs; +use std::io::{stdin, stdout, BufReader, Write}; +use std::path::PathBuf; + +#[derive(Parser)] +struct Opts { + /// Input file + input: PathBuf, + + /// Input file + output: PathBuf, +} + +fn main() -> Result<(), Box<dyn Error>> { + let opts = Opts::parse(); + + print!("Enter a password for a file {}: ", opts.input.display()); + stdout().flush()?; + + let mut password = String::new(); + stdin().read_line(&mut password)?; + println!(""); + + let file = fs::OpenOptions::new().read(true).open(&opts.input)?; + let mut buffer = BufReader::new(file); + + let data = revelation::decrypt_revelation_file(&mut buffer, &password.trim())?; + + fs::write(&opts.output, data.content)?; + + println!( + "Output file: {}\nData format: {:?}\nDone", + opts.output.display(), + data.format + ); + + Ok(()) +} diff --git a/src/format/revelation/mod.rs b/src/format/revelation/mod.rs index ed08aa34..78d029a8 100644 --- a/src/format/revelation/mod.rs +++ b/src/format/revelation/mod.rs @@ -26,7 +26,8 @@ impl CryptoContainer { } } -enum SerializationFormat { +#[derive(Debug)] +pub enum SerializationFormat { Xml, } @@ -51,7 +52,12 @@ fn version_impl(version: u8) -> Option<(CryptoContainer, SerializationFormat)> { } } -pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<RecordTree> { +pub struct Decrypted { + pub format: SerializationFormat, + pub content: Vec<u8>, +} + +pub fn decrypt_revelation_file(source: &mut dyn Read, password: &str) -> Result<Decrypted> { let header = file_header::FileHeader::read(source)?; let (container, format) = version_impl(header.data_version).ok_or_else(|| { format!( @@ -59,8 +65,13 @@ pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<Rec header.data_version, header.app_version ) })?; - let decrypted = container.decrypt(source, password)?; - let tree = format.deserialize(&decrypted)?; + let content = container.decrypt(source, password)?; + Ok(Decrypted { format, content }) +} + +pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<RecordTree> { + let Decrypted { format, content } = decrypt_revelation_file(source, password)?; + let tree = format.deserialize(&content)?; Ok(tree) }