#[cfg(test)]
mod constant_time_comparison {
use crate::constant_time::ConstantTimeOps;
#[test]
fn test_equal_tokens_return_true() {
let token1 = b"valid_jwt_token_12345";
let token2 = b"valid_jwt_token_12345";
assert!(ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_different_tokens_return_false() {
let token1 = b"valid_jwt_token_12345";
let token2 = b"invalid_jwt_token_54321";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_mismatch_at_start() {
let token1 = b"AAAAAAAAAAAAAAAAAAAAA";
let token2 = b"BBBBBBBBBBBBBBBBBBBBB";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_mismatch_at_middle() {
let token1 = b"AAAAAAAAAABAAAAAAAAAA";
let token2 = b"AAAAAAAAAABAAAAAAAAA";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_mismatch_at_end() {
let token1 = b"AAAAAAAAAAAAAAAAAAAAA";
let token2 = b"AAAAAAAAAAAAAAAAAAAAB";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_empty_tokens_equal() {
let token1 = b"";
let token2 = b"";
assert!(ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_different_lengths() {
let token1 = b"short";
let token2 = b"much_longer_token";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_jwt_valid_signature() {
let valid_jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature123";
let same_jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature123";
assert!(ConstantTimeOps::compare_str(valid_jwt, same_jwt));
}
#[test]
fn test_jwt_invalid_signature() {
let valid_jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature123";
let invalid_jwt =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature999";
assert!(!ConstantTimeOps::compare_str(valid_jwt, invalid_jwt));
}
#[test]
fn test_jwt_tampered_payload() {
let original = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature123";
let tampered = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbjEyM30.signature123";
assert!(!ConstantTimeOps::compare_str(original, tampered));
}
#[test]
fn test_session_token_valid() {
let token1 = "sess_abcdef123456:hmac_signature_value_xyz";
let token2 = "sess_abcdef123456:hmac_signature_value_xyz";
assert!(ConstantTimeOps::compare_str(token1, token2));
}
#[test]
fn test_session_token_invalid_session_id() {
let token1 = "sess_abcdef123456:hmac_signature_value_xyz";
let token2 = "sess_different654321:hmac_signature_value_xyz";
assert!(!ConstantTimeOps::compare_str(token1, token2));
}
#[test]
fn test_session_token_invalid_signature() {
let token1 = "sess_abcdef123456:hmac_signature_value_xyz";
let token2 = "sess_abcdef123456:hmac_signature_value_abc";
assert!(!ConstantTimeOps::compare_str(token1, token2));
}
#[test]
fn test_csrf_token_valid() {
let token1 = "csrf_token_abcdefghijklmnopqrstuvwxyz";
let token2 = "csrf_token_abcdefghijklmnopqrstuvwxyz";
assert!(ConstantTimeOps::compare_str(token1, token2));
}
#[test]
fn test_csrf_token_invalid() {
let token1 = "csrf_token_abcdefghijklmnopqrstuvwxyz";
let token2 = "csrf_token_zyxwvutsrqponmlkjihgfedcba";
assert!(!ConstantTimeOps::compare_str(token1, token2));
}
#[test]
fn test_mismatch_position_doesnt_affect_comparison() {
let base = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
let mut mismatch_start = base.to_vec();
mismatch_start[0] = b'B';
assert!(!ConstantTimeOps::compare(base, &mismatch_start));
let mut mismatch_middle = base.to_vec();
mismatch_middle[16] = b'B';
assert!(!ConstantTimeOps::compare(base, &mismatch_middle));
let mut mismatch_end = base.to_vec();
mismatch_end[33] = b'B';
assert!(!ConstantTimeOps::compare(base, &mismatch_end));
}
#[test]
fn test_multiple_bit_flips_same_result() {
let token1 = b"abcdefghijklmnopqrstuvwxyz123456";
let token2 = b"abXdefgXijklmnXpqrstuvwXyz12X456";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_single_bit_flip() {
let token1 = b"abcdefghijklmnopqrstuvwxyz123456";
let token2 = b"abcdefghijklmnopqrstuvwxyz123457";
assert!(!ConstantTimeOps::compare(token1, token2));
}
#[test]
fn test_hmac_signatures_equal() {
let sig1 = b"\x48\x6d\x61\x63\x5f\x76\x61\x6c\x75\x65\x5f\x78\x79\x7a\x5f\x31\x32\x33";
let sig2 = b"\x48\x6d\x61\x63\x5f\x76\x61\x6c\x75\x65\x5f\x78\x79\x7a\x5f\x31\x32\x33";
assert!(ConstantTimeOps::compare(sig1, sig2));
}
#[test]
fn test_hmac_signatures_different() {
let sig1 = b"\x48\x6d\x61\x63\x5f\x76\x61\x6c\x75\x65\x5f\x78\x79\x7a\x5f\x31\x32\x33";
let sig2 = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
assert!(!ConstantTimeOps::compare(sig1, sig2));
}
#[test]
fn test_brute_force_attempt_early_match() {
let valid_token = b"super_secret_token_xyz_abc_def_123";
let attack_1 = b"super_fake_token_qqq_bbb_ggg_456";
let attack_2 = b"super_secret_token_xyz_abc_def_999";
assert!(!ConstantTimeOps::compare(valid_token, attack_1));
assert!(!ConstantTimeOps::compare(valid_token, attack_2));
}
#[test]
fn test_token_with_null_bytes() {
let token1 = b"token\x00with\x00nulls";
let token2 = b"token\x00with\x00nulls";
let token3 = b"token\x00with\x00other";
assert!(ConstantTimeOps::compare(token1, token2));
assert!(!ConstantTimeOps::compare(token1, token3));
}
#[test]
fn test_token_with_all_byte_values() {
let mut token1 = vec![0u8; 256];
let mut token2 = vec![0u8; 256];
for (i, t) in token1.iter_mut().enumerate() {
*t = i as u8;
}
for (i, t) in token2.iter_mut().enumerate() {
*t = i as u8;
}
assert!(ConstantTimeOps::compare(&token1, &token2));
token2[127] = token2[127].wrapping_add(1);
assert!(!ConstantTimeOps::compare(&token1, &token2));
}
#[test]
fn test_very_long_tokens() {
let token1: Vec<u8> = (0..10_000).map(|i| (i % 256) as u8).collect();
let token2 = token1.clone();
let mut token3 = token1.clone();
token3[5_000] = token3[5_000].wrapping_add(1);
assert!(ConstantTimeOps::compare(&token1, &token2));
assert!(!ConstantTimeOps::compare(&token1, &token3));
}
#[test]
fn test_unicode_in_tokens() {
let token1 = "token_with_รฉmojis_๐_๐_๐";
let token2 = "token_with_รฉmojis_๐_๐_๐";
let token3 = "token_with_รฉmojis_๐_๐_๐";
assert!(ConstantTimeOps::compare_str(token1, token2));
assert!(!ConstantTimeOps::compare_str(token1, token3));
}
#[test]
fn test_comparison_is_commutative() {
let token1 = b"first_token_value_abcd";
let token2 = b"second_token_value_xyz";
let result1 = ConstantTimeOps::compare(token1, token2);
let result2 = ConstantTimeOps::compare(token2, token1);
assert_eq!(result1, result2);
}
#[test]
fn test_comparison_consistency() {
let token1 = b"consistent_token_abc";
let token2 = b"different_token_xyz";
let result1 = ConstantTimeOps::compare(token1, token2);
let result2 = ConstantTimeOps::compare(token1, token2);
let result3 = ConstantTimeOps::compare(token1, token2);
assert_eq!(result1, result2);
assert_eq!(result2, result3);
}
}