summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-05-29 11:40:03 +0300
committerLars Wirzenius <liw@liw.fi>2021-05-31 16:40:32 +0300
commitcccb998288d05273d709cda75766928e052cca2a (patch)
treef390fecc8a296ba2ff0c02a966b1ebdb3b80929f
parent7a88987b3c10c81845fce749b7b86b62770aecca (diff)
downloadobnam2-cccb998288d05273d709cda75766928e052cca2a.tar.gz
feat: add subcommands for encrypting, decrypting individual chunks
-rw-r--r--src/cmd/chunk.rs64
-rw-r--r--src/cmd/mod.rs1
-rw-r--r--subplot/data.py16
-rw-r--r--subplot/data.yaml6
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