diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-05-29 11:40:03 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-05-31 16:40:32 +0300 |
commit | cccb998288d05273d709cda75766928e052cca2a (patch) | |
tree | f390fecc8a296ba2ff0c02a966b1ebdb3b80929f | |
parent | 7a88987b3c10c81845fce749b7b86b62770aecca (diff) | |
download | obnam2-cccb998288d05273d709cda75766928e052cca2a.tar.gz |
feat: add subcommands for encrypting, decrypting individual chunks
-rw-r--r-- | src/cmd/chunk.rs | 64 | ||||
-rw-r--r-- | src/cmd/mod.rs | 1 | ||||
-rw-r--r-- | subplot/data.py | 16 | ||||
-rw-r--r-- | subplot/data.yaml | 6 |
4 files changed, 87 insertions, 0 deletions
diff --git a/src/cmd/chunk.rs b/src/cmd/chunk.rs new file mode 100644 index 0000000..e0e91b1 --- /dev/null +++ b/src/cmd/chunk.rs @@ -0,0 +1,64 @@ +use crate::chunk::DataChunk; +use crate::chunkmeta::ChunkMeta; +use crate::cipher::CipherEngine; +use crate::config::ClientConfig; +use crate::error::ObnamError; +use std::path::PathBuf; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +pub struct EncryptChunk { + #[structopt(parse(from_os_str))] + filename: PathBuf, + + #[structopt(parse(from_os_str))] + output: PathBuf, + + #[structopt()] + json: String, +} + +impl EncryptChunk { + pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> { + let pass = config.passwords()?; + let cipher = CipherEngine::new(&pass); + + let meta = ChunkMeta::from_json(&self.json)?; + + let cleartext = std::fs::read(&self.filename)?; + let chunk = DataChunk::new(cleartext, meta); + let encrypted = cipher.encrypt_chunk(&chunk)?; + + std::fs::write(&self.output, encrypted.ciphertext())?; + + Ok(()) + } +} + +#[derive(Debug, StructOpt)] +pub struct DecryptChunk { + #[structopt(parse(from_os_str))] + filename: PathBuf, + + #[structopt(parse(from_os_str))] + output: PathBuf, + + #[structopt()] + json: String, +} + +impl DecryptChunk { + pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> { + let pass = config.passwords()?; + let cipher = CipherEngine::new(&pass); + + let meta = ChunkMeta::from_json(&self.json)?; + + let encrypted = std::fs::read(&self.filename)?; + let chunk = cipher.decrypt_chunk(&encrypted, &meta.to_json_vec())?; + + std::fs::write(&self.output, chunk.data())?; + + Ok(()) + } +} diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 890e176..bd101da 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,4 +1,5 @@ pub mod backup; +pub mod chunk; pub mod get_chunk; pub mod init; pub mod list; diff --git a/subplot/data.py b/subplot/data.py index d134e5f..13b6d2b 100644 --- a/subplot/data.py +++ b/subplot/data.py @@ -170,3 +170,19 @@ def file_is_readable_by_owner(ctx, filename=None): def file_does_not_contain(ctx, filename=None, pattern=None): data = open(filename).read() assert pattern not in data + + +def files_are_different(ctx, filename1=None, filename2=None): + assert_ne = globals()["assert_ne"] + + data1 = open(filename1, "rb").read() + data2 = open(filename2, "rb").read() + assert_ne(data1, data2) + + +def files_are_identical(ctx, filename1=None, filename2=None): + assert_eq = globals()["assert_eq"] + + data1 = open(filename1, "rb").read() + data2 = open(filename2, "rb").read() + assert_eq(data1, data2) diff --git a/subplot/data.yaml b/subplot/data.yaml index dcc6807..41a563f 100644 --- a/subplot/data.yaml +++ b/subplot/data.yaml @@ -48,3 +48,9 @@ - then: "file {filename} does not contain \"{pattern:text}\"" function: file_does_not_contain + +- then: "files {filename1} and {filename2} are different" + function: files_are_different + +- then: "files {filename1} and {filename2} are identical" + function: files_are_identical |