830 lines
25 KiB
Rust
830 lines
25 KiB
Rust
//! Argon2 Known Answer Tests (KAT).
|
|
//!
|
|
//! Taken from the Argon2 reference implementation as well as
|
|
//! `draft-irtf-cfrg-argon2-12` Section 5:
|
|
//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/>
|
|
|
|
#![cfg(all(feature = "alloc", feature = "password-hash"))]
|
|
|
|
// TODO(tarcieri): test full set of vectors from the reference implementation:
|
|
// https://github.com/P-H-C/phc-winner-argon2/blob/master/src/test.c
|
|
|
|
use argon2::{
|
|
Algorithm, Argon2, AssociatedData, Error, Params, ParamsBuilder, PasswordHash, PasswordHasher,
|
|
PasswordVerifier, Version,
|
|
};
|
|
use hex_literal::hex;
|
|
use password_hash::SaltString;
|
|
|
|
/// Params used by the KATs.
|
|
fn example_params() -> Params {
|
|
ParamsBuilder::new()
|
|
.m_cost(32)
|
|
.t_cost(3)
|
|
.p_cost(4)
|
|
.data(AssociatedData::new(&[0x04; 12]).unwrap())
|
|
.build()
|
|
.unwrap()
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2d version number 16
|
|
/// =======================================
|
|
/// Memory: 32 KiB, Iterations: 3, Parallelism: 4 lanes, Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// ec dc 26 dc 6b dd 21 56 19 68 97 aa 8c c9 a0 4c
|
|
/// 03 ed 07 cd 12 92 67 c5 3c a6 ae f7 76 a4 30 89
|
|
/// 6a 09 80 54 e4 de c3 e0 2e cd 82 c4 7f 56 2c a2
|
|
/// 73 d2 f6 97 8a 5c 05 41 1a 0c d0 9d 47 7b 7b 06
|
|
/// Tag[32]:
|
|
/// 96 a9 d4 e5 a1 73 40 92 c8 5e 29 f4 10 a4 59 14
|
|
/// a5 dd 1f 5c bf 08 b2 67 0d a6 8a 02 85 ab f3 2b
|
|
#[test]
|
|
fn argon2d_v0x10() {
|
|
let algorithm = Algorithm::Argon2d;
|
|
let version = Version::V0x10;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
96 a9 d4 e5 a1 73 40 92 c8 5e 29 f4 10 a4 59 14
|
|
a5 dd 1f 5c bf 08 b2 67 0d a6 8a 02 85 ab f3 2b
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2i version number 16
|
|
/// =======================================
|
|
/// Memory: 32 KiB, Iterations: 3, Parallelism: 4 lanes, Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// 1c dc ec c8 58 ca 1b 6d 45 c7 3c 78 d0 00 76 c5
|
|
/// ec fc 5e df 14 45 b4 43 73 97 b1 b8 20 83 ff bf
|
|
/// e3 c9 1a a8 f5 06 67 ad 8f b9 d4 e7 52 df b3 85
|
|
/// 34 71 9f ba d2 22 61 33 7b 2b 55 29 81 44 09 af
|
|
/// Tag[32]:
|
|
/// 87 ae ed d6 51 7a b8 30 cd 97 65 cd 82 31 ab b2
|
|
/// e6 47 a5 de e0 8f 7c 05 e0 2f cb 76 33 35 d0 fd
|
|
#[test]
|
|
fn argon2i_v0x10() {
|
|
let algorithm = Algorithm::Argon2i;
|
|
let version = Version::V0x10;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
87 ae ed d6 51 7a b8 30 cd 97 65 cd 82 31 ab b2
|
|
e6 47 a5 de e0 8f 7c 05 e0 2f cb 76 33 35 d0 fd
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2id version number 16
|
|
/// =======================================
|
|
/// Memory: 32 KiB, Iterations: 3, Parallelism: 4 lanes, Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// 70 65 ab 9c 82 b5 f0 e8 71 28 c7 84 7a 02 1d 1e
|
|
/// 59 aa 16 66 6f c8 b4 ef ac a3 86 3f bf d6 5e 0e
|
|
/// 8b a6 f6 09 eb bc 9b 60 e2 78 22 c8 24 b7 50 6f
|
|
/// b9 f9 5b e9 0e e5 84 2a ac 6e d6 b7 da 67 30 44
|
|
/// Tag[32]:
|
|
/// b6 46 15 f0 77 89 b6 6b 64 5b 67 ee 9e d3 b3 77
|
|
/// ae 35 0b 6b fc bb 0f c9 51 41 ea 8f 32 26 13 c0
|
|
#[test]
|
|
fn argon2id_v0x10() {
|
|
let algorithm = Algorithm::Argon2id;
|
|
let version = Version::V0x10;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
b6 46 15 f0 77 89 b6 6b 64 5b 67 ee 9e d3 b3 77
|
|
ae 35 0b 6b fc bb 0f c9 51 41 ea 8f 32 26 13 c0
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2d version number 19
|
|
/// =======================================
|
|
/// Memory: 32 KiB
|
|
/// Passes: 3
|
|
/// Parallelism: 4 lanes
|
|
/// Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// b8 81 97 91 a0 35 96 60
|
|
/// bb 77 09 c8 5f a4 8f 04
|
|
/// d5 d8 2c 05 c5 f2 15 cc
|
|
/// db 88 54 91 71 7c f7 57
|
|
/// 08 2c 28 b9 51 be 38 14
|
|
/// 10 b5 fc 2e b7 27 40 33
|
|
/// b9 fd c7 ae 67 2b ca ac
|
|
/// 5d 17 90 97 a4 af 31 09
|
|
/// Tag[32]:
|
|
/// 51 2b 39 1b 6f 11 62 97
|
|
/// 53 71 d3 09 19 73 42 94
|
|
/// f8 68 e3 be 39 84 f3 c1
|
|
/// a1 3a 4d b9 fa be 4a cb
|
|
#[test]
|
|
fn argon2d_v0x13() {
|
|
let algorithm = Algorithm::Argon2d;
|
|
let version = Version::V0x13;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
51 2b 39 1b 6f 11 62 97
|
|
53 71 d3 09 19 73 42 94
|
|
f8 68 e3 be 39 84 f3 c1
|
|
a1 3a 4d b9 fa be 4a cb
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2i version number 19
|
|
/// =======================================
|
|
/// Memory: 32 KiB
|
|
/// Passes: 3
|
|
/// Parallelism: 4 lanes
|
|
/// Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// c4 60 65 81 52 76 a0 b3
|
|
/// e7 31 73 1c 90 2f 1f d8
|
|
/// 0c f7 76 90 7f bb 7b 6a
|
|
/// 5c a7 2e 7b 56 01 1f ee
|
|
/// ca 44 6c 86 dd 75 b9 46
|
|
/// 9a 5e 68 79 de c4 b7 2d
|
|
/// 08 63 fb 93 9b 98 2e 5f
|
|
/// 39 7c c7 d1 64 fd da a9
|
|
/// Tag[32]:
|
|
/// c8 14 d9 d1 dc 7f 37 aa
|
|
/// 13 f0 d7 7f 24 94 bd a1
|
|
/// c8 de 6b 01 6d d3 88 d2
|
|
/// 99 52 a4 c4 67 2b 6c e8
|
|
#[test]
|
|
fn argon2i_v0x13() {
|
|
let algorithm = Algorithm::Argon2i;
|
|
let version = Version::V0x13;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
c8 14 d9 d1 dc 7f 37 aa
|
|
13 f0 d7 7f 24 94 bd a1
|
|
c8 de 6b 01 6d d3 88 d2
|
|
99 52 a4 c4 67 2b 6c e8
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
/// =======================================
|
|
/// Argon2id version number 19
|
|
/// =======================================
|
|
/// Memory: 32 KiB, Passes: 3,
|
|
/// Parallelism: 4 lanes, Tag length: 32 bytes
|
|
/// Password[32]:
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
|
/// Salt[16]: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
|
|
/// Secret[8]: 03 03 03 03 03 03 03 03
|
|
/// Associated data[12]: 04 04 04 04 04 04 04 04 04 04 04 04
|
|
/// Pre-hashing digest:
|
|
/// 28 89 de 48 7e b4 2a e5 00 c0 00 7e d9 25 2f 10
|
|
/// 69 ea de c4 0d 57 65 b4 85 de 6d c2 43 7a 67 b8
|
|
/// 54 6a 2f 0a cc 1a 08 82 db 8f cf 74 71 4b 47 2e
|
|
/// 94 df 42 1a 5d a1 11 2f fa 11 43 43 70 a1 e9 97
|
|
/// Tag[32]:
|
|
/// 0d 64 0d f5 8d 78 76 6c 08 c0 37 a3 4a 8b 53 c9
|
|
/// d0 1e f0 45 2d 75 b6 5e b5 25 20 e9 6b 01 e6 59
|
|
#[test]
|
|
fn argon2id_v0x13() {
|
|
let algorithm = Algorithm::Argon2id;
|
|
let version = Version::V0x13;
|
|
let params = example_params();
|
|
let password = [0x01; 32];
|
|
let salt = [0x02; 16];
|
|
let secret = [0x03; 8];
|
|
let expected_tag = hex!(
|
|
"
|
|
0d 64 0d f5 8d 78 76 6c 08 c0 37 a3 4a 8b 53 c9
|
|
d0 1e f0 45 2d 75 b6 5e b5 25 20 e9 6b 01 e6 59
|
|
"
|
|
);
|
|
|
|
let ctx = Argon2::new_with_secret(&secret, algorithm, version, params).unwrap();
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(&password, &salt, &mut out).unwrap();
|
|
|
|
assert_eq!(out, expected_tag);
|
|
}
|
|
|
|
// =======================================
|
|
// Basic error checks
|
|
// =======================================
|
|
|
|
#[test]
|
|
fn salt_bad_length() {
|
|
let ctx = Argon2::new(Algorithm::Argon2id, Version::V0x13, example_params());
|
|
let mut out = [0u8; 32];
|
|
|
|
let too_short_salt = [0u8; argon2::MIN_SALT_LEN - 1];
|
|
let ret = ctx.hash_password_into(b"password", &too_short_salt, &mut out);
|
|
assert_eq!(ret, Err(Error::SaltTooShort));
|
|
|
|
#[cfg(target_pointer_width = "64")] // MAX_SALT_LEN + 1 is too big for 32-bit targets
|
|
{
|
|
// 4 GiB of RAM seems big, but as long as we ask for a zero-initialized vector
|
|
// optimizations kicks in an nothing is really allocated
|
|
let too_long_salt = vec![0u8; argon2::MAX_SALT_LEN + 1];
|
|
let ret = ctx.hash_password_into(b"password", &too_long_salt, &mut out);
|
|
assert_eq!(ret, Err(Error::SaltTooLong));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn output_bad_length() {
|
|
let ctx = Argon2::new(Algorithm::Argon2id, Version::V0x13, example_params());
|
|
let mut out = [0u8; Params::MIN_OUTPUT_LEN - 1];
|
|
let ret = ctx.hash_password_into(b"password", b"diffsalt", &mut out);
|
|
assert_eq!(ret, Err(Error::OutputTooShort));
|
|
|
|
#[cfg(target_pointer_width = "64")] // MAX_SALT_LEN + 1 is too big for 32-bit targets
|
|
{
|
|
// 4 GiB of RAM seems big, but as long as we ask for a zero-initialized vector
|
|
// optimizations kicks in an nothing is really allocated
|
|
let mut out = vec![0u8; Params::MAX_OUTPUT_LEN + 1];
|
|
let ret = ctx.hash_password_into(b"password", b"diffsalt", &mut out);
|
|
assert_eq!(ret, Err(Error::OutputTooLong));
|
|
}
|
|
}
|
|
|
|
// =======================================
|
|
// Reference implementation's test suite
|
|
// =======================================
|
|
// Taken from https://github.com/P-H-C/phc-winner-argon2/blob/master/src/test.c
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn hashtest(
|
|
algorithm: Algorithm,
|
|
version: Version,
|
|
t: u32,
|
|
m: u32,
|
|
p: u32,
|
|
pwd: &[u8],
|
|
salt: &[u8],
|
|
expected_raw_hash: [u8; 32],
|
|
expected_phc_hash: &str,
|
|
alternative_phc_hash: &str,
|
|
) {
|
|
let params = ParamsBuilder::new()
|
|
.t_cost(t)
|
|
.m_cost(1 << m)
|
|
.p_cost(p)
|
|
.build()
|
|
.unwrap();
|
|
|
|
let ctx = Argon2::new(algorithm, version, params);
|
|
|
|
// Test raw hash
|
|
let mut out = [0u8; 32];
|
|
ctx.hash_password_into(pwd, salt, &mut out).unwrap();
|
|
assert_eq!(out, expected_raw_hash);
|
|
|
|
// Test hash encoding
|
|
let salt_string = SaltString::encode_b64(salt).unwrap();
|
|
let phc_hash = ctx.hash_password(pwd, &salt_string).unwrap().to_string();
|
|
assert_eq!(phc_hash, expected_phc_hash);
|
|
|
|
let hash = PasswordHash::new(alternative_phc_hash).unwrap();
|
|
assert!(Argon2::default().verify_password(pwd, &hash).is_ok());
|
|
}
|
|
|
|
macro_rules! testcase_good {
|
|
($name: ident, $algorithm: expr, $version: expr, $t: expr, $m: expr, $p: expr, $pwd: expr, $salt: expr, $expected_raw: expr, $expected_phc: expr) => {
|
|
#[test]
|
|
fn $name() {
|
|
hashtest(
|
|
$algorithm,
|
|
$version,
|
|
$t,
|
|
$m,
|
|
$p,
|
|
$pwd,
|
|
$salt,
|
|
$expected_raw,
|
|
$expected_phc,
|
|
$expected_phc,
|
|
)
|
|
}
|
|
};
|
|
($name: ident, $algorithm: expr, $version: expr, $t: expr, $m: expr, $p: expr, $pwd: expr, $salt: expr, $expected_raw: expr, $expected_phc: expr, $alternative_phc: expr) => {
|
|
#[test]
|
|
fn $name() {
|
|
hashtest(
|
|
$algorithm,
|
|
$version,
|
|
$t,
|
|
$m,
|
|
$p,
|
|
$pwd,
|
|
$salt,
|
|
$expected_raw,
|
|
$expected_phc,
|
|
$alternative_phc,
|
|
)
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! ignored_testcase_good {
|
|
($name: ident, $algorithm: expr, $version: expr, $t: expr, $m: expr, $p: expr, $pwd: expr, $salt: expr, $expected_raw: expr, $expected_phc: expr, $alternative_phc: expr) => {
|
|
#[test]
|
|
#[ignore]
|
|
fn $name() {
|
|
hashtest(
|
|
$algorithm,
|
|
$version,
|
|
$t,
|
|
$m,
|
|
$p,
|
|
$pwd,
|
|
$salt,
|
|
$expected_raw,
|
|
$expected_phc,
|
|
$alternative_phc,
|
|
)
|
|
}
|
|
};
|
|
}
|
|
|
|
/* Argon2i V0x10: Multiple test cases for various input values */
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("f6c4db4a54e2a370627aff3db6176b94a2a209a62c8e36152711802f7b30c694"),
|
|
"$argon2i$v=16$m=65536,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
|
|
"$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
#[ignore]
|
|
#[cfg(feature = "test_large_ram")]
|
|
testcase_good!(
|
|
reference_argon2i_v0x10_2_20_1_large_ram,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
20,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("9690ec55d28d3ed32562f2e73ea62b02b018757643a2ae6e79528459de8106e9"),
|
|
"$argon2i$v=16$m=1048576,t=2,p=1$c29tZXNhbHQ$lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk",
|
|
"$argon2i$m=1048576,t=2,p=1$c29tZXNhbHQ$lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_18_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
18,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("3e689aaa3d28a77cf2bc72a51ac53166761751182f1ee292e3f677a7da4c2467"),
|
|
"$argon2i$v=16$m=262144,t=2,p=1$c29tZXNhbHQ$Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc",
|
|
"$argon2i$m=262144,t=2,p=1$c29tZXNhbHQ$Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_8_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
8,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("fd4dd83d762c49bdeaf57c47bdcd0c2f1babf863fdeb490df63ede9975fccf06"),
|
|
"$argon2i$v=16$m=256,t=2,p=1$c29tZXNhbHQ$/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY",
|
|
"$argon2i$m=256,t=2,p=1$c29tZXNhbHQ$/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_8_2,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
8,
|
|
2,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("b6c11560a6a9d61eac706b79a2f97d68b4463aa3ad87e00c07e2b01e90c564fb"),
|
|
"$argon2i$v=16$m=256,t=2,p=2$c29tZXNhbHQ$tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs",
|
|
"$argon2i$m=256,t=2,p=2$c29tZXNhbHQ$tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_1_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
1,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("81630552b8f3b1f48cdb1992c4c678643d490b2b5eb4ff6c4b3438b5621724b2"),
|
|
"$argon2i$v=16$m=65536,t=1,p=1$c29tZXNhbHQ$gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI",
|
|
"$argon2i$m=65536,t=1,p=1$c29tZXNhbHQ$gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_4_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
4,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("f212f01615e6eb5d74734dc3ef40ade2d51d052468d8c69440a3a1f2c1c2847b"),
|
|
"$argon2i$v=16$m=65536,t=4,p=1$c29tZXNhbHQ$8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs",
|
|
"$argon2i$m=65536,t=4,p=1$c29tZXNhbHQ$8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_16_1_differentpassword,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
16,
|
|
1,
|
|
b"differentpassword",
|
|
b"somesalt",
|
|
hex!("e9c902074b6754531a3a0be519e5baf404b30ce69b3f01ac3bf21229960109a3"),
|
|
"$argon2i$v=16$m=65536,t=2,p=1$c29tZXNhbHQ$6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM",
|
|
"$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM"
|
|
);
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
ignored_testcase_good!(
|
|
reference_argon2i_v0x10_2_16_1_diffsalt,
|
|
Algorithm::Argon2i,
|
|
Version::V0x10,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"diffsalt",
|
|
hex!("79a103b90fe8aef8570cb31fc8b22259778916f8336b7bdac3892569d4f1c497"),
|
|
"$argon2i$v=16$m=65536,t=2,p=1$ZGlmZnNhbHQ$eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc",
|
|
"$argon2i$m=65536,t=2,p=1$ZGlmZnNhbHQ$eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc"
|
|
);
|
|
|
|
/* Argon2i V0x10: Error state tests */
|
|
|
|
// TODO: If version is not provided, verifier incorrectly uses version 0x13
|
|
#[ignore]
|
|
#[test]
|
|
fn reference_argon2i_v0x10_mismatching_hash() {
|
|
/* Handle an mismatching hash (the encoded password is "passwore") */
|
|
let hash = PasswordHash::new(
|
|
"$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo",
|
|
)
|
|
.unwrap();
|
|
assert_eq!(
|
|
Argon2::default().verify_password(b"password", &hash),
|
|
Err(password_hash::errors::Error::Password)
|
|
);
|
|
}
|
|
|
|
/* Argon2i V0x13: Multiple test cases for various input values */
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("c1628832147d9720c5bd1cfd61367078729f6dfb6f8fea9ff98158e0d7816ed0"),
|
|
"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA"
|
|
);
|
|
|
|
#[cfg(feature = "test_large_ram")]
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_20_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
20,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("d1587aca0922c3b5d6a83edab31bee3c4ebaef342ed6127a55d19b2351ad1f41"),
|
|
"$argon2i$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ$0Vh6ygkiw7XWqD7asxvuPE667zQu1hJ6VdGbI1GtH0E"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_18_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
18,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("296dbae80b807cdceaad44ae741b506f14db0959267b183b118f9b24229bc7cb"),
|
|
"$argon2i$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$KW266AuAfNzqrUSudBtQbxTbCVkmexg7EY+bJCKbx8s"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_8_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
8,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("89e9029f4637b295beb027056a7336c414fadd43f6b208645281cb214a56452f"),
|
|
"$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_8_2,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
8,
|
|
2,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("4ff5ce2769a1d7f4c8a491df09d41a9fbe90e5eb02155a13e4c01e20cd4eab61"),
|
|
"$argon2i$v=19$m=256,t=2,p=2$c29tZXNhbHQ$T/XOJ2mh1/TIpJHfCdQan76Q5esCFVoT5MAeIM1Oq2E"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_1_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
1,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("d168075c4d985e13ebeae560cf8b94c3b5d8a16c51916b6f4ac2da3ac11bbecf"),
|
|
"$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQ$0WgHXE2YXhPr6uVgz4uUw7XYoWxRkWtvSsLaOsEbvs8"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_4_16_1,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
4,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("aaa953d58af3706ce3df1aefd4a64a84e31d7f54175231f1285259f88174ce5b"),
|
|
"$argon2i$v=19$m=65536,t=4,p=1$c29tZXNhbHQ$qqlT1YrzcGzj3xrv1KZKhOMdf1QXUjHxKFJZ+IF0zls"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_16_1_differentpassword,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"differentpassword",
|
|
b"somesalt",
|
|
hex!("14ae8da01afea8700c2358dcef7c5358d9021282bd88663a4562f59fb74d22ee"),
|
|
"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$FK6NoBr+qHAMI1jc73xTWNkCEoK9iGY6RWL1n7dNIu4"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2i_v0x13_2_16_1_diffsalt,
|
|
Algorithm::Argon2i,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"diffsalt",
|
|
hex!("b0357cccfbef91f3860b0dba447b2348cbefecadaf990abfe9cc40726c521271"),
|
|
"$argon2i$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ$sDV8zPvvkfOGCw26RHsjSMvv7K2vmQq/6cxAcmxSEnE"
|
|
);
|
|
|
|
#[test]
|
|
fn reference_argon2i_v0x13_mismatching_hash() {
|
|
/* Handle an mismatching hash (the encoded password is "passwore") */
|
|
let hash = PasswordHash::new(
|
|
"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM",
|
|
)
|
|
.unwrap();
|
|
assert_eq!(
|
|
Argon2::default().verify_password(b"password", &hash),
|
|
Err(password_hash::errors::Error::Password)
|
|
);
|
|
}
|
|
|
|
/* Argon2id V0x13: Multiple test cases for various input values */
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_16_1,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("09316115d5cf24ed5a15a31a3ba326e5cf32edc24702987c02b6566f61913cf7"),
|
|
"$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_18_1,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
18,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("78fe1ec91fb3aa5657d72e710854e4c3d9b9198c742f9616c2f085bed95b2e8c"),
|
|
"$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_8_1,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
8,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("9dfeb910e80bad0311fee20f9c0e2b12c17987b4cac90c2ef54d5b3021c68bfe"),
|
|
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_8_2,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
8,
|
|
2,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("6d093c501fd5999645e0ea3bf620d7b8be7fd2db59c20d9fff9539da2bf57037"),
|
|
"$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ$bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_1_16_1,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
1,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("f6a5adc1ba723dddef9b5ac1d464e180fcd9dffc9d1cbf76cca2fed795d9ca98"),
|
|
"$argon2id$v=19$m=65536,t=1,p=1$c29tZXNhbHQ$9qWtwbpyPd3vm1rB1GThgPzZ3/ydHL92zKL+15XZypg"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_4_16_1,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
4,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"somesalt",
|
|
hex!("9025d48e68ef7395cca9079da4c4ec3affb3c8911fe4f86d1a2520856f63172c"),
|
|
"$argon2id$v=19$m=65536,t=4,p=1$c29tZXNhbHQ$kCXUjmjvc5XMqQedpMTsOv+zyJEf5PhtGiUghW9jFyw"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_16_1_differentpassword,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"differentpassword",
|
|
b"somesalt",
|
|
hex!("0b84d652cf6b0c4beaef0dfe278ba6a80df6696281d7e0d2891b817d8c458fde"),
|
|
"$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$C4TWUs9rDEvq7w3+J4umqA32aWKB1+DSiRuBfYxFj94"
|
|
);
|
|
|
|
testcase_good!(
|
|
reference_argon2id_v0x13_2_16_1_diffsalt,
|
|
Algorithm::Argon2id,
|
|
Version::V0x13,
|
|
2,
|
|
16,
|
|
1,
|
|
b"password",
|
|
b"diffsalt",
|
|
hex!("bdf32b05ccc42eb15d58fd19b1f856b113da1e9a5874fdcc544308565aa8141c"),
|
|
"$argon2id$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ$vfMrBczELrFdWP0ZsfhWsRPaHppYdP3MVEMIVlqoFBw"
|
|
);
|