chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

220
vendor/argon2/tests/phc_strings.rs vendored Normal file
View File

@@ -0,0 +1,220 @@
//! Test vectors for Argon2 password hashes in the PHC string format
//!
//! Adapted from: <https://github.com/P-H-C/phc-winner-argon2/blob/master/src/test.c>
#![cfg(all(feature = "alloc", feature = "password-hash"))]
use argon2::{
Algorithm, Argon2, AssociatedData, KeyId, ParamsBuilder, PasswordHash, PasswordHasher,
PasswordVerifier, Version,
};
use password_hash::{
errors::{Error, InvalidValue},
SaltString,
};
/// Valid password
pub const VALID_PASSWORD: &[u8] = b"password";
/// Invalid password
pub const INVALID_PASSWORD: &[u8] = b"sassword";
/// Password hashes for "password"
pub const VALID_PASSWORD_HASHES: &[&str] = &[
"$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQAAAAAAAAAAA$+r0d29hqEB0yasKr55ZgICsQGSkl0v0kgwhd+U3wyRo",
"$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow",
"$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc",
"$argon2d$v=19$m=65536,t=2,p=1$YzI5dFpYTmhiSFFBQUFBQUFBQUFBQQ$Jxy74cswY2mq9y+u+iJcJy8EqOp4t/C7DWDzGwGB3IM",
// Password with optional keyid
"$argon2d$v=19$m=65536,t=2,p=1,keyid=8PDw8A$YzI5dFpYTmhiSFFBQUFBQUFBQUFBQQ$Jxy74cswY2mq9y+u+iJcJy8EqOp4t/C7DWDzGwGB3IM",
// Password with optional data
"$argon2d$v=16$m=32,t=2,p=3,data=Dw8PDw8P$AAAAAAAAAAA$KnH4gniiaFnDvlA1xev3yovC4cnrrI6tnHOYtmja90o",
// Password with optional keyid&data
"$argon2d$v=16$m=32,t=2,p=3,keyid=8PDw8A,data=Dw8PDw8P$AAAAAAAAAAA$KnH4gniiaFnDvlA1xev3yovC4cnrrI6tnHOYtmja90o",
];
#[test]
fn verifies_correct_password() {
for hash_string in VALID_PASSWORD_HASHES {
let hash = PasswordHash::new(hash_string).unwrap();
assert_eq!(
Argon2::default().verify_password(VALID_PASSWORD, &hash),
Ok(())
);
}
}
#[test]
fn rejects_incorrect_password() {
for hash_string in VALID_PASSWORD_HASHES {
let hash = PasswordHash::new(hash_string).unwrap();
assert!(Argon2::default()
.verify_password(INVALID_PASSWORD, &hash)
.is_err());
}
}
// Test PHC string format according to spec
// see: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md#argon2-encoding
macro_rules! testcase_bad_encoding {
($name: ident, $err: expr, $hash: expr) => {
#[test]
fn $name() {
let hash = PasswordHash::new($hash).unwrap();
assert_eq!(
Argon2::default().verify_password(b"password", &hash),
Err($err)
);
}
};
}
macro_rules! ignored_testcase_bad_encoding {
($name: ident, $err: expr, $hash: expr) => {
#[test]
#[ignore]
fn $name() {
let hash = PasswordHash::new($hash).unwrap();
assert_eq!(
Argon2::default().verify_password(b"password", &hash),
Err($err)
);
}
};
}
testcase_bad_encoding!(
argon2i_invalid_encoding_invalid_version,
Error::Version,
"$argon2i$v=42$m=65536,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_m_not_a_number,
Error::ParamValueInvalid(InvalidValue::InvalidChar('d')),
"$argon2i$m=dummy,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_m_too_small,
Error::ParamValueInvalid(InvalidValue::TooShort),
"$argon2i$m=0,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_m_too_big,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2i$m=4294967296,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_t_not_a_number,
Error::ParamValueInvalid(InvalidValue::InvalidChar('d')),
"$argon2i$m=65536,t=dummy,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_t_too_small,
Error::ParamValueInvalid(InvalidValue::TooShort),
"$argon2i$m=65536,t=0,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_t_too_big,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2i$m=65536,t=4294967296,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_p_not_a_number,
Error::ParamValueInvalid(InvalidValue::InvalidChar('d')),
"$argon2i$m=65536,t=2,p=dummy$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_p_too_small,
Error::ParamValueInvalid(InvalidValue::TooShort),
"$argon2i$m=65536,t=2,p=0$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
// TODO: Wrong error is returned, this should be changed in the `password-hash` crate
ignored_testcase_bad_encoding!(
argon2i_invalid_encoding_p_too_big,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2i$m=65536,t=2,p=256$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_keyid_not_b64,
Error::B64Encoding(base64ct::Error::InvalidEncoding),
"$argon2i$m=65536,t=2,p=1,keyid=dummy$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
testcase_bad_encoding!(
argon2i_invalid_encoding_data_not_b64,
Error::B64Encoding(base64ct::Error::InvalidEncoding),
"$argon2i$m=65536,t=2,p=1,data=dummy$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"
);
#[test]
fn check_decoding_supports_out_of_order_parameters() {
// parameters order is not mandatory
let hash = "$argon2d$v=16$m=32,t=2,p=3,keyid=8PDw8A,data=Dw8PDw8P$AAAAAAAAAAA$KnH4gniiaFnDvlA1xev3yovC4cnrrI6tnHOYtmja90o";
let hash = PasswordHash::new(hash).unwrap();
assert!(Argon2::default()
.verify_password(b"password", &hash)
.is_ok());
}
// TODO: Fix default parameters for decoding !
#[test]
#[ignore]
fn check_decoding_supports_default_parameters() {
// parameters order is not mandatory
let hash = "$argon2i$p=2,m=256,t=2$c29tZXNhbHQ$tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs";
let hash = PasswordHash::new(hash).unwrap();
assert!(Argon2::default()
.verify_password(b"password", &hash)
.is_ok());
}
// m/t/p parameters are NOT optional according to spec
// TODO: Wrong error is returned, this should be changed in the `password-hash` crate
ignored_testcase_bad_encoding!(
argon2i_invalid_encoding_missing_m,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2d$v=16$t=2,p=3$8PDw8PDw8PA$Xv5daH0zPuKO3c9tMBG/WOIUsDrPqq815/xyQTukNxY"
);
// TODO: Wrong error is returned, this should be changed in the `password-hash` crate
ignored_testcase_bad_encoding!(
argon2i_invalid_encoding_missing_t,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2d$v=16$m=32,p=3$8PDw8PDw8PA$Xv5daH0zPuKO3c9tMBG/WOIUsDrPqq815/xyQTukNxY"
);
// TODO: Wrong error is returned, this should be changed in the `password-hash` crate
ignored_testcase_bad_encoding!(
argon2i_invalid_encoding_missing_p,
Error::ParamValueInvalid(InvalidValue::InvalidFormat),
"$argon2d$v=16$m=32,t=2$8PDw8PDw8PA$Xv5daH0zPuKO3c9tMBG/WOIUsDrPqq815/xyQTukNxY"
);
// Missing&invalid id/salt/hash fields is handled by `PasswordHash` so no need to test that here
#[test]
fn check_hash_encoding_parameters_order() {
let params = ParamsBuilder::new()
.m_cost(32)
.t_cost(2)
.p_cost(3)
.data(AssociatedData::new(&[0x0f; 6]).unwrap())
.keyid(KeyId::new(&[0xf0; 4]).unwrap())
.build()
.unwrap();
let ctx = Argon2::new(Algorithm::Argon2d, Version::V0x10, params);
let salt = vec![0; 8];
let password = b"password";
let salt_string = SaltString::encode_b64(&salt).unwrap();
let password_hash = ctx
.hash_password(password, &salt_string)
.unwrap()
.to_string();
// The parameters shall appear in the m,t,p,keyid,data order
assert_eq!(password_hash, "$argon2d$v=16$m=32,t=2,p=3,keyid=8PDw8A,data=Dw8PDw8P$AAAAAAAAAAA$KnH4gniiaFnDvlA1xev3yovC4cnrrI6tnHOYtmja90o");
}