From 5ffe081eacd21a07ad37c90260b7f36d25552aca Mon Sep 17 00:00:00 2001 From: lbeder Date: Thu, 24 Oct 2024 15:16:32 +0100 Subject: [PATCH] Include iteration number as an input in every step --- README.md | 137 ++++++++++++++++++++-------- src/main.rs | 44 ++++++--- src/slowkey.rs | 48 +++++----- src/utils/checkpoints/checkpoint.rs | 4 +- src/utils/outputs/output.rs | 6 +- 5 files changed, 162 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 0602256..81e4f4b 100755 --- a/README.md +++ b/README.md @@ -42,17 +42,15 @@ The SlowKey Key Derivation Scheme is defined as follows: function deriveKey(password, salt, iterations): previousResult = "" - for i from 1 to iterations: - step1 = SHA2(concatenate(previousResult, salt, password)) - step2 = SHA3(concatenate(step1, salt, password)) - step3 = Scrypt(step2, salt) - step4 = SHA2(concatenate(step3, salt, password)) - step5 = SHA3(concatenate(step4, salt, password)) - step6 = Argon2id(step5, salt) + for iteration from 1 to iterations: + step1 = SHA2(concatenate(previousResult, salt, password, iteration)) + step2 = SHA3(concatenate(step1, salt, password, iteration)) + step3 = Scrypt(concatenate(step2, salt, password, iteration), salt) + step4 = SHA2(concatenate(step3, salt, password, iteration)) + step5 = SHA3(concatenate(step4, salt, password, iteration)) + step6 = Argon2id(concatenate(step5, salt, password, iteration), salt) previousResult = step6 - finalStep1 = SHA2(concatenate(previousResult, salt, password)) - finalKey = truncate(previousResult, keySize) return finalKey @@ -208,7 +206,7 @@ Final result: ████████████████████████████████████████████████████████████████████████████████ 10/10 100% (0s) -Key is (please highlight to see): 0xc0255d3609a46c269de09a8a35372c3bd8ab4aad41d51125579364510c8ff96e +Key is (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 Start time: 2024-09-18 18:57:34 End time: 2024-09-18 18:58:26 @@ -235,7 +233,7 @@ The tool also supports the creation of periodic checkpoints, which are securely Please note that even if the last checkpoint is done at the final iteration (in the case that the number of iterations divides by the check-pointing interval), the checkpoint still won't have the actual output until you complete the recovery process. -Each 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, when restoring from a checkpoint, that the password and salt match the checkpoint by attempting to derive the checkpoint's iteration data from the previous iteration's data. +Each 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 checkpoint by attempting to derive the checkpoint's iteration data from the previous iteration's data. Please exercise caution when using this feature. Resuming computation from a compromised checkpoint may undermine your expectations regarding the duration of the key stretching process. @@ -262,16 +260,16 @@ SlowKey Parameters: ✔ Enter your password · ******** -████████████████████████████████████████████████████████████████░░░░░░░░░░░░░░░░ 8/10 80% (10s) +████████████████████████████████████████████████████████████████░░░░░░░░░░░░░░░░ 5/10 80% (10s) -Created checkpoint #5 with data hash (salted) 0x2706f2dca6d2f5a3870d9b8c66451662ec5d4da3a8a638f1e3cfbc83725107af +Created checkpoint #5 with data hash (salted) 0x1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc ``` -We can see that the `checkpoint.05.2706f2dca6d2f5a3870d9b8c66451662ec5d4da3a8a638f1e3cfbc83725107af` was retained in the `~/checkpoints` directory. Please note that file name contains iteration the checkpoint was taken at and a salted hash of the data. +We can see that the `checkpoint.05.1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc` was retained in the `~/checkpoints` directory. Please note that file name contains iteration the checkpoint was taken at and a salted hash of the data. Let's use the `show-checkpoint` command to decrypt its contents and verify the parameters: -> slowkey show-checkpoint --checkpoint ~/checkpoints/checkpoint.05.2706f2dca6d2f5a3870d9b8c66451662ec5d4da3a8a638f1e3cfbc83725107af +> slowkey show-checkpoint --checkpoint ~/checkpoints/checkpoint.05.1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc ```sh Please input all data either in raw or hex format starting with the 0x prefix @@ -281,18 +279,47 @@ Please input all data either in raw or hex format starting with the 0x prefix Checkpoint: Version: 1: Iteration: 5: - Data (please highlight to see): 0xaa9e712a3a5d83c5369bd0d31b319f24b552dcef1b429f019c82c660d4947869 - Previous Iteration's Data (please highlight to see): 0x0abf29286d3c398904ab055ae6389a599bae2c75ad233216f44a8ffb02dc46d7 + Data (please highlight to see): 0x394097ab2a70d59caf6f4f950830ba86fe7593b762a763705631b9752341d879 + Previous Iteration's Data (please highlight to see): 0xf4d0306c5e72f644526e8d663b4b62209287238cce22fab0868e96acdaa9b8a1 + +SlowKey Parameters: + Length: 32 + Scrypt: (n: 1048576, r: 8, p: 1) + Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) +``` + +We can also verify that the password and salt match the checkpoint by passing the optional `--verify` flag: + +> slowkey show-checkpoint --checkpoint ~/checkpoints/checkpoint.05.1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc --verify + +```sh +Please input all data either in raw or hex format starting with the 0x prefix + +✔ Enter your checkpoint/output encryption key · ******** + +Checkpoint: + Version: 1: + Iterations: 5: + Data (please highlight to see): 0x394097ab2a70d59caf6f4f950830ba86fe7593b762a763705631b9752341d879 + Previous Iteration's Data (please highlight to see): 0xf4d0306c5e72f644526e8d663b4b62209287238cce22fab0868e96acdaa9b8a1 SlowKey Parameters: Length: 32 Scrypt: (n: 1048576, r: 8, p: 1) Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) + +✔ Enter your salt · ******** + +✔ Enter your password · ******** + +Verifying the checkpoint... + +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 derive -i 10 --restore-from-checkpoint ~/checkpoints/checkpoint.05.2706f2dca6d2f5a3870d9b8c66451662ec5d4da3a8a638f1e3cfbc83725107af +> slowkey derive -i 10 --restore-from-checkpoint ~/checkpoints/checkpoint.05.1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc ```sh @@ -302,9 +329,9 @@ Please input all data either in raw or hex format starting with the 0x prefix Checkpoint: Version: 1: - Iteration: 5: - Data (please highlight to see): 0xaa9e712a3a5d83c5369bd0d31b319f24b552dcef1b429f019c82c660d4947869 - Previous Iteration's Data (please highlight to see): 0x0abf29286d3c398904ab055ae6389a599bae2c75ad233216f44a8ffb02dc46d7 + Iterations: 5: + Data (please highlight to see): 0x394097ab2a70d59caf6f4f950830ba86fe7593b762a763705631b9752341d879 + Previous Iteration's Data (please highlight to see): 0xf4d0306c5e72f644526e8d663b4b62209287238cce22fab0868e96acdaa9b8a1 SlowKey Parameters: Iterations: 10 @@ -316,7 +343,9 @@ SlowKey Parameters: ✔ Enter your password · ******** -Verifying checkpoint... +Verifying the checkpoint... + +The password, salt and internal data are correct ████████████████████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5/10 50% (4s) @@ -327,7 +356,7 @@ Final result: ```sh ████████████████████████████████████████████████████████████████████████████████ 10/10 100% (0s) -Key is (please highlight to see): 0xc0255d3609a46c269de09a8a35372c3bd8ab4aad41d51125579364510c8ff96e +Key is (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 Start time: 2024-09-18 19:00:59 End time: 2024-09-18 19:01:25 @@ -336,9 +365,7 @@ Total running time: 25s 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 derive -i 20 --restore-from-checkpoint ~/checkpoints/checkpoint.05.2706f2dca6d2f5a3870d9b8c66451662ec5d4da3a8a638f1e3cfbc83725107af - -TODO: +> slowkey derive -i 20 --restore-from-checkpoint ~/checkpoints/checkpoint.05.1d63a329b6bd1ab1199ee8d72b65e38e30cb129001436cc8ec8645329b0176dc ```sh Please input all data either in raw or hex format starting with the 0x prefix @@ -347,9 +374,9 @@ Please input all data either in raw or hex format starting with the 0x prefix Checkpoint: Version: 1: - Iteration: 5: - Data (please highlight to see): 0xaa9e712a3a5d83c5369bd0d31b319f24b552dcef1b429f019c82c660d4947869 - Previous Iteration's Data (please highlight to see): 0x0abf29286d3c398904ab055ae6389a599bae2c75ad233216f44a8ffb02dc46d7 + Iterations: 5: + Data (please highlight to see): 0x394097ab2a70d59caf6f4f950830ba86fe7593b762a763705631b9752341d879 + Previous Iteration's Data (please highlight to see): 0xf4d0306c5e72f644526e8d663b4b62209287238cce22fab0868e96acdaa9b8a1 SlowKey Parameters: Iterations: 20 @@ -361,7 +388,9 @@ SlowKey Parameters: ✔ Enter your password · ******** -Verifying checkpoint... +Verifying the checkpoint... + +The password, salt and internal data are correct ████████████████████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5/20 50% (56s) ``` @@ -371,7 +400,7 @@ Final result: ```sh ████████████████████████████████████████████████████████████████████████████████ 20/20 100% (0s) -Key is (please highlight to see): 0x68c470bd2c478cc8a46af74af2faaa0171542acd9b97f1d8eaaf98f9122894a8 +Key is (please highlight to see): 0x07eee820a3f92c5577dedd07e7d325dc58bb1064f9ae05af30be9863ec6e7354 Start time: 2024-09-18 19:00:59 End time: 2024-09-18 19:01:25 @@ -399,9 +428,9 @@ SlowKey Parameters: ████████████████████████████████████████████████████████████████████████████████ 10/10 100% (0s) -Key is (please highlight to see): 0xc0255d3609a46c269de09a8a35372c3bd8ab4aad41d51125579364510c8ff96e -Key (base64) is (please highlight to see): wCVdNgmkbCad4JqKNTcsO9irSq1B1RElV5NkUQyP+W4 -Key (base58) is (please highlight to see): Dw4KjVFNSGXz3R1oG81KvmDVUyrdQ9QbHAQwp4iTcZXj +Key is (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 +Key (base64) is (please highlight to see): rZqgMSh7QvRcQKXK87PtR/eV2TFdIqtQolZSs/KmtxY+W4 +Key (base58) is (please highlight to see): CggHSjC3rpDdCGcbL2uB28qpFeBsWVsUMph1iGpbnDGy Start time: 2024-09-18 18:57:34 End time: 2024-09-18 18:58:26 @@ -429,7 +458,7 @@ SlowKey Parameters: ████████████████████████████████████████████████████████████████████████████████ 10/10 100% (0s) -Key is (please highlight to see): 0xc0255d3609a46c269de09a8a35372c3bd8ab4aad41d51125579364510c8ff96e +Key is (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 Saved encrypted output to "~/output.enc" @@ -444,14 +473,44 @@ Let's use the `show-output` command to decrypt its contents: ```sh Output: - Iteration: 10 - Data (please highlight to see): 0xc0255d3609a46c269de09a8a35372c3bd8ab4aad41d51125579364510c8ff96e + Iterations: 10 + Data (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 + Previous Iteration's Data (please highlight to see): 0x2645534232e84c83989d6dae3d93be851771c7c47852301b413147780215bd08 + +SlowKey Parameters: + Iterations: 10 + Length: 32 + Scrypt: (n: 1048576, r: 8, p: 1) + Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) +``` + +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 show-output --output ~/output.enc --verify + +```sh +Please input all data either in raw or hex format starting with the 0x prefix + +✔ Enter your checkpoint/output encryption key · ******** + +Output: + Iterations: 10 + Data (please highlight to see): 0xad9aa031287b42f45c40a5caf3b3ed47f795d9315d22ab50a25652b3f2a6b716 + Previous Iteration's Data (please highlight to see): 0x2645534232e84c83989d6dae3d93be851771c7c47852301b413147780215bd08 SlowKey Parameters: Iterations: 10 Length: 32 Scrypt: (n: 1048576, r: 8, p: 1) Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) + +✔ Enter your salt · ******** + +✔ Enter your password · ******** + +Verifying the output... + +The password, salt and internal data are correct ``` ## Test Vectors @@ -502,7 +561,7 @@ SlowKey Parameters: Length: 64 Scrypt: (n: 1048576, r: 8, p: 1) Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) -Derived key: 0x1805476033e579abf06772db32b52886e07d9c579c99be05dcc1826e2f162b5c4bf846b7fae13ac5e57991da69769f1d2aac2d9046b9c60cbce9af35b371d4bd +Derived key: 0xb2c1bcd2674c0c96473e61b17d6e30d6e8a46ac258f730075b476a732284c64e36df041f7bd50260d68128b62e6cffac03e4ff585025d18b04d41dda4633b800 Salt: "SlowKeySlowKey16" Password: "Hello World" @@ -511,7 +570,7 @@ SlowKey Parameters: Length: 64 Scrypt: (n: 1048576, r: 8, p: 1) Argon2id: (version: 19, m_cost: 2097152, t_cost: 2) -Derived key: 0xedada70cd27e31ddcfc41edba2f63a03418fc1acd352ff78eff149573c5e247f0e06850cf03dc50dd9eef63275061cb85cdff8b47c3593d749145f1a226e8b7b +Derived key: 0xe24c16e6912d2348e8be84977d22bd229382b72b65b501afe0066a32d6771df57f3557de0719070bbafb8faf1d0649562be693e3bf33c6e0a107d0af712030ef ``` ## License diff --git a/src/main.rs b/src/main.rs index 8d20c95..10d0fee 100755 --- a/src/main.rs +++ b/src/main.rs @@ -157,6 +157,9 @@ enum Commands { ShowCheckpoint { #[arg(long, help = "Path to an existing checkpoint")] checkpoint: PathBuf, + + #[arg(long, help = "Verify that the password and salt match the checkpoint")] + verify: bool, }, #[command(about = "Decrypt an output file")] @@ -455,14 +458,14 @@ fn main() { let password = get_password(); if let Some(checkpoint_data) = restore_from_checkpoint_data { - if checkpoint_data.data.iteration > 0 { - println!("Verifying the checkpoint..."); + println!("Verifying the checkpoint...\n"); + if checkpoint_data.data.iteration > 0 { if !checkpoint_data.verify(&salt, &password) { - panic!("The password or salt provided for the checkpoint is incorrect!"); + panic!("The password, salt, or internal data is incorrect!"); } - println!(); + println!("The password, salt and internal data are correct\n"); } else { println!("{}: Unable to verify the first checkpoint\n", "Warning".dark_yellow()); } @@ -609,7 +612,7 @@ fn main() { ); }, - Some(Commands::ShowCheckpoint { checkpoint }) => { + Some(Commands::ShowCheckpoint { checkpoint, verify }) => { println!( "Please input all data either in raw or hex format starting with the {} prefix\n", HEX_PREFIX @@ -624,6 +627,23 @@ fn main() { println!("{}\n", &checkpoint_data); println!("{}\n", &checkpoint_data.data.slowkey); + + if verify { + let salt = get_salt(); + let password = get_password(); + + println!("Verifying the checkpoint...\n"); + + if checkpoint_data.data.iteration > 0 { + if !checkpoint_data.verify(&salt, &password) { + panic!("The password, salt, or internal data is incorrect!"); + } + + println!("The password, salt and internal data are correct\n"); + } else { + println!("{}: Unable to verify the first checkpoint\n", "Warning".dark_yellow()); + } + } }, Some(Commands::ShowOutput { output, verify }) => { @@ -639,18 +659,21 @@ fn main() { path: output, }); + println!("{}\n", &output_data); + println!("{}\n", &output_data.data.slowkey); + if verify { let salt = get_salt(); let password = get_password(); - if output_data.data.iteration > 0 { - println!("Verifying the output..."); + println!("Verifying the output...\n"); + if output_data.data.iteration > 0 { if !output_data.verify(&salt, &password) { - panic!("The password or salt provided for the output is incorrect!"); + panic!("The password, salt, or internal data is incorrect!"); } - println!(); + println!("The password, salt and internal data are correct\n"); } else { println!( "{}: Unable to verify the output of the first iteration checkpoint\n", @@ -658,9 +681,6 @@ fn main() { ); } } - - println!("{}\n", &output_data); - println!("{}\n", &output_data.data.slowkey); }, Some(Commands::Test {}) => { diff --git a/src/slowkey.rs b/src/slowkey.rs index da3e80a..b289232 100755 --- a/src/slowkey.rs +++ b/src/slowkey.rs @@ -164,17 +164,19 @@ impl SlowKey { }; for i in offset..self.iterations { + let iteration = i as u64; + // Calculate the SHA2 and SHA3 hashes of the result and the inputs - self.double_hash(salt, password, &mut res); + self.double_hash(salt, password, iteration, &mut res); // Calculate the Scrypt hash of the result and the inputs - self.scrypt(salt, password, &mut res); + self.scrypt(salt, password, iteration, &mut res); // Calculate the SHA2 and SHA3 hashes of the result and the inputs again - self.double_hash(salt, password, &mut res); + self.double_hash(salt, password, iteration, &mut res); // Calculate the Argon2 hash of the result and the inputs - self.argon2id(salt, password, &mut res); + self.argon2id(salt, password, iteration, &mut res); callback(i, &res); } @@ -188,10 +190,11 @@ impl SlowKey { self.derive_key_with_callback(salt, password, offset_data, offset, |_, _| {}) } - fn double_hash(&self, salt: &[u8], password: &[u8], res: &mut Vec) { + fn double_hash(&self, salt: &[u8], password: &[u8], iteration: u64, res: &mut Vec) { // Calculate the SHA2 hash of the result and the inputs res.extend_from_slice(salt); res.extend_from_slice(password); + res.extend_from_slice(&iteration.to_le_bytes()); let mut sha512 = Sha512::new(); sha512.update(&res); @@ -200,22 +203,25 @@ impl SlowKey { // Calculate the SHA3 hash of the result and the inputs res.extend_from_slice(salt); res.extend_from_slice(password); + res.extend_from_slice(&iteration.to_le_bytes()); let mut keccack512 = Keccak512::new(); keccack512.update(&res); *res = keccack512.finalize().to_vec(); } - fn scrypt(&self, salt: &[u8], password: &[u8], res: &mut Vec) { + fn scrypt(&self, salt: &[u8], password: &[u8], iteration: u64, res: &mut Vec) { res.extend_from_slice(salt); res.extend_from_slice(password); + res.extend_from_slice(&iteration.to_le_bytes()); *res = self.scrypt.hash(salt, res); } - fn argon2id(&self, salt: &[u8], password: &[u8], res: &mut Vec) { + fn argon2id(&self, salt: &[u8], password: &[u8], iteration: u64, res: &mut Vec) { res.extend_from_slice(salt); res.extend_from_slice(password); + res.extend_from_slice(&iteration.to_le_bytes()); *res = self.argon2id.hash(salt, res); } @@ -228,92 +234,92 @@ mod tests { use rstest::rstest; #[rstest] - #[case(&TEST_VECTORS[0].opts, &TEST_VECTORS[0].salt, &TEST_VECTORS[0].password, &TEST_VECTORS[0].offset_data, TEST_VECTORS[0].offset, "1805476033e579abf06772db32b52886e07d9c579c99be05dcc1826e2f162b5c4bf846b7fae13ac5e57991da69769f1d2aac2d9046b9c60cbce9af35b371d4bd")] - #[case(&TEST_VECTORS[1].opts, &TEST_VECTORS[1].salt, &TEST_VECTORS[1].password, &TEST_VECTORS[1].offset_data, TEST_VECTORS[1].offset, "edada70cd27e31ddcfc41edba2f63a03418fc1acd352ff78eff149573c5e247f0e06850cf03dc50dd9eef63275061cb85cdff8b47c3593d749145f1a226e8b7b")] + #[case(&TEST_VECTORS[0].opts, &TEST_VECTORS[0].salt, &TEST_VECTORS[0].password, &TEST_VECTORS[0].offset_data, TEST_VECTORS[0].offset, "b2c1bcd2674c0c96473e61b17d6e30d6e8a46ac258f730075b476a732284c64e36df041f7bd50260d68128b62e6cffac03e4ff585025d18b04d41dda4633b800")] + #[case(&TEST_VECTORS[1].opts, &TEST_VECTORS[1].salt, &TEST_VECTORS[1].password, &TEST_VECTORS[1].offset_data, TEST_VECTORS[1].offset, "e24c16e6912d2348e8be84977d22bd229382b72b65b501afe0066a32d6771df57f3557de0719070bbafb8faf1d0649562be693e3bf33c6e0a107d0af712030ef")] #[case(&SlowKeyOptions { iterations: 1, length: 64, scrypt: ScryptOptions::default(), argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "3dcbcc11d08ee43af8c4b537daf61087ce4c740f70e89b72b1f19083a6aa25a6d978eb94e452db49fc9c2309db56edbae93f68a0858e6b1d31aa38e1c63bbe03")] + "b143409d7030a3a2d1099de2071452406e0a94d7ccae6ef9fc570f724bfe15358b3b530d90b93e47b742f5883330f9742f1ca367b9a4c519daf66be30af100b6")] #[case(&SlowKeyOptions { iterations: 10, length: 32, scrypt: ScryptOptions { n: 1 << 12, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "2943950259d56a78c439065d0bf2baa86e32a7be9ad9509e3e0ba78c2bc1494a")] + "6fe4ad1ea824710e75b4a3914c6f3c617c70b3aeb0451639188c253b6f52880e")] #[case(&SlowKeyOptions { iterations: 10, length: 32, scrypt: ScryptOptions::default(), argon2id: Argon2idOptions { m_cost: 16, t_cost: 2 } }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "d4509baa22a5cd0065e99b304e3efe2681a564e4d1fe5f19e57017d58f06c59e")] + "744cfcc54433dfb5f4027163cc94c81d4630a63a6e60799c44f2a5801ad2bc77")] #[case(&SlowKeyOptions { iterations: 4, length: 64, scrypt: ScryptOptions { n: 1 << 20, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "6b66b1280b06539fbb571cfd4b44b3f114ab0d4f40e2d5e881cc1a329f2dd615088aa2b86f63422897cdf465ab11d68919bc247cb1517e4bd5abff78677dfb47")] + "3ed36a2cb71a043a901cbe237df6976b7a724acadfbc12112c90402548876dd5e76be1da2a1cb57e924a858c36b51c68db13b986e70ddc23254d7fa7a15c2ee0")] #[case(&SlowKeyOptions { iterations: 4, length: 128, scrypt: ScryptOptions { n: 1 << 20, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "ecfe68be26c4cd219e44ab9a0d287252b07e9fc4ce3203563d578bc713fbfe65bb2c4cb167ff67dad2225521eb78aa73ee646c3a3b4d5caca7ff37cc59573a047c66d7761164d5b1b5586ec4bc953e75e128accda5fe2cb70ac4f860a825de3483a61839d6f6f9e14a3826a4fab2a6fbc8fad0f8ce4a71e7c15f4f14b08635cc")] + "8e69eb21b3aa9cf0d5b42d18b5a80c8db50908c3baadd9c425d8dfc21ca0f37a503e37a18c5312cf040654f643cc1a5b1801e1f8e86fde355d05a5d2699725b088bf6bf02b0a5888e9198c1876ce82b2664185ff914c853b86b6ead34a351fcfd7124e75bfd643fbdb391025eee3483f30b1f765eae304547a1a1168d0ef448b")] #[case(&SlowKeyOptions { iterations: 4, length: 64, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"", &Vec::new(), 0, - "dcec23f3d34f980291e6a5246eb87a87039729d68f71b6c601ad1bbb7997c4b3584edb681eda73b60a232cd5fd672afc4516ed9c0d3ed922a209a93e155b22fb")] + "3af13ebf654ddf60014f4a7f37826f5f60e4defddefffdfc6bf5431e37420c1e308e823bef30a6adb3f862c4b4270aa55e9b0440af7e8ec8d52a3458c1cb3ff4")] #[case(&SlowKeyOptions { iterations: 10, length: 64, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 0, - "bc4f95aeddc434ba2f308865a31a06365fc45d9bcb47f70fbcb59be948f3c104a18eed7a3eaa595bf90233b3f1cafe545cf3e06eee49e2f9952b68a86a66b2a9")] + "c2a74fca9621ca13f2ab1a1bdf7cb8e6abe231d7494c280ff40024b1e92f964579d7c77e4b5c32ec438f2932b612f8eae9eeedbba93b0708e1f1b497bcdaed5d")] #[case(&SlowKeyOptions { iterations: 10, length: 64, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsal2", b"test", &Vec::new(), 0, - "8006abf493c49f65ed7a8d47719fd5b2b90f63e8c3d6759ba012d87e9bcd8791598984de8100bbaadef4c9228683f69dab74b53dcda8f8693e7bff58c3491b36")] + "016bbfa52b69c0fc366f9b93b5209d0c9783c018102101eb755f217627541778b13c5db624a105ed6470d7a916e8e5843f952f20bb9f0e9b6053e72176b6158b")] #[case(&SlowKeyOptions { iterations: 10, length: 64, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test2", &Vec::new(), 0, - "07b6fc97a02cd99fd6d7b1618dcf972421bed33bffa72eaea7c22e6ac224735ac80192dc90818d02ff1ab8c00d84513c6156f1f301e951a4cb9a313874c2df59")] + "f20e5bf61c9c0ab9208eb1b5a2f3a51a8276dbc5490862f17afbba5ffe539ee95765095aff000d86371ed6ca927efe736008fd048fbde77af56b20331ebde083")] #[case(&SlowKeyOptions { iterations: 10, length: 32, scrypt: ScryptOptions { n: 1 << 12, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 1, - "653f16de895c368d2ec8cd1950fe68b1fd4177050118f98d967a39c1057c1cc8")] + "dc4ca67e268ac2df2bbaa377afabafda82012b6188d562d67ef57f66f2f592e1")] #[case(&SlowKeyOptions { iterations: 10, length: 64, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 5, - "f5bd30aebebdaa919d54a0cabceba79dd1ee175de91a5ce9b2b9ba83b96dfd6a1dda7cf298e8aeccc56a5826ead128b9eb1669150426499f3cc8475b54702c18")] + "488d73ed1e5c22edfe060d542dc1bc517cdc567aede68fbf87f344fc153b1febbfff6bb52f236a21fa6aaa16e39769248f7eb01c80a48988049a9faee7434f99")] #[case(&SlowKeyOptions { iterations: 10, length: 128, scrypt: ScryptOptions { n: 1 << 15, r: 8, p: 1 }, argon2id: Argon2idOptions::default() }, b"saltsaltsaltsalt", b"test", &Vec::new(), 5, - "93c1738ae91ff2011cc630f781f278573f0397f5bebc676fd43619fe92019ac0f53c00a6773bfa06275ce4d92828f66fa33681f88950fd59b20d6f7e9ecb9b454d0988a0ff76a1780e7d93a9fca7b0869de6ebb5f673e200ea7def18ddf1923597e75d2e6985750e62d2326f887bef2c1d88a8252d2d4d0c77d23af8535bf020")] + "0ff28531af487240b664d549ebc2a367df89a2b5d94baed94a53025601b2b2f5ced135415c7cf880b4cc1fe97ea5ba052838caebb8301719d268b7a2d795d75908712910839c8145a70b7ebdf49e2f61a4c1466e89e2e5bd8fb45eb076a72baa60bc803162ee20481b1b85a5985d768908b283e95e52df4466f116ab9014945a")] fn derive_test( #[case] options: &SlowKeyOptions, #[case] salt: &[u8], #[case] password: &[u8], #[case] offset_data: &[u8], diff --git a/src/utils/checkpoints/checkpoint.rs b/src/utils/checkpoints/checkpoint.rs index 232ec62..29ca36e 100644 --- a/src/utils/checkpoints/checkpoint.rs +++ b/src/utils/checkpoints/checkpoint.rs @@ -96,7 +96,7 @@ impl CheckpointData { pub fn verify(&self, salt: &[u8], password: &[u8]) -> bool { // Use the checkpoint's previous data to derive the current data and return if it matches let options = SlowKeyOptions { - iterations: 2, + iterations: self.data.iteration + 1, length: self.data.slowkey.length, scrypt: self.data.slowkey.scrypt, argon2id: self.data.slowkey.argon2id, @@ -108,7 +108,7 @@ impl CheckpointData { }; let slowkey = SlowKey::new(&options); - let key = slowkey.derive_key(salt, password, prev_data, 1); + let key = slowkey.derive_key(salt, password, prev_data, self.data.iteration); key == self.data.data } diff --git a/src/utils/outputs/output.rs b/src/utils/outputs/output.rs index 7c0dbd5..5e7616f 100644 --- a/src/utils/outputs/output.rs +++ b/src/utils/outputs/output.rs @@ -37,7 +37,7 @@ impl OutputData { pub fn verify(&self, salt: &[u8], password: &[u8]) -> bool { // Use the checkpoint's previous data to derive the current data and return if it matches let options = SlowKeyOptions { - iterations: 2, + iterations: self.data.iteration, length: self.data.slowkey.length, scrypt: self.data.slowkey.scrypt, argon2id: self.data.slowkey.argon2id, @@ -49,7 +49,7 @@ impl OutputData { }; let slowkey = SlowKey::new(&options); - let key = slowkey.derive_key(salt, password, prev_data, 1); + let key = slowkey.derive_key(salt, password, prev_data, self.data.iteration - 1); key == self.data.data } @@ -65,7 +65,7 @@ impl Display for OutputData { let output = format!( "{}:\n {}: {}\n {} (please highlight to see): {}\n {} (please highlight to see): {}", "Output".yellow(), - "Iteration".green(), + "Iterations".green(), self.data.iteration, "Data".green(), format!("0x{}", hex::encode(&self.data.data)).black().on_black(),