Skip to content

Commit

Permalink
Add output reencryption + refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
lbeder committed Jan 6, 2025
1 parent 6fa70ac commit f08492a
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 64 deletions.
70 changes: 49 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,9 @@ Checkpoint operations
Usage: slowkey checkpoint <COMMAND>

Commands:
show Print a checkpoint
restore Continue derivation process from an existing checkpoint
show Print a checkpoint
restore Continue derivation process from an existing checkpoint
reencrypt Reencrypt a checkpoint

Options:
-h, --help Print help
Expand All @@ -181,14 +182,14 @@ Options:
```sh
Print a checkpoint

Usage: slowkey checkpoint show [OPTIONS] --checkpoint <CHECKPOINT>
Usage: slowkey checkpoint show [OPTIONS] --path <PATH>

Options:
--checkpoint <CHECKPOINT> Path to an existing checkpoint
--verify Verify that the password and salt match the checkpoint
--base64 Show the result in Base64 (in addition to hex)
--base58 Show the result in Base58 (in addition to hex)
-h, --help Print help
--path <PATH> Path to an existing checkpoint
--verify Verify that the password and salt match the checkpoint
--base64 Show the result in Base64 (in addition to hex)
--base58 Show the result in Base58 (in addition to hex)
-h, --help Print help
```
#### Restoring from a Checkpoint
Expand All @@ -209,7 +210,7 @@ Options:
Frequency of saving encrypted checkpoints to disk, specified as the number of iterations between each save [default: 1]
--max-checkpoints-to-keep <MAX_CHECKPOINTS_TO_KEEP>
Specifies the number of most recent checkpoints to keep, while automatically deleting older ones [default: 1]
--checkpoint <CHECKPOINT>
--path <PATH>
Path to an existing checkpoint from which to resume the derivation process
--interactive
Input checkpoint data interactively (instead of providing the path to an existing checkpoint)
Expand All @@ -225,6 +226,19 @@ Options:
Print help
```
#### Reencrypting a Checkpoint
```sh
Reencrypt a checkpoint

Usage: slowkey checkpoint reencrypt --input <INPUT> --output <OUTPUT>

Options:
--input <INPUT> Path to an existing checkpoint
--output <OUTPUT> Path to the new checkpoint
-h, --help Print help
```
### Outputs
```sh
Expand All @@ -233,7 +247,8 @@ Output operations
Usage: slowkey output <COMMAND>

Commands:
show Print an output file
show Print an output file
reencrypt Reencrypt an output file

Options:
-h, --help Print help
Expand All @@ -244,13 +259,26 @@ Options:
```sh
Print an output file

Usage: slowkey output show [OPTIONS] --output <OUTPUT>
Usage: slowkey output show [OPTIONS] --path <PATH>

Options:
--path <PATH> Path to an existing output
--verify Verify that the password and salt match the output
--base64 Show the result in Base64 (in addition to hex)
--base58 Show the result in Base58 (in addition to hex)
-h, --help Print help
```
#### Reencrypting an Output
```sh
Reencrypt an output file

Usage: slowkey output reencrypt --input <INPUT> --output <OUTPUT>

Options:
--output <OUTPUT> Path to an existing output
--verify Verify that the password and salt match the output
--base64 Show the result in Base64 (in addition to hex)
--base58 Show the result in Base58 (in addition to hex)
--input <INPUT> Path to an existing output
--output <OUTPUT> Path to the new checkpoint
-h, --help Print help
```
Expand Down Expand Up @@ -458,7 +486,7 @@ We can see that the `checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4
Let's use the `checkpoint show` command to decrypt its contents and verify the parameters:
> slowkey checkpoint show --checkpoint ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
> slowkey checkpoint show --path ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
```sh
Please input all data either in raw or hex format starting with the 0x prefix
Expand All @@ -480,7 +508,7 @@ SlowKey Parameters:
We can also verify that the password and salt match the checkpoint by passing the optional `--verify` flag:
> slowkey checkpoint show --checkpoint ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0 --verify
> slowkey checkpoint show --path ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0 --verify
```sh
Please input all data either in raw or hex format starting with the 0x prefix
Expand Down Expand Up @@ -514,7 +542,7 @@ The password, salt and internal data are correct
Let's continue the derivation process from this checkpoint and verify that we arrive at the same final result as before. Please make sure to specify the correct number of iterations, as the checkpoint does not store the original iteration count.
> slowkey checkpoint restore -i 10 --checkpoint ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
> slowkey checkpoint restore -i 10 --path ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
```sh
Please input all data either in raw or hex format starting with the 0x prefix
Expand Down Expand Up @@ -570,7 +598,7 @@ Average iteration time: 2s 40ms
In addition to the above, you can use a checkpoint while specifying a larger iteration count. For example, if you originally ran 10,000 iterations and want to continue from checkpoint 9,000, you can set a higher iteration count, such as 100,000, when restoring from this checkpoint:
> slowkey checkpoint restore -i 20 --checkpoint ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
> slowkey checkpoint restore -i 20 --path ~/checkpoints/checkpoint.05.c33f06fe6bdaac774ab473181aa4fe46a3baadee4b8f4dc02be2248dea5308c0
```sh
Please input all data either in raw or hex format starting with the 0x prefix
Expand Down Expand Up @@ -771,7 +799,7 @@ Average iteration time: 2s 717ms
Let's use the `output show` command to decrypt its contents:
> slowkey output show --output ~/output.enc
> slowkey output show --path ~/output.enc
```sh
Output:
Expand All @@ -791,7 +819,7 @@ Fingerprint: E5E61F417790448A
The output file checkpoint, except for the one that coincides with the first iteration, also includes the output of the previous iteration. This allows the system to verify that the password and salt match the output by attempting to derive the output's data from the previous iteration's data. This verification is optional and requires the `--verify` flag:
> slowkey output show --output ~/output.enc --verify
> slowkey output show --path ~/output.enc --verify
```sh
Please input all data either in raw or hex format starting with the 0x prefix
Expand Down
59 changes: 36 additions & 23 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ enum CheckpointCommands {
#[command(about = "Print a checkpoint", arg_required_else_help = true)]
Show {
#[arg(long, help = "Path to an existing checkpoint")]
checkpoint: PathBuf,
path: PathBuf,

#[arg(long, help = "Verify that the password and salt match the checkpoint")]
verify: bool,
Expand Down Expand Up @@ -266,7 +266,7 @@ enum CheckpointCommands {
long,
help = "Path to an existing checkpoint from which to resume the derivation process"
)]
checkpoint: Option<PathBuf>,
path: Option<PathBuf>,

#[arg(
long,
Expand Down Expand Up @@ -303,7 +303,7 @@ enum CheckpointCommands {
#[command(about = "Reencrypt a checkpoint", arg_required_else_help = true)]
Reencrypt {
#[arg(long, help = "Path to an existing checkpoint")]
checkpoint: PathBuf,
input: PathBuf,

#[arg(long, help = "Path to the new checkpoint")]
output: PathBuf,
Expand All @@ -315,7 +315,7 @@ enum OutputCommands {
#[command(about = "Print an output file", arg_required_else_help = true)]
Show {
#[arg(long, help = "Path to an existing output")]
output: PathBuf,
path: PathBuf,

#[arg(long, help = "Verify that the password and salt match the output")]
verify: bool,
Expand All @@ -334,6 +334,15 @@ enum OutputCommands {
)]
base58: bool,
},

#[command(about = "Reencrypt an output file", arg_required_else_help = true)]
Reencrypt {
#[arg(long, help = "Path to an existing output")]
input: PathBuf,

#[arg(long, help = "Path to the new checkpoint")]
output: PathBuf,
},
}

const BENCHMARKS_DIRECTORY: &str = "benchmarks";
Expand Down Expand Up @@ -1033,18 +1042,15 @@ fn main() {

Commands::Checkpoint(cmd) => match cmd {
CheckpointCommands::Show {
checkpoint,
path,
verify,
base64,
base58,
} => {
print_input_instructions();

let file_key = get_file_key();
let checkpoint_data = Checkpoint::open(&OpenCheckpointOptions {
key: file_key,
path: checkpoint,
});
let checkpoint_data = Checkpoint::open(&OpenCheckpointOptions { key: file_key, path });

checkpoint_data.print(DisplayOptions {
base64,
Expand Down Expand Up @@ -1072,7 +1078,7 @@ fn main() {
checkpoint_dir,
checkpoint_interval,
max_checkpoints_to_keep,
checkpoint,
path,
interactive,
base64,
base58,
Expand All @@ -1083,7 +1089,7 @@ fn main() {

let mut file_key: Option<Vec<u8>> = None;

let checkpoint_data = match checkpoint {
let checkpoint_data = match path {
Some(path) => {
let key = get_file_key();
file_key = Some(key.clone());
Expand Down Expand Up @@ -1127,7 +1133,7 @@ fn main() {
});
},

CheckpointCommands::Reencrypt { checkpoint, output } => {
CheckpointCommands::Reencrypt { input, output } => {
print_input_instructions();

let key = get_file_key();
Expand All @@ -1136,30 +1142,23 @@ fn main() {

let new_key = get_file_key();

Checkpoint::reencrypt(&checkpoint, key, &output, new_key);
Checkpoint::reencrypt(&input, key, &output, new_key);

println!(
"Reencrypted checkpoint at \"{}\" and saved at \"{}\"",
checkpoint.to_string_lossy(),
output.to_string_lossy()
);
println!("Saved new checkpoint at \"{}\"", output.to_string_lossy());
},
},

Commands::Output(cmd) => match cmd {
OutputCommands::Show {
output,
path,
verify,
base64,
base58,
} => {
print_input_instructions();

let file_key = get_file_key();
let output_data = Output::get(&OpenOutputOptions {
key: file_key,
path: output,
});
let output_data = Output::open(&OpenOutputOptions { key: file_key, path });

output_data.print(DisplayOptions {
base64,
Expand All @@ -1180,6 +1179,20 @@ fn main() {
println!("The password, salt and internal data are correct\n");
}
},

OutputCommands::Reencrypt { input, output } => {
print_input_instructions();

let key = get_file_key();

println!("Please provide the new file encryption key:\n");

let new_key = get_file_key();

Output::reencrypt(&input, key, &output, new_key);

println!("Saved new output at \"{}\"", output.to_string_lossy());
},
},

Commands::Bench {} => {
Expand Down
27 changes: 9 additions & 18 deletions src/utils/checkpoints/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl Checkpoint {
},
};

self.store(&checkpoint_path, &checkpoint);
self.save(&checkpoint_path, &checkpoint);

self.data = CheckpointData {
version: Version::V2,
Expand Down Expand Up @@ -305,7 +305,7 @@ impl Checkpoint {
}
}

fn store(&mut self, checkpoint_path: &Path, checkpoint: &CheckpointData) {
fn save(&mut self, checkpoint_path: &Path, checkpoint: &CheckpointData) {
let file = File::create(checkpoint_path).unwrap();
let mut writer = BufWriter::new(file);

Expand All @@ -328,29 +328,20 @@ impl Checkpoint {
self.checkpoint_paths.push_back(checkpoint_path.to_path_buf());
}

pub fn reencrypt(checkpoint_path: &Path, key: Vec<u8>, output_path: &Path, new_key: Vec<u8>) {
if !checkpoint_path.exists() {
panic!(
"Input checkpoint path \"{}\" does not exist",
checkpoint_path.to_string_lossy()
);
pub fn reencrypt(input_path: &Path, key: Vec<u8>, output_path: &Path, new_key: Vec<u8>) {
if !input_path.exists() {
panic!("Input path \"{}\" does not exist", input_path.to_string_lossy());
}

if checkpoint_path.is_dir() {
panic!(
"Input checkpoint path \"{}\" is a directory",
checkpoint_path.to_string_lossy()
);
if input_path.is_dir() {
panic!("Input path \"{}\" is a directory", input_path.to_string_lossy());
}

if output_path.exists() {
panic!(
"Output checkpoint path \"{}\" already exists",
output_path.to_string_lossy()
);
panic!("Output path \"{}\" already exists", output_path.to_string_lossy());
}

let checkpoint_file = File::open(checkpoint_path).unwrap();
let checkpoint_file = File::open(input_path).unwrap();
let mut reader = BufReader::new(checkpoint_file);

// Read the first byte (version)
Expand Down
Loading

0 comments on commit f08492a

Please sign in to comment.