use dever_runtime::{crypto, value::secret::Secret}; fn hex(bytes: &[u8]) -> String { bytes.iter().map(|byte| format!("{byte:02x}")).collect() } #[test] fn secret_debug_is_redacted_and_token_bounds_are_fixed() { let secret = Secret::from_input(b"test-only-sensitive-input".to_vec()); assert_eq!(format!("{secret:?}"), "Secret([REDACTED])"); assert_eq!(format!("{:?}", secret.clone()), "Secret([REDACTED])"); for length in [-1, 0, 15, 1025] { assert!(crypto::token(length).is_err()); } assert!(crypto::token(16).is_ok()); assert!(crypto::token(1024).is_ok()); } #[test] fn sha256_and_hmac_match_known_vectors() { assert_eq!( hex(&crypto::sha256(b"abc")), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" ); let key = Secret::from_input(vec![0x0b; 20]); assert_eq!( hex(&crypto::hmac_sha256(&key, b"Hi There")), "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7" ); } #[test] fn content_comparison_has_the_declared_value_semantics() { assert!(crypto::constant_time_eq(b"", b"")); assert!(crypto::constant_time_eq(b"same", b"same")); assert!(!crypto::constant_time_eq(b"same", b"sXme")); assert!(!crypto::constant_time_eq(b"same", b"sam")); } #[test] fn passwords_use_the_existing_profile_and_distinguish_mismatch_from_invalid_hash() { let password = Secret::from_input(b"test-only-password".to_vec()); let wrong = Secret::from_input(b"other-test-password".to_vec()); let encoded = crypto::password_hash(&password).unwrap(); assert!(encoded.starts_with("$argon2id$v=19$m=19456,t=2,p=1$")); assert_eq!(crypto::password_verify(&password, &encoded), Ok(true)); assert_eq!( crypto::password_verify(&password.clone(), &encoded), Ok(true) ); assert_eq!(crypto::password_verify(&wrong, &encoded), Ok(false)); assert!(crypto::password_verify(&password, "not a hash").is_err()); } #[test] fn raw_phc_costs_are_rejected_before_parameter_arithmetic_or_hashing() { let password = Secret::from_input(b"test-only-password".to_vec()); let encoded = "$argon2id$v=19$m=19456,t=2,p=1$c29tZXNhbHQ$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; for invalid in [ encoded.replace("m=19456", "m=19457"), encoded.replace("t=2", "t=3"), encoded.replace("p=1", "p=2"), encoded.replace("p=1", "p=536870912"), encoded.replace("p=1", "p=0"), encoded.replace("p=1", "p=invalid"), encoded.replace("$v=19$", "$v=16$"), encoded.replace("argon2id", "argon2i"), encoded.replace("p=1", "p=1,data=YQ"), encoded.replace("p=1", "p=1,keyid=YQ"), "x".repeat(257), ] { assert!( crypto::password_verify(&password, &invalid).is_err(), "{invalid}" ); } }