From 89168dccceb03d402cf5f46ee261a10e4704daea Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Tue, 24 Mar 2026 19:42:35 -0400 Subject: [PATCH 01/11] sha-crypt SHA512 and SHA256 benchmarks --- sha-crypt/benches/lib.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 sha-crypt/benches/lib.rs diff --git a/sha-crypt/benches/lib.rs b/sha-crypt/benches/lib.rs new file mode 100644 index 00000000..03cdfb08 --- /dev/null +++ b/sha-crypt/benches/lib.rs @@ -0,0 +1,31 @@ +#![no_std] +#![feature(test)] + +extern crate test; + +use sha_crypt::{Algorithm, Params, PasswordHasher, ShaCrypt}; +use test::Bencher; + +#[bench] +pub fn sha_crypt_sha_512(bh: &mut Bencher) { + let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let salt = b"idU8Ptdv2tVGArtN"; + let rounds = 5_000; + let sha_crypt = ShaCrypt::new(Algorithm::Sha256Crypt, Params::new(rounds).unwrap()); + + bh.iter(|| { + sha_crypt.hash_password_with_salt(input, salt).unwrap(); + }); +} + +#[bench] +pub fn sha_crypt_sha_256(bh: &mut Bencher) { + let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let salt = b"idU8Ptdv2tVGArtN"; + let rounds = 5_000; + let sha_crypt = ShaCrypt::new(Algorithm::Sha512Crypt, Params::new(rounds).unwrap()); + + bh.iter(|| { + sha_crypt.hash_password_with_salt(input, salt).unwrap(); + }); +} \ No newline at end of file From 5f8ed9c82aca4041dda8e125ad93c1476ccf5242 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Tue, 24 Mar 2026 19:59:18 -0400 Subject: [PATCH 02/11] fmt --- sha-crypt/benches/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sha-crypt/benches/lib.rs b/sha-crypt/benches/lib.rs index 03cdfb08..25e67d4b 100644 --- a/sha-crypt/benches/lib.rs +++ b/sha-crypt/benches/lib.rs @@ -8,10 +8,10 @@ use test::Bencher; #[bench] pub fn sha_crypt_sha_512(bh: &mut Bencher) { - let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; let salt = b"idU8Ptdv2tVGArtN"; let rounds = 5_000; - let sha_crypt = ShaCrypt::new(Algorithm::Sha256Crypt, Params::new(rounds).unwrap()); + let sha_crypt = ShaCrypt::new(Algorithm::Sha256Crypt, Params::new(rounds).unwrap()); bh.iter(|| { sha_crypt.hash_password_with_salt(input, salt).unwrap(); @@ -20,12 +20,12 @@ pub fn sha_crypt_sha_512(bh: &mut Bencher) { #[bench] pub fn sha_crypt_sha_256(bh: &mut Bencher) { - let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let input = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; let salt = b"idU8Ptdv2tVGArtN"; let rounds = 5_000; - let sha_crypt = ShaCrypt::new(Algorithm::Sha512Crypt, Params::new(rounds).unwrap()); + let sha_crypt = ShaCrypt::new(Algorithm::Sha512Crypt, Params::new(rounds).unwrap()); bh.iter(|| { sha_crypt.hash_password_with_salt(input, salt).unwrap(); }); -} \ No newline at end of file +} From d14e3437ebeaf044044afd0fa23904b7f35217cb Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:01:55 -0400 Subject: [PATCH 03/11] ballon hash benchmarks --- balloon-hash/benches/lib.rs | 64 +++++++++++++++++++++++++ balloon-hash/data/mod.rs | 80 +++++++++++++++++++++++++++++++ balloon-hash/tests/balloon.rs | 51 ++------------------ balloon-hash/tests/balloon_m.rs | 84 ++------------------------------- 4 files changed, 152 insertions(+), 127 deletions(-) create mode 100644 balloon-hash/benches/lib.rs create mode 100644 balloon-hash/data/mod.rs diff --git a/balloon-hash/benches/lib.rs b/balloon-hash/benches/lib.rs new file mode 100644 index 00000000..46784e76 --- /dev/null +++ b/balloon-hash/benches/lib.rs @@ -0,0 +1,64 @@ +#![feature(test)] + +extern crate test; +use test::Bencher; + +use balloon_hash::{Algorithm, Balloon, Params}; +use digest::array::Array; + +#[path = "../data/mod.rs"] +mod data; +use data::TestVector; + +fn bench_test_vector(b: &mut Bencher, test_vector: &TestVector) { + let params = Params::new(test_vector.s_cost, test_vector.t_cost, test_vector.p_cost).unwrap(); + let balloon = Balloon::::new(Algorithm::BalloonM, params, None); + let mut memory = vec![Array::default(); balloon.params.s_cost.get() as usize]; + b.bytes = test_vector.password.len() as u64; + b.iter(|| { + let result = balloon + .hash_password_with_memory(test_vector.password, test_vector.salt, &mut memory) + .unwrap(); + assert_eq!(result.as_slice(), test_vector.output); + }); +} + +#[bench] +fn bench_balloon_m_vector_0(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[0]); +} + +#[bench] +fn bench_balloon_m_vector_1(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[1]); +} + +#[bench] +fn bench_balloon_m_vector_2(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[2]); +} + +#[bench] +fn bench_balloon_m_vector_3(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[3]); +} + +#[bench] +fn bench_balloon_m_vector_4(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[4]); +} + +#[bench] +fn bench_balloon_m_vector_5(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[5]); +} + +#[bench] +fn bench_balloon_m_vector_6(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[6]); +} + +#[bench] +fn bench_balloon_m_vector_7(b: &mut Bencher) { + bench_test_vector(b, &data::TEST_VECTORS[7]); +} \ No newline at end of file diff --git a/balloon-hash/data/mod.rs b/balloon-hash/data/mod.rs new file mode 100644 index 00000000..581d2ad5 --- /dev/null +++ b/balloon-hash/data/mod.rs @@ -0,0 +1,80 @@ +use hex_literal::hex; + +pub struct TestVector { + pub password: &'static [u8], + pub salt: &'static [u8], + pub s_cost: u32, + pub t_cost: u32, + pub p_cost: u32, + pub output: [u8; 32], +} + +/// Tested with the following implementations: +/// - +/// - +pub const TEST_VECTORS: &[TestVector] = &[ + TestVector { + password: b"hunter42", + salt: b"examplesalt", + s_cost: 1024, + t_cost: 3, + p_cost: 4, + output: hex!("1832bd8e5cbeba1cb174a13838095e7e66508e9bf04c40178990adbc8ba9eb6f"), + }, + TestVector { + password: b"", + salt: b"salt", + s_cost: 3, + t_cost: 3, + p_cost: 2, + output: hex!("f8767fe04059cef67b4427cda99bf8bcdd983959dbd399a5e63ea04523716c23"), + }, + TestVector { + password: b"password", + salt: b"", + s_cost: 3, + t_cost: 3, + p_cost: 3, + output: hex!("bcad257eff3d1090b50276514857e60db5d0ec484129013ef3c88f7d36e438d6"), + }, + TestVector { + password: b"password", + salt: b"", + s_cost: 3, + t_cost: 3, + p_cost: 1, + output: hex!("498344ee9d31baf82cc93ebb3874fe0b76e164302c1cefa1b63a90a69afb9b4d"), + }, + TestVector { + password: b"\0", + salt: b"\0", + s_cost: 3, + t_cost: 3, + p_cost: 4, + output: hex!("8a665611e40710ba1fd78c181549c750f17c12e423c11930ce997f04c7153e0c"), + }, + TestVector { + password: b"\0", + salt: b"\0", + s_cost: 3, + t_cost: 3, + p_cost: 1, + output: hex!("d9e33c683451b21fb3720afbd78bf12518c1d4401fa39f054b052a145c968bb1"), + }, + TestVector { + password: b"password", + salt: b"salt", + s_cost: 1, + t_cost: 1, + p_cost: 16, + output: hex!("a67b383bb88a282aef595d98697f90820adf64582a4b3627c76b7da3d8bae915"), + }, + TestVector { + password: b"password", + salt: b"salt", + s_cost: 1, + t_cost: 1, + p_cost: 1, + output: hex!("97a11df9382a788c781929831d409d3599e0b67ab452ef834718114efdcd1c6d"), + }, +]; \ No newline at end of file diff --git a/balloon-hash/tests/balloon.rs b/balloon-hash/tests/balloon.rs index eb36c1a4..8f6ca7f3 100644 --- a/balloon-hash/tests/balloon.rs +++ b/balloon-hash/tests/balloon.rs @@ -1,55 +1,10 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -use hex_literal::hex; -struct TestVector { - password: &'static [u8], - salt: &'static [u8], - s_cost: u32, - t_cost: u32, - output: [u8; 32], -} -/// Tested with the following implementations: -/// - -/// - -const TEST_VECTORS: &[TestVector] = &[ - TestVector { - password: b"hunter42", - salt: b"examplesalt", - s_cost: 1024, - t_cost: 3, - output: hex!("716043dff777b44aa7b88dcbab12c078abecfac9d289c5b5195967aa63440dfb"), - }, - TestVector { - password: b"", - salt: b"salt", - s_cost: 3, - t_cost: 3, - output: hex!("5f02f8206f9cd212485c6bdf85527b698956701ad0852106f94b94ee94577378"), - }, - TestVector { - password: b"password", - salt: b"", - s_cost: 3, - t_cost: 3, - output: hex!("20aa99d7fe3f4df4bd98c655c5480ec98b143107a331fd491deda885c4d6a6cc"), - }, - TestVector { - password: b"\0", - salt: b"\0", - s_cost: 3, - t_cost: 3, - output: hex!("4fc7e302ffa29ae0eac31166cee7a552d1d71135f4e0da66486fb68a749b73a4"), - }, - TestVector { - password: b"password", - salt: b"salt", - s_cost: 1, - t_cost: 1, - output: hex!("eefda4a8a75b461fa389c1dcfaf3e9dfacbc26f81f22e6f280d15cc18c417545"), - }, -]; +#[path = "../data/mod.rs"] +mod data; +use data::TEST_VECTORS; #[test] fn test_vectors() { diff --git a/balloon-hash/tests/balloon_m.rs b/balloon-hash/tests/balloon_m.rs index d4f4faa6..e00ca7f0 100644 --- a/balloon-hash/tests/balloon_m.rs +++ b/balloon-hash/tests/balloon_m.rs @@ -1,85 +1,11 @@ +use std::path; + use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -use hex_literal::hex; - -struct TestVector { - password: &'static [u8], - salt: &'static [u8], - s_cost: u32, - t_cost: u32, - p_cost: u32, - output: [u8; 32], -} -/// Tested with the following implementations: -/// - -/// - -const TEST_VECTORS: &[TestVector] = &[ - TestVector { - password: b"hunter42", - salt: b"examplesalt", - s_cost: 1024, - t_cost: 3, - p_cost: 4, - output: hex!("1832bd8e5cbeba1cb174a13838095e7e66508e9bf04c40178990adbc8ba9eb6f"), - }, - TestVector { - password: b"", - salt: b"salt", - s_cost: 3, - t_cost: 3, - p_cost: 2, - output: hex!("f8767fe04059cef67b4427cda99bf8bcdd983959dbd399a5e63ea04523716c23"), - }, - TestVector { - password: b"password", - salt: b"", - s_cost: 3, - t_cost: 3, - p_cost: 3, - output: hex!("bcad257eff3d1090b50276514857e60db5d0ec484129013ef3c88f7d36e438d6"), - }, - TestVector { - password: b"password", - salt: b"", - s_cost: 3, - t_cost: 3, - p_cost: 1, - output: hex!("498344ee9d31baf82cc93ebb3874fe0b76e164302c1cefa1b63a90a69afb9b4d"), - }, - TestVector { - password: b"\0", - salt: b"\0", - s_cost: 3, - t_cost: 3, - p_cost: 4, - output: hex!("8a665611e40710ba1fd78c181549c750f17c12e423c11930ce997f04c7153e0c"), - }, - TestVector { - password: b"\0", - salt: b"\0", - s_cost: 3, - t_cost: 3, - p_cost: 1, - output: hex!("d9e33c683451b21fb3720afbd78bf12518c1d4401fa39f054b052a145c968bb1"), - }, - TestVector { - password: b"password", - salt: b"salt", - s_cost: 1, - t_cost: 1, - p_cost: 16, - output: hex!("a67b383bb88a282aef595d98697f90820adf64582a4b3627c76b7da3d8bae915"), - }, - TestVector { - password: b"password", - salt: b"salt", - s_cost: 1, - t_cost: 1, - p_cost: 1, - output: hex!("97a11df9382a788c781929831d409d3599e0b67ab452ef834718114efdcd1c6d"), - }, -]; +#[path = "../data/mod.rs"] +mod data; +use data::TEST_VECTORS; #[test] fn test_vectors() { From 8a42d4ccc527c7a4c8591c353cf2c75ddb8c101c Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:02:49 -0400 Subject: [PATCH 04/11] cargo fmt --- balloon-hash/benches/lib.rs | 2 +- balloon-hash/data/mod.rs | 2 +- balloon-hash/tests/balloon.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/balloon-hash/benches/lib.rs b/balloon-hash/benches/lib.rs index 46784e76..89418e93 100644 --- a/balloon-hash/benches/lib.rs +++ b/balloon-hash/benches/lib.rs @@ -61,4 +61,4 @@ fn bench_balloon_m_vector_6(b: &mut Bencher) { #[bench] fn bench_balloon_m_vector_7(b: &mut Bencher) { bench_test_vector(b, &data::TEST_VECTORS[7]); -} \ No newline at end of file +} diff --git a/balloon-hash/data/mod.rs b/balloon-hash/data/mod.rs index 581d2ad5..066b3108 100644 --- a/balloon-hash/data/mod.rs +++ b/balloon-hash/data/mod.rs @@ -77,4 +77,4 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 1, output: hex!("97a11df9382a788c781929831d409d3599e0b67ab452ef834718114efdcd1c6d"), }, -]; \ No newline at end of file +]; diff --git a/balloon-hash/tests/balloon.rs b/balloon-hash/tests/balloon.rs index 8f6ca7f3..819439e1 100644 --- a/balloon-hash/tests/balloon.rs +++ b/balloon-hash/tests/balloon.rs @@ -1,7 +1,6 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; - #[path = "../data/mod.rs"] mod data; use data::TEST_VECTORS; From 5e31a6258d00052b0e32f2c389b7d9d8b70dcdd9 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:05:34 -0400 Subject: [PATCH 05/11] unused import --- balloon-hash/tests/balloon_m.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/balloon-hash/tests/balloon_m.rs b/balloon-hash/tests/balloon_m.rs index e00ca7f0..9a1d2bec 100644 --- a/balloon-hash/tests/balloon_m.rs +++ b/balloon-hash/tests/balloon_m.rs @@ -1,5 +1,3 @@ -use std::path; - use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; From 6c3606077e80bb306c135ddb10b8783c10595d41 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:21:33 -0400 Subject: [PATCH 06/11] refactor to use seperate files to avoid dead code usage --- balloon-hash/benches/lib.rs | 24 +++++------ balloon-hash/data/balloon.rs | 50 ++++++++++++++++++++++ balloon-hash/data/{mod.rs => balloon_m.rs} | 20 ++++----- balloon-hash/tests/balloon.rs | 8 ++-- balloon-hash/tests/balloon_m.rs | 8 ++-- 5 files changed, 80 insertions(+), 30 deletions(-) create mode 100644 balloon-hash/data/balloon.rs rename balloon-hash/data/{mod.rs => balloon_m.rs} (87%) diff --git a/balloon-hash/benches/lib.rs b/balloon-hash/benches/lib.rs index 89418e93..ae203e55 100644 --- a/balloon-hash/benches/lib.rs +++ b/balloon-hash/benches/lib.rs @@ -6,11 +6,11 @@ use test::Bencher; use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/mod.rs"] -mod data; -use data::TestVector; +#[path = "../data/balloon_m.rs"] +mod test_vectors; +use test_vectors::{BALLOON_M_TEST_VECTORS, BalloonMTestVector}; -fn bench_test_vector(b: &mut Bencher, test_vector: &TestVector) { +fn bench_test_vector(b: &mut Bencher, test_vector: &BalloonMTestVector) { let params = Params::new(test_vector.s_cost, test_vector.t_cost, test_vector.p_cost).unwrap(); let balloon = Balloon::::new(Algorithm::BalloonM, params, None); let mut memory = vec![Array::default(); balloon.params.s_cost.get() as usize]; @@ -25,40 +25,40 @@ fn bench_test_vector(b: &mut Bencher, test_vector: &TestVector) { #[bench] fn bench_balloon_m_vector_0(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[0]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[0]); } #[bench] fn bench_balloon_m_vector_1(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[1]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[1]); } #[bench] fn bench_balloon_m_vector_2(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[2]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[2]); } #[bench] fn bench_balloon_m_vector_3(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[3]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[3]); } #[bench] fn bench_balloon_m_vector_4(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[4]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[4]); } #[bench] fn bench_balloon_m_vector_5(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[5]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[5]); } #[bench] fn bench_balloon_m_vector_6(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[6]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[6]); } #[bench] fn bench_balloon_m_vector_7(b: &mut Bencher) { - bench_test_vector(b, &data::TEST_VECTORS[7]); + bench_test_vector(b, &BALLOON_M_TEST_VECTORS[7]); } diff --git a/balloon-hash/data/balloon.rs b/balloon-hash/data/balloon.rs new file mode 100644 index 00000000..d699b093 --- /dev/null +++ b/balloon-hash/data/balloon.rs @@ -0,0 +1,50 @@ +use hex_literal::hex; + +pub struct BalloonTestVector { + pub password: &'static [u8], + pub salt: &'static [u8], + pub s_cost: u32, + pub t_cost: u32, + pub output: [u8; 32], +} + +/// Tested with the following implementations: +/// - +/// - +pub const BALLOON_TEST_VECTORS: &[BalloonTestVector] = &[ + BalloonTestVector { + password: b"hunter42", + salt: b"examplesalt", + s_cost: 1024, + t_cost: 3, + output: hex!("716043dff777b44aa7b88dcbab12c078abecfac9d289c5b5195967aa63440dfb"), + }, + BalloonTestVector { + password: b"", + salt: b"salt", + s_cost: 3, + t_cost: 3, + output: hex!("5f02f8206f9cd212485c6bdf85527b698956701ad0852106f94b94ee94577378"), + }, + BalloonTestVector { + password: b"password", + salt: b"", + s_cost: 3, + t_cost: 3, + output: hex!("20aa99d7fe3f4df4bd98c655c5480ec98b143107a331fd491deda885c4d6a6cc"), + }, + BalloonTestVector { + password: b"\0", + salt: b"\0", + s_cost: 3, + t_cost: 3, + output: hex!("4fc7e302ffa29ae0eac31166cee7a552d1d71135f4e0da66486fb68a749b73a4"), + }, + BalloonTestVector { + password: b"password", + salt: b"salt", + s_cost: 1, + t_cost: 1, + output: hex!("eefda4a8a75b461fa389c1dcfaf3e9dfacbc26f81f22e6f280d15cc18c417545"), + }, +]; diff --git a/balloon-hash/data/mod.rs b/balloon-hash/data/balloon_m.rs similarity index 87% rename from balloon-hash/data/mod.rs rename to balloon-hash/data/balloon_m.rs index 066b3108..a780a0ac 100644 --- a/balloon-hash/data/mod.rs +++ b/balloon-hash/data/balloon_m.rs @@ -1,6 +1,6 @@ use hex_literal::hex; -pub struct TestVector { +pub struct BalloonMTestVector { pub password: &'static [u8], pub salt: &'static [u8], pub s_cost: u32, @@ -12,8 +12,8 @@ pub struct TestVector { /// Tested with the following implementations: /// - /// - -pub const TEST_VECTORS: &[TestVector] = &[ - TestVector { +pub const BALLOON_M_TEST_VECTORS: &[BalloonMTestVector] = &[ + BalloonMTestVector { password: b"hunter42", salt: b"examplesalt", s_cost: 1024, @@ -21,7 +21,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 4, output: hex!("1832bd8e5cbeba1cb174a13838095e7e66508e9bf04c40178990adbc8ba9eb6f"), }, - TestVector { + BalloonMTestVector { password: b"", salt: b"salt", s_cost: 3, @@ -29,7 +29,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 2, output: hex!("f8767fe04059cef67b4427cda99bf8bcdd983959dbd399a5e63ea04523716c23"), }, - TestVector { + BalloonMTestVector { password: b"password", salt: b"", s_cost: 3, @@ -37,7 +37,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 3, output: hex!("bcad257eff3d1090b50276514857e60db5d0ec484129013ef3c88f7d36e438d6"), }, - TestVector { + BalloonMTestVector { password: b"password", salt: b"", s_cost: 3, @@ -45,7 +45,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 1, output: hex!("498344ee9d31baf82cc93ebb3874fe0b76e164302c1cefa1b63a90a69afb9b4d"), }, - TestVector { + BalloonMTestVector { password: b"\0", salt: b"\0", s_cost: 3, @@ -53,7 +53,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 4, output: hex!("8a665611e40710ba1fd78c181549c750f17c12e423c11930ce997f04c7153e0c"), }, - TestVector { + BalloonMTestVector { password: b"\0", salt: b"\0", s_cost: 3, @@ -61,7 +61,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 1, output: hex!("d9e33c683451b21fb3720afbd78bf12518c1d4401fa39f054b052a145c968bb1"), }, - TestVector { + BalloonMTestVector { password: b"password", salt: b"salt", s_cost: 1, @@ -69,7 +69,7 @@ pub const TEST_VECTORS: &[TestVector] = &[ p_cost: 16, output: hex!("a67b383bb88a282aef595d98697f90820adf64582a4b3627c76b7da3d8bae915"), }, - TestVector { + BalloonMTestVector { password: b"password", salt: b"salt", s_cost: 1, diff --git a/balloon-hash/tests/balloon.rs b/balloon-hash/tests/balloon.rs index 819439e1..c3255458 100644 --- a/balloon-hash/tests/balloon.rs +++ b/balloon-hash/tests/balloon.rs @@ -1,13 +1,13 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/mod.rs"] -mod data; -use data::TEST_VECTORS; +#[path = "../data/balloon.rs"] +mod test_vectors; +use test_vectors::BALLOON_TEST_VECTORS; #[test] fn test_vectors() { - for test_vector in TEST_VECTORS { + for test_vector in BALLOON_TEST_VECTORS { let balloon = Balloon::::new( Algorithm::Balloon, Params::new(test_vector.s_cost, test_vector.t_cost, 1).unwrap(), diff --git a/balloon-hash/tests/balloon_m.rs b/balloon-hash/tests/balloon_m.rs index 9a1d2bec..ba81e12b 100644 --- a/balloon-hash/tests/balloon_m.rs +++ b/balloon-hash/tests/balloon_m.rs @@ -1,13 +1,13 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/mod.rs"] -mod data; -use data::TEST_VECTORS; +#[path = "../data/balloon_m.rs"] +mod test_vectors; +use test_vectors::BALLOON_M_TEST_VECTORS; #[test] fn test_vectors() { - for test_vector in TEST_VECTORS { + for test_vector in BALLOON_M_TEST_VECTORS { let balloon = Balloon::::new( Algorithm::BalloonM, Params::new(test_vector.s_cost, test_vector.t_cost, test_vector.p_cost).unwrap(), From 870dbe589b2bb63f6a4314628dc9eb7c35500c5d Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:31:23 -0400 Subject: [PATCH 07/11] renaming to test vectors files --- balloon-hash/benches/lib.rs | 2 +- .../data/{balloon_m.rs => balloon_m_test_vectors.rs} | 0 balloon-hash/data/{balloon.rs => balloon_test_vectors.rs} | 0 balloon-hash/tests/balloon.rs | 6 +++--- balloon-hash/tests/balloon_m.rs | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) rename balloon-hash/data/{balloon_m.rs => balloon_m_test_vectors.rs} (100%) rename balloon-hash/data/{balloon.rs => balloon_test_vectors.rs} (100%) diff --git a/balloon-hash/benches/lib.rs b/balloon-hash/benches/lib.rs index ae203e55..f15ef615 100644 --- a/balloon-hash/benches/lib.rs +++ b/balloon-hash/benches/lib.rs @@ -6,7 +6,7 @@ use test::Bencher; use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/balloon_m.rs"] +#[path = "../data/balloon_m_test_vectors.rs"] mod test_vectors; use test_vectors::{BALLOON_M_TEST_VECTORS, BalloonMTestVector}; diff --git a/balloon-hash/data/balloon_m.rs b/balloon-hash/data/balloon_m_test_vectors.rs similarity index 100% rename from balloon-hash/data/balloon_m.rs rename to balloon-hash/data/balloon_m_test_vectors.rs diff --git a/balloon-hash/data/balloon.rs b/balloon-hash/data/balloon_test_vectors.rs similarity index 100% rename from balloon-hash/data/balloon.rs rename to balloon-hash/data/balloon_test_vectors.rs diff --git a/balloon-hash/tests/balloon.rs b/balloon-hash/tests/balloon.rs index c3255458..5a76ac0a 100644 --- a/balloon-hash/tests/balloon.rs +++ b/balloon-hash/tests/balloon.rs @@ -1,9 +1,9 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/balloon.rs"] -mod test_vectors; -use test_vectors::BALLOON_TEST_VECTORS; +#[path = "../data/balloon_test_vectors.rs"] +mod balloon_test_vectors; +use balloon_test_vectors::BALLOON_TEST_VECTORS; #[test] fn test_vectors() { diff --git a/balloon-hash/tests/balloon_m.rs b/balloon-hash/tests/balloon_m.rs index ba81e12b..5eae207f 100644 --- a/balloon-hash/tests/balloon_m.rs +++ b/balloon-hash/tests/balloon_m.rs @@ -1,9 +1,9 @@ use balloon_hash::{Algorithm, Balloon, Params}; use digest::array::Array; -#[path = "../data/balloon_m.rs"] -mod test_vectors; -use test_vectors::BALLOON_M_TEST_VECTORS; +#[path = "../data/balloon_m_test_vectors.rs"] +mod balloon_m_test_vectors; +use balloon_m_test_vectors::BALLOON_M_TEST_VECTORS; #[test] fn test_vectors() { From 50ad7bc675d5e1f926db9f6b9ec35b8ca4798999 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:34:35 -0400 Subject: [PATCH 08/11] bcrypt-pbkdf benchmarks --- bcrypt-pbkdf/benches/lib.rs | 75 ++++++++++++++++++++++++++ bcrypt-pbkdf/data/test_vectors.rs | 78 +++++++++++++++++++++++++++ bcrypt-pbkdf/tests/test_vectors.rs | 84 ++---------------------------- 3 files changed, 157 insertions(+), 80 deletions(-) create mode 100644 bcrypt-pbkdf/benches/lib.rs create mode 100644 bcrypt-pbkdf/data/test_vectors.rs diff --git a/bcrypt-pbkdf/benches/lib.rs b/bcrypt-pbkdf/benches/lib.rs new file mode 100644 index 00000000..0f6e3261 --- /dev/null +++ b/bcrypt-pbkdf/benches/lib.rs @@ -0,0 +1,75 @@ +#![feature(test)] + +extern crate test; + +use bcrypt_pbkdf::bcrypt_pbkdf_with_memory; +use test::Bencher; + +#[path = "../data/test_vectors.rs"] +mod test_vectors; +use test_vectors::{TEST_VECTORS, Test}; + +fn bench_test_vector(b: &mut Bencher, test_vector: &Test) { + let mut out = vec![0; test_vector.out.len()]; + let len = test_vector.out.len().div_ceil(32) * 32; + let mut memory = vec![0; len]; + + b.bytes = test_vector.password.len() as u64; + b.iter(|| { + bcrypt_pbkdf_with_memory( + test_vector.password, + test_vector.salt, + test_vector.rounds, + &mut out, + &mut memory, + ) + .unwrap(); + + assert_eq!(out, test_vector.out); + }); +} + +#[bench] +fn bench_vector_0(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[0]); +} + +#[bench] +fn bench_vector_1(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[1]); +} + +#[bench] +fn bench_vector_2(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[2]); +} + +#[bench] +fn bench_vector_3(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[3]); +} + +#[bench] +fn bench_vector_4(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[4]); +} + +#[bench] +fn bench_vector_5(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[5]); +} + +#[bench] +fn bench_vector_6(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[6]); +} + +#[bench] +fn bench_vector_7(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[7]); +} + +#[bench] +fn bench_vector_8(b: &mut Bencher) { + bench_test_vector(b, &TEST_VECTORS[8]); +} diff --git a/bcrypt-pbkdf/data/test_vectors.rs b/bcrypt-pbkdf/data/test_vectors.rs new file mode 100644 index 00000000..0ddfb14b --- /dev/null +++ b/bcrypt-pbkdf/data/test_vectors.rs @@ -0,0 +1,78 @@ +use hex_literal::hex; + +pub struct Test { + pub password: &'static str, + pub salt: &'static [u8], + pub rounds: u32, + pub out: &'static [u8], +} + +pub static TEST_VECTORS: &[Test] = &[ + Test { + password: "password", + salt: b"salt", + rounds: 4, + out: &hex!("5bbf0cc293587f1c3635555c27796598d47e579071bf427e9d8fbe842aba34d9"), + }, + Test { + password: "password", + salt: &[0], + rounds: 4, + out: &hex!("c12b566235eee04c212598970a579a67"), + }, + Test { + password: "\x00", + salt: b"salt", + rounds: 4, + out: &hex!("6051be18c2f4f82cbf0efee5471b4bb9"), + }, + Test { + password: "password\x00", + salt: b"salt\x00", + rounds: 4, + out: &hex!("7410e44cf4fa07bfaac8a928b1727fac001375e7bf7384370f48efd121743050"), + }, + Test { + password: "pass\x00wor", + salt: b"sa\x00l", + rounds: 4, + out: &hex!("c2bffd9db38f6569efef4372f4de83c0"), + }, + Test { + password: "pass\x00word", + salt: b"sa\x00lt", + rounds: 4, + out: &hex!("4ba4ac3925c0e8d7f0cdb6bb1684a56f"), + }, + Test { + password: "password", + salt: b"salt", + rounds: 8, + out: &hex!( + "e1367ec5151a33faac4cc1c144cd" + "23fa15d5548493ecc99b9b5d9c0d" + "3b27bec76227ea66088b849b20ab" + "7aa478010246e74bba51723fefa9" + "f9474d6508845e8d"), + }, + Test { + password: "password", + salt: b"salt", + rounds: 42, + out: &hex!("833cf0dcf56db65608e8f0dc0ce882bd"), + }, + Test { + password: concat!( + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, ", + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ", + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ", + "nisi ut aliquip ex ea commodo consequat. ", + "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum ", + "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non ", + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum." + ), + salt: b"salis\x00", + rounds: 8, + out: &hex!("10978b07253df57f71a162eb0e8ad30a"), + }, +]; diff --git a/bcrypt-pbkdf/tests/test_vectors.rs b/bcrypt-pbkdf/tests/test_vectors.rs index c5c1d8ff..79ebea0d 100644 --- a/bcrypt-pbkdf/tests/test_vectors.rs +++ b/bcrypt-pbkdf/tests/test_vectors.rs @@ -1,89 +1,13 @@ extern crate bcrypt_pbkdf; use bcrypt_pbkdf::bcrypt_pbkdf_with_memory; -use hex_literal::hex; +#[path = "../data/test_vectors.rs"] +mod test_vectors; +use test_vectors::TEST_VECTORS; #[test] fn test_openbsd_vectors() { - struct Test { - password: &'static str, - salt: Vec, - rounds: u32, - out: Vec, - } - - let tests = vec![ - Test { - password: "password", - salt: b"salt".to_vec(), - rounds: 4, - out: hex!("5bbf0cc293587f1c3635555c27796598d47e579071bf427e9d8fbe842aba34d9").to_vec(), - }, - Test { - password: "password", - salt: vec![0], - rounds: 4, - out: hex!("c12b566235eee04c212598970a579a67").to_vec(), - }, - Test { - password: "\x00", - salt: b"salt".to_vec(), - rounds: 4, - out: hex!("6051be18c2f4f82cbf0efee5471b4bb9").to_vec(), - }, - Test { - password: "password\x00", - salt: b"salt\x00".to_vec(), - rounds: 4, - out: hex!("7410e44cf4fa07bfaac8a928b1727fac001375e7bf7384370f48efd121743050").to_vec(), - }, - Test { - password: "pass\x00wor", - salt: b"sa\x00l".to_vec(), - rounds: 4, - out: hex!("c2bffd9db38f6569efef4372f4de83c0").to_vec(), - }, - Test { - password: "pass\x00word", - salt: b"sa\x00lt".to_vec(), - rounds: 4, - out: hex!("4ba4ac3925c0e8d7f0cdb6bb1684a56f").to_vec(), - }, - Test { - password: "password", - salt: b"salt".to_vec(), - rounds: 8, - out: hex!( - "e1367ec5151a33faac4cc1c144cd" - "23fa15d5548493ecc99b9b5d9c0d" - "3b27bec76227ea66088b849b20ab" - "7aa478010246e74bba51723fefa9" - "f9474d6508845e8d") - .to_vec(), - }, - Test { - password: "password", - salt: b"salt".to_vec(), - rounds: 42, - out: hex!("833cf0dcf56db65608e8f0dc0ce882bd").to_vec(), - }, - Test { - password: concat!( - "Lorem ipsum dolor sit amet, consectetur adipisicing elit, ", - "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ", - "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ", - "nisi ut aliquip ex ea commodo consequat. ", - "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum ", - "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non ", - "proident, sunt in culpa qui officia deserunt mollit anim id est laborum." - ), - salt: b"salis\x00".to_vec(), - rounds: 8, - out: hex!("10978b07253df57f71a162eb0e8ad30a").to_vec(), - }, - ]; - - for t in tests.iter() { + for t in TEST_VECTORS.iter() { let mut out = vec![0; t.out.len()]; let len = t.out.len().div_ceil(32) * 32; let mut memory = vec![0; len]; From 62256a6d99565371927c990b6e6f996d25705104 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 19:36:55 -0400 Subject: [PATCH 09/11] clippy recommendation, last commit for the night. 2 crates was good enough --- bcrypt-pbkdf/tests/test_vectors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcrypt-pbkdf/tests/test_vectors.rs b/bcrypt-pbkdf/tests/test_vectors.rs index 79ebea0d..ae5abd6a 100644 --- a/bcrypt-pbkdf/tests/test_vectors.rs +++ b/bcrypt-pbkdf/tests/test_vectors.rs @@ -11,7 +11,7 @@ fn test_openbsd_vectors() { let mut out = vec![0; t.out.len()]; let len = t.out.len().div_ceil(32) * 32; let mut memory = vec![0; len]; - bcrypt_pbkdf_with_memory(t.password, &t.salt[..], t.rounds, &mut out, &mut memory).unwrap(); + bcrypt_pbkdf_with_memory(t.password, t.salt, t.rounds, &mut out, &mut memory).unwrap(); assert_eq!(out, t.out); } } From 8c281613864c6a2f403f9b903ba9f7ea1089b97e Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 21:36:50 -0400 Subject: [PATCH 10/11] refactoring yescrypt to use same test vectors for benchmarks --- yescrypt/benches/lib.rs | 266 ++++++++++++++++++++++++ yescrypt/data/mcf_test_vectors.rs | 187 +++++++++++++++++ yescrypt/data/test_vectors.rs | 332 ++++++++++++++++++++++++++++++ yescrypt/tests/kats.rs | 276 ++----------------------- yescrypt/tests/mcf.rs | 76 ++----- 5 files changed, 819 insertions(+), 318 deletions(-) create mode 100644 yescrypt/benches/lib.rs create mode 100644 yescrypt/data/mcf_test_vectors.rs create mode 100644 yescrypt/data/test_vectors.rs diff --git a/yescrypt/benches/lib.rs b/yescrypt/benches/lib.rs new file mode 100644 index 00000000..fbf11d85 --- /dev/null +++ b/yescrypt/benches/lib.rs @@ -0,0 +1,266 @@ +#![no_std] +#![feature(test)] + +extern crate test; + +use test::Bencher; +use yescrypt::{CustomizedPasswordHasher, Params, Yescrypt, yescrypt}; + +#[path = "../data/test_vectors.rs"] +mod test_vectors; +use test_vectors::{TEST_VECTORS, TestVector}; + +#[path = "../data/mcf_test_vectors.rs"] +mod mcf_test_vectors; +use mcf_test_vectors::{MCF_TEST_VECTORS, McfTestVector}; + +fn bench_test_vector(bh: &mut Bencher, test_vector: &TestVector) { + let params = test_vector.params(); + let mut buf = [0u8; 64]; + + bh.bytes = test_vector.password.len() as u64; + bh.iter(|| { + yescrypt( + test_vector.password, + test_vector.salt, + ¶ms, + &mut buf[..test_vector.output.len()], + ) + .unwrap(); + // assert_eq!(test_vector.output, &buf[..test_vector.output.len()]); + }); +} + +fn bench_hash_mcf(bh: &mut Bencher, test_vector: &McfTestVector) { + let params = Params::new( + test_vector.mode, + test_vector.n, + test_vector.r, + test_vector.p, + ) + .unwrap(); + let salt = test_vector.salt(); + + bh.bytes = test_vector.password.len() as u64; + bh.iter(|| { + let hash = Yescrypt::default() + .hash_password_with_params(test_vector.password, salt, params) + .unwrap(); + // assert_eq!(test_vector.expected_hash, hash.as_str()); + }); +} + +#[bench] +pub fn yescrypt_kat_0(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[0]); +} + +#[bench] +pub fn yescrypt_kat_1(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[1]); +} + +#[bench] +pub fn yescrypt_kat_2(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[2]); +} + +#[bench] +pub fn yescrypt_kat_3(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[3]); +} + +#[bench] +pub fn yescrypt_kat_4(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[4]); +} + +#[bench] +pub fn yescrypt_kat_5(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[5]); +} + +#[bench] +pub fn yescrypt_kat_6(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[6]); +} + +#[bench] +pub fn yescrypt_kat_7(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[7]); +} + +#[bench] +pub fn yescrypt_kat_8(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[8]); +} + +#[bench] +pub fn yescrypt_kat_9(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[9]); +} + +#[bench] +pub fn yescrypt_kat_10(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[10]); +} + +#[bench] +pub fn yescrypt_kat_11(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[11]); +} + +#[bench] +pub fn yescrypt_kat_12(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[12]); +} + +#[bench] +pub fn yescrypt_kat_13(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[13]); +} + +#[bench] +pub fn yescrypt_kat_14(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[14]); +} + +#[bench] +pub fn yescrypt_kat_15(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[15]); +} + +#[bench] +pub fn yescrypt_kat_16(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[16]); +} + +#[bench] +pub fn yescrypt_kat_17(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[17]); +} + +#[bench] +pub fn yescrypt_kat_18(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[18]); +} + +#[bench] +pub fn yescrypt_kat_19(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[19]); +} + +#[bench] +pub fn yescrypt_kat_20(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[20]); +} + +#[bench] +pub fn yescrypt_kat_21(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[21]); +} + +#[bench] +pub fn yescrypt_kat_22(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[22]); +} + +#[bench] +pub fn yescrypt_kat_23(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[23]); +} + +#[bench] +pub fn yescrypt_kat_24(bh: &mut Bencher) { + bench_test_vector(bh, &TEST_VECTORS[24]); +} + +#[bench] +pub fn yescrypt_mcf_hash_0(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[0]); +} + +#[bench] +pub fn yescrypt_mcf_hash_1(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[1]); +} + +#[bench] +pub fn yescrypt_mcf_hash_2(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[2]); +} + +#[bench] +pub fn yescrypt_mcf_hash_3(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[3]); +} + +#[bench] +pub fn yescrypt_mcf_hash_4(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[4]); +} + +#[bench] +pub fn yescrypt_mcf_hash_5(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[5]); +} + +#[bench] +pub fn yescrypt_mcf_hash_6(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[6]); +} + +#[bench] +pub fn yescrypt_mcf_hash_7(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[7]); +} + +#[bench] +pub fn yescrypt_mcf_hash_8(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[8]); +} + +#[bench] +pub fn yescrypt_mcf_hash_9(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[9]); +} + +#[bench] +pub fn yescrypt_mcf_hash_10(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[10]); +} + +#[bench] +pub fn yescrypt_mcf_hash_11(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[11]); +} + +#[bench] +pub fn yescrypt_mcf_hash_12(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[12]); +} + +#[bench] +pub fn yescrypt_mcf_hash_13(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[13]); +} + +#[bench] +pub fn yescrypt_mcf_hash_14(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[14]); +} + +#[bench] +pub fn yescrypt_mcf_hash_15(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[15]); +} + +#[bench] +pub fn yescrypt_mcf_hash_16(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[16]); +} + +#[bench] +pub fn yescrypt_mcf_hash_17(bh: &mut Bencher) { + bench_hash_mcf(bh, &MCF_TEST_VECTORS[17]); +} diff --git a/yescrypt/data/mcf_test_vectors.rs b/yescrypt/data/mcf_test_vectors.rs new file mode 100644 index 00000000..a594f75b --- /dev/null +++ b/yescrypt/data/mcf_test_vectors.rs @@ -0,0 +1,187 @@ +use yescrypt::Mode; + +pub struct McfTestVector { + pub password: &'static [u8], + pub salt_len: usize, + pub mode: Mode, + pub n: u64, + pub r: u32, + pub p: u32, + pub expected_hash: &'static str, +} + +impl McfTestVector { + pub fn salt(&self) -> &'static [u8] { + &EXAMPLE_SALT[..self.salt_len] + } +} + +pub const EXAMPLE_PASSWD: &[u8] = b"pleaseletmein"; +pub const EXAMPLE_SALT: &[u8] = b"WZaPV7LSUEKMo34."; + +/// Adapted from `TESTS-OK` in the yescrypt reference C implementation. +/// +pub static MCF_TEST_VECTORS: &[McfTestVector] = &[ + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 16, + mode: Mode::Rw, + n: 1 << 16, + r: 8, + p: 11, + expected_hash: "$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.$HboGM6qPrsK.StKYGt6KErmUYtioHreJd98oIugoNB6", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 15, + mode: Mode::Rw, + n: 1 << 15, + r: 7, + p: 1, + expected_hash: "$y$jC4$LdJMENpBABJJ3hIHjB1B$jVg4HoqqpbmQv/NCpin.QCMagJ8o4QX7lXdzvVV0xFC", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 14, + mode: Mode::Worm, + n: 1 << 14, + r: 6, + p: 10, + expected_hash: "$y$/B3.6$LdJMENpBABJJ3hIHjB1$h8sE4hJo.BsdlfJr0.d8bNJNPZymH7Y3kLj4aY1Rfc8", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 13, + mode: Mode::Worm, + n: 1 << 13, + r: 5, + p: 1, + expected_hash: "$y$/A2$LdJMENpBABJJ3hIHj/$5IEld1eWdmh5lylrqHLF5dvA3ISpimEM9J1Dd05n/.3", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 12, + mode: Mode::Rw, + n: 1 << 12, + r: 4, + p: 9, + expected_hash: "$y$j91.5$LdJMENpBABJJ3hIH$ebKnn23URD5vyLgF9cP2EvVosrUXf7UErGRV0KmC6e6", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 11, + mode: Mode::Rw, + n: 1 << 11, + r: 3, + p: 1, + expected_hash: "$y$j80$LdJMENpBABJJ3h2$ysXVVJwuaVlI1BWoEKt/Bz3WNDDmdOWz/8KTQaHL1cC", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 10, + mode: Mode::Worm, + n: 1 << 10, + r: 2, + p: 8, + expected_hash: "$y$/7/.4$LdJMENpBABJJ3/$lXHleh7bIZMGNtJVxGVrsIWkEIXfBedlfPui/PITflC", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 9, + mode: Mode::Worm, + n: 1 << 9, + r: 1, + p: 1, + expected_hash: "$y$/6.$LdJMENpBABJJ$zQITmYSih5.CTY47x0IuE4wl.b3HzYGKKCSggakaQ22", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 8, + mode: Mode::Rw, + n: 1 << 8, + r: 1, + p: 7, + expected_hash: "$y$j5..3$LdJMENpBAB3$xi27PTUNd8NsChHeLOz85JFnUOyibRHkWzprowRlR5/", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 7, + mode: Mode::Rw, + n: 1 << 7, + r: 2, + p: 1, + expected_hash: "$y$j4/$LdJMENpBA/$tHlkpTQ8V/eEnTVau1uW36T97LIXlfPrEzdeV5SE5K7", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 6, + mode: Mode::Worm, + n: 1 << 6, + r: 1, + p: 6, + expected_hash: "$y$/3..2$LdJMENpB$tNczXFuNUd3HMqypStCRsEaL4e4KF7ZYLBe8Hbeg0B7", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 5, + mode: Mode::Worm, + n: 1 << 5, + r: 2, + p: 1, + expected_hash: "$y$/2/$LdJMEN3$RRorHhfsw1/P/WR6Aurg4U72e9Q7qt9vFPURdyfiqK8", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 4, + mode: Mode::Rw, + n: 1 << 5, + r: 1, + p: 5, + expected_hash: "$y$j2..1$LdJME/$iLEt6kuTwHch6XdCxtTHfsQzYwWFmpUwgl6Ax8RH4d1", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 3, + mode: Mode::Rw, + n: 1 << 3, + r: 2, + p: 1, + expected_hash: "$y$j0/$LdJM$k7BXzSDuoGHW56SY3HxROCiA0gWRscZe2aA0q5oHPM0", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 2, + mode: Mode::Worm, + n: 1 << 2, + r: 1, + p: 4, + expected_hash: "$y$//..0$Ld3$6BJXezMFxaMiO5wsuoEmztvtCs/79085dZO56ADlV5B", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 1, + mode: Mode::Worm, + n: 1 << 2, + r: 2, + p: 1, + expected_hash: "$y$///$L/$Rrrkp6OVljrIk0kcwkCDhAiHJiSthh3cKeIGHUW7Z0C", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 16, + mode: Mode::Rw, + n: 1 << 4, + r: 1, + p: 3, + expected_hash: "$y$j1../$LdJMENpBABJJ3hIHjB1Bi.$L8OQFc8mxJPd7CpUFgkS7KqJM2I9jGXu3BdqX2D.647", + }, + McfTestVector { + password: EXAMPLE_PASSWD, + salt_len: 15, + mode: Mode::Rw, + n: 1 << 2, + r: 2, + p: 1, + expected_hash: "$y$j//$LdJMENpBABJJ3hIHjB1B$U8a2MaK.yesqWySK8Owk6PWeWmp/XuagMbpP45q1/q1", + }, +]; diff --git a/yescrypt/data/test_vectors.rs b/yescrypt/data/test_vectors.rs new file mode 100644 index 00000000..014417cc --- /dev/null +++ b/yescrypt/data/test_vectors.rs @@ -0,0 +1,332 @@ +use hex_literal::hex; +use yescrypt::{Mode, Params}; + +pub struct TestVector { + pub password: &'static [u8], + pub salt: &'static [u8], + pub mode: Mode, + pub n: u64, + pub r: u32, + pub p: u32, + pub t: u32, + pub g: u32, + pub output: &'static [u8], +} + +impl TestVector { + pub fn params(&self) -> Params { + Params::new_with_all_params(self.mode, self.n, self.r, self.p, self.t, self.g).unwrap() + } +} + +/// Adapted from the reference implementation's `TESTS-OK`. +/// +pub static TEST_VECTORS: &[TestVector] = &[ + TestVector { + password: b"", + salt: b"", + mode: Mode::Classic, + n: 16, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!( + "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442" + "fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Classic, + n: 16, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!("77d6576238657b20"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Classic, + n: 4, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!( + "efad0c23314cb572bc3cfb1543da42f8a8b073004c866b64ab5055a4f09fa5f5" + "71142ebfe7e05a3b92c432f31dea95ad5f9c854b6456462f4bd0f732b7cdc549" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!( + "85dda48c9ec9de2f7f1ae8b4dfeda51f8b6d56f3081be1a7c0833ba2719a36ab" + "02885dae36557d342686b17ba75f2c217792de0970ab1d07a9c750936d31426f" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!("85dda48c9ec9de2f"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!( + "4baa8cd8608ba91f3e3439d9ec4fae8f9fc092d9ca22b7377e31ae5b9ad7877c" + "1168691162dd0e5ef049e570650cbed4384ad60534fb0cbed19ff3f033c94b0c" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 2, + g: 0, + output: &hex!( + "e6e8bba09b6412ffb0b3cc35e37d0b782a47fbaadc57a076d7c6cc2e70919a1b" + "8d4738c4f83355690742d9bed71c3b8fb0d7eb086ab134c5e55707c2c13c75ef" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 3, + g: 0, + output: &hex!( + "acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a108" + "997d70ae0a64bf0a4d96c173abf88279c1a94ad9bdf168edfbbd90f66ed5c80d" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 3, + g: 0, + output: &hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a10899"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 3, + g: 0, + output: &hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a108"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 3, + g: 0, + output: &hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a1"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Worm, + n: 4, + r: 1, + p: 1, + t: 3, + g: 0, + output: &hex!("ac"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!( + "0cd5af76eb241df8119a9a122ae36920bcc7f414b9c0d58f45008060dade46b0" + "c80922bdcc16a3ab5d201d4c6140c671be1f75272ca904739d5ad1ff672b0c21" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 0, + g: 0, + output: &hex!("0cd5af76"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!( + "23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c4" + "68ca362c5557cc04b6811e2e730841f526d8f4f7acfbfa9e06fe1f383a71155e" + ), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c468"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c4"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35"), + }, + TestVector { + password: b"", + salt: b"", + mode: Mode::Rw, + n: 4, + r: 1, + p: 1, + t: 1, + g: 0, + output: &hex!("23"), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Rw, + n: 16, + r: 8, + p: 1, + t: 10, + g: 0, + output: &hex!( + "e1f981733a94052fcd7acb1405df0bbde8e499b6a1331b775909b48c2f516c40dcc8301635b7237b" + ), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Worm, + n: 16, + r: 8, + p: 1, + t: 10, + g: 0, + output: &hex!( + "9e7a4097644284cf3b73b60450ff230cdcb6b1b19b1509eeb482f696c4f1c705c00f740216183a12" + ), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Rw, + n: 16, + r: 8, + p: 1, + t: 0, + g: 0, + output: &hex!( + "c8c7ff1122b0b291c3f2608948782cd689cc45579017aaa5ff8baa74a632ec99c3d66930fb2023bb" + ), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Worm, + n: 16, + r: 8, + p: 1, + t: 0, + g: 0, + output: &hex!( + "9dd636c2d0bb92345286efdaf8a68cfc1b4ffdc4b1adaccc7d864b9a6787b85d6ae0f5280da8889f" + ), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Rw, + n: 16, + r: 8, + p: 1, + t: 0, + g: 0, + output: &hex!("c8c7ff1122b0b291c3f2608948782cd689cc45579017aaa5ff8baa74a632ec99"), + }, + TestVector { + password: b"p", + salt: b"s", + mode: Mode::Rw, + n: 16, + r: 8, + p: 1, + t: 0, + g: 0, + output: &hex!("c8c7ff1122b0b291"), + }, +]; diff --git a/yescrypt/tests/kats.rs b/yescrypt/tests/kats.rs index fa7529e1..125af6a9 100644 --- a/yescrypt/tests/kats.rs +++ b/yescrypt/tests/kats.rs @@ -1,267 +1,25 @@ //! Adapted from the reference implementation's `TESTS-OK`. //! -use hex_literal::hex; use yescrypt::{Mode, Params, yescrypt}; -#[test] -fn kat0() { - const EXPECTED: [u8; 64] = hex!( - "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442" - "fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" - ); - let params = Params::new(Mode::Classic, 16, 1, 1).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat1() { - const EXPECTED: [u8; 8] = hex!("77d6576238657b20"); - let params = Params::new(Mode::Classic, 16, 1, 1).unwrap(); - let mut actual = [0u8; 8]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat2() { - const EXPECTED: [u8; 64] = hex!( - "efad0c23314cb572bc3cfb1543da42f8a8b073004c866b64ab5055a4f09fa5f5" - "71142ebfe7e05a3b92c432f31dea95ad5f9c854b6456462f4bd0f732b7cdc549" - ); - let params = Params::new(Mode::Classic, 4, 1, 1).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat3() { - const EXPECTED: [u8; 64] = hex!( - "85dda48c9ec9de2f7f1ae8b4dfeda51f8b6d56f3081be1a7c0833ba2719a36ab" - "02885dae36557d342686b17ba75f2c217792de0970ab1d07a9c750936d31426f" - ); - let params = Params::new(Mode::Worm, 4, 1, 1).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat4() { - const EXPECTED: [u8; 8] = hex!("85dda48c9ec9de2f"); - let params = Params::new(Mode::Worm, 4, 1, 1).unwrap(); - let mut actual = [0u8; 8]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat5() { - const EXPECTED: [u8; 64] = hex!( - "4baa8cd8608ba91f3e3439d9ec4fae8f9fc092d9ca22b7377e31ae5b9ad7877c" - "1168691162dd0e5ef049e570650cbed4384ad60534fb0cbed19ff3f033c94b0c" - ); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat6() { - const EXPECTED: [u8; 64] = hex!( - "e6e8bba09b6412ffb0b3cc35e37d0b782a47fbaadc57a076d7c6cc2e70919a1b" - "8d4738c4f83355690742d9bed71c3b8fb0d7eb086ab134c5e55707c2c13c75ef" - ); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 2, 0).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat7() { - const EXPECTED: [u8; 64] = hex!( - "acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a108" - "997d70ae0a64bf0a4d96c173abf88279c1a94ad9bdf168edfbbd90f66ed5c80d" - ); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 3, 0).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat8() { - const EXPECTED: [u8; 33] = - hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a10899"); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 3, 0).unwrap(); - let mut actual = [0u8; 33]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat9() { - const EXPECTED: [u8; 32] = - hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a108"); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 3, 0).unwrap(); - let mut actual = [0u8; 32]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat10() { - const EXPECTED: [u8; 31] = - hex!("acd9a4201cf4a476ecf7baa6113d86fb65cd07102b4004e4f9d99cd34255a1"); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 3, 0).unwrap(); - let mut actual = [0u8; 31]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat11() { - const EXPECTED: [u8; 1] = hex!("ac"); - let params = Params::new_with_all_params(Mode::Worm, 4, 1, 1, 3, 0).unwrap(); - let mut actual = [0u8; 1]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat12() { - const EXPECTED: [u8; 64] = hex!( - "0cd5af76eb241df8119a9a122ae36920bcc7f414b9c0d58f45008060dade46b0" - "c80922bdcc16a3ab5d201d4c6140c671be1f75272ca904739d5ad1ff672b0c21" - ); - let params = Params::new(Mode::default(), 4, 1, 1).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat13() { - const EXPECTED: [u8; 4] = hex!("0cd5af76"); - let params = Params::new(Mode::default(), 4, 1, 1).unwrap(); - let mut actual = [0u8; 4]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat14() { - const EXPECTED: [u8; 64] = hex!( - "23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c4" - "68ca362c5557cc04b6811e2e730841f526d8f4f7acfbfa9e06fe1f383a71155e" - ); - let params = Params::new_with_all_params(Mode::default(), 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 64]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat15() { - const EXPECTED: [u8; 33] = - hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c468"); - let params = Params::new_with_all_params(Mode::default(), 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 33]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat16() { - const EXPECTED: [u8; 32] = - hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35c4"); - let params = Params::new_with_all_params(Mode::default(), 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 32]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat17() { - const EXPECTED: [u8; 31] = - hex!("23b6adf0b60c9a997f58583d80cda48c638cdc2f289edf93a70807725a0d35"); - let params = Params::new_with_all_params(Mode::default(), 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 31]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat18() { - const EXPECTED: [u8; 1] = hex!("23"); - let params = Params::new_with_all_params(Mode::default(), 4, 1, 1, 1, 0).unwrap(); - let mut actual = [0u8; 1]; - yescrypt(b"", b"", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat19() { - const EXPECTED: [u8; 40] = - hex!("e1f981733a94052fcd7acb1405df0bbde8e499b6a1331b775909b48c2f516c40dcc8301635b7237b"); - let params = Params::new_with_all_params(Mode::default(), 16, 8, 1, 10, 0).unwrap(); - let mut actual = [0u8; 40]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat20() { - const EXPECTED: [u8; 40] = - hex!("9e7a4097644284cf3b73b60450ff230cdcb6b1b19b1509eeb482f696c4f1c705c00f740216183a12"); - let params = Params::new_with_all_params(Mode::Worm, 16, 8, 1, 10, 0).unwrap(); - let mut actual = [0u8; 40]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat21() { - const EXPECTED: [u8; 40] = - hex!("c8c7ff1122b0b291c3f2608948782cd689cc45579017aaa5ff8baa74a632ec99c3d66930fb2023bb"); - let params = Params::new(Mode::default(), 16, 8, 1).unwrap(); - let mut actual = [0u8; 40]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat22() { - const EXPECTED: [u8; 40] = - hex!("9dd636c2d0bb92345286efdaf8a68cfc1b4ffdc4b1adaccc7d864b9a6787b85d6ae0f5280da8889f"); - let params = Params::new(Mode::Worm, 16, 8, 1).unwrap(); - let mut actual = [0u8; 40]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat23() { - const EXPECTED: [u8; 32] = - hex!("c8c7ff1122b0b291c3f2608948782cd689cc45579017aaa5ff8baa74a632ec99"); - let params = Params::new(Mode::default(), 16, 8, 1).unwrap(); - let mut actual = [0u8; 32]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); -} - -#[test] -fn kat24() { - const EXPECTED: [u8; 8] = hex!("c8c7ff1122b0b291"); - let params = Params::new(Mode::default(), 16, 8, 1).unwrap(); - let mut actual = [0u8; 8]; - yescrypt(b"p", b"s", ¶ms, &mut actual).unwrap(); - assert_eq!(EXPECTED.as_slice(), actual.as_slice()); +#[path = "../data/test_vectors.rs"] +mod test_vectors; +use test_vectors::TEST_VECTORS; + +#[test] +fn kats() { + for test_vector in TEST_VECTORS { + let mut actual = vec![0u8; test_vector.output.len()]; + yescrypt( + test_vector.password, + test_vector.salt, + &test_vector.params(), + &mut actual, + ) + .unwrap(); + assert_eq!(test_vector.output, actual.as_slice()); + } } /// Regression test for RustCrypto/password-hashes#680 diff --git a/yescrypt/tests/mcf.rs b/yescrypt/tests/mcf.rs index 650ac52b..3eda105b 100644 --- a/yescrypt/tests/mcf.rs +++ b/yescrypt/tests/mcf.rs @@ -1,74 +1,32 @@ //! Tests for encoding password hash strings in Modular Crypt Format (MCF). #![cfg(feature = "password-hash")] -#![allow(non_snake_case)] use yescrypt::{ - CustomizedPasswordHasher, Mode, Params, PasswordHashRef, PasswordVerifier, Yescrypt, + CustomizedPasswordHasher, Params, PasswordHashRef, PasswordVerifier, Yescrypt, password_hash::Error, }; -const YESCRYPT_P: u32 = 11; - -// Don't use this as a real password!!! -const EXAMPLE_PASSWD: &[u8] = b"pleaseletmein"; -const EXAMPLE_SALT: &[u8] = b"WZaPV7LSUEKMo34."; - -/// Adapted from `TESTS-OK` in the yescrypt reference C implementation -/// https://github.com/openwall/yescrypt/blob/caa931d/TESTS-OK#L31-L66 -const EXAMPLE_HASHES: &[&str] = &[ - "$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.$HboGM6qPrsK.StKYGt6KErmUYtioHreJd98oIugoNB6", - "$y$jC4$LdJMENpBABJJ3hIHjB1B$jVg4HoqqpbmQv/NCpin.QCMagJ8o4QX7lXdzvVV0xFC", // TODO - "$y$/B3.6$LdJMENpBABJJ3hIHjB1$h8sE4hJo.BsdlfJr0.d8bNJNPZymH7Y3kLj4aY1Rfc8", - "$y$/A2$LdJMENpBABJJ3hIHj/$5IEld1eWdmh5lylrqHLF5dvA3ISpimEM9J1Dd05n/.3", - "$y$j91.5$LdJMENpBABJJ3hIH$ebKnn23URD5vyLgF9cP2EvVosrUXf7UErGRV0KmC6e6", - "$y$j80$LdJMENpBABJJ3h2$ysXVVJwuaVlI1BWoEKt/Bz3WNDDmdOWz/8KTQaHL1cC", - "$y$/7/.4$LdJMENpBABJJ3/$lXHleh7bIZMGNtJVxGVrsIWkEIXfBedlfPui/PITflC", - "$y$/6.$LdJMENpBABJJ$zQITmYSih5.CTY47x0IuE4wl.b3HzYGKKCSggakaQ22", - "$y$j5..3$LdJMENpBAB3$xi27PTUNd8NsChHeLOz85JFnUOyibRHkWzprowRlR5/", - "$y$j4/$LdJMENpBA/$tHlkpTQ8V/eEnTVau1uW36T97LIXlfPrEzdeV5SE5K7", - "$y$/3..2$LdJMENpB$tNczXFuNUd3HMqypStCRsEaL4e4KF7ZYLBe8Hbeg0B7", - "$y$/2/$LdJMEN3$RRorHhfsw1/P/WR6Aurg4U72e9Q7qt9vFPURdyfiqK8", - "$y$j2..1$LdJME/$iLEt6kuTwHch6XdCxtTHfsQzYwWFmpUwgl6Ax8RH4d1", - "$y$j0/$LdJM$k7BXzSDuoGHW56SY3HxROCiA0gWRscZe2aA0q5oHPM0", - "$y$//..0$Ld3$6BJXezMFxaMiO5wsuoEmztvtCs/79085dZO56ADlV5B", - "$y$///$L/$Rrrkp6OVljrIk0kcwkCDhAiHJiSthh3cKeIGHUW7Z0C", - "$y$j1../$LdJMENpBABJJ3hIHjB1Bi.$L8OQFc8mxJPd7CpUFgkS7KqJM2I9jGXu3BdqX2D.647", - "$y$j//$LdJMENpBABJJ3hIHjB1B$U8a2MaK.yesqWySK8Owk6PWeWmp/XuagMbpP45q1/q1", -]; +#[path = "../data/mcf_test_vectors.rs"] +mod test_vectors; +use test_vectors::MCF_TEST_VECTORS; /// `yescrypt()` tests #[test] fn compute_reference_strings() { - for (i, &expected_hash) in EXAMPLE_HASHES.iter().enumerate() { - let i = i as u32; - - // Test case logic adapted from the yescrypt C reference implementation (tests.c) - let mut N_log2 = if i < 14 { 16 - i } else { 2 }; - let r = if i < 8 { 8 - i } else { 1 + (i & 1) }; - let mut p = if i & 1 == 1 { 1 } else { YESCRYPT_P }; - let mut flags = Mode::default(); - - if p.saturating_sub(i / 2) > 1 { - p -= i / 2; - } - - if i & 2 != 0 { - flags = Mode::Worm; - } else { - while (1 << N_log2) / p <= 3 { - N_log2 += 1; - } - } - - let params = Params::new(flags, 1 << N_log2, r, p).unwrap(); - let salt = &EXAMPLE_SALT[..(16 - (i as usize & 15))]; - + for test_vector in MCF_TEST_VECTORS { + let params = Params::new( + test_vector.mode, + test_vector.n, + test_vector.r, + test_vector.p, + ) + .unwrap(); let actual_hash = Yescrypt::default() - .hash_password_with_params(EXAMPLE_PASSWD, salt, params) + .hash_password_with_params(test_vector.password, test_vector.salt(), params) .unwrap(); - assert_eq!(expected_hash, actual_hash.as_str()); + assert_eq!(test_vector.expected_hash, actual_hash.as_str()); } } @@ -77,9 +35,9 @@ fn compute_reference_strings() { fn verify_reference_strings() { let yescrypt = Yescrypt::default(); - for &hash in EXAMPLE_HASHES { - let hash = PasswordHashRef::new(hash).unwrap(); - assert_eq!(yescrypt.verify_password(EXAMPLE_PASSWD, hash), Ok(())); + for test_vector in MCF_TEST_VECTORS { + let hash = PasswordHashRef::new(test_vector.expected_hash).unwrap(); + assert_eq!(yescrypt.verify_password(test_vector.password, hash), Ok(())); assert_eq!( yescrypt.verify_password(b"bogus", hash), From 9e1144be5483d9cd1d63ddd83003451d0e7cbe69 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Fri, 27 Mar 2026 21:42:43 -0400 Subject: [PATCH 11/11] leave those in --- yescrypt/benches/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yescrypt/benches/lib.rs b/yescrypt/benches/lib.rs index fbf11d85..418efe05 100644 --- a/yescrypt/benches/lib.rs +++ b/yescrypt/benches/lib.rs @@ -27,7 +27,7 @@ fn bench_test_vector(bh: &mut Bencher, test_vector: &TestVector) { &mut buf[..test_vector.output.len()], ) .unwrap(); - // assert_eq!(test_vector.output, &buf[..test_vector.output.len()]); + assert_eq!(test_vector.output, &buf[..test_vector.output.len()]); }); } @@ -46,7 +46,7 @@ fn bench_hash_mcf(bh: &mut Bencher, test_vector: &McfTestVector) { let hash = Yescrypt::default() .hash_password_with_params(test_vector.password, salt, params) .unwrap(); - // assert_eq!(test_vector.expected_hash, hash.as_str()); + assert_eq!(test_vector.expected_hash, hash.as_str()); }); }