use keyhog_scanner::decode::{
base64_decode, find_base64_strings, find_hex_strings, hex_decode, is_base64_candidate_byte,
};
#[test]
fn base64_candidate_byte_accepts_the_full_alphabet_and_rejects_others() {
for b in [
b'A', b'Z', b'a', b'z', b'0', b'9', b'+', b'/', b'=', b'-', b'_',
] {
assert!(
is_base64_candidate_byte(b),
"{} must be a candidate",
b as char
);
}
for b in [b' ', b'!', b'.', b'\n', b'#', b'@', b':', b'"'] {
assert!(
!is_base64_candidate_byte(b),
"{} must NOT be a candidate",
b as char
);
}
}
#[test]
fn find_base64_strings_extracts_the_value_of_an_assignment() {
let found = find_base64_strings("token=aGVsbG8= end", 8);
assert!(
found
.iter()
.any(|e| base64_decode(&e.value).ok().as_deref() == Some(&b"hello"[..])),
"expected the assignment value to decode to `hello`, got: {:?}",
found.iter().map(|e| &e.value).collect::<Vec<_>>()
);
}
#[test]
fn find_base64_strings_honors_the_min_length_floor() {
let short = find_base64_strings("x YWI= y", 32);
assert!(
!short
.iter()
.any(|e| base64_decode(&e.value).ok().as_deref() == Some(&b"ab"[..])),
"a 4-char run must be filtered out by min_length=32"
);
}
#[test]
fn find_hex_strings_locates_an_embedded_token_that_round_trips() {
let text = "sha=48656c6c6f;";
let found = find_hex_strings(text, 8);
assert!(
found
.iter()
.any(|e| hex_decode(&e.value).ok().as_deref() == Some(&b"Hello"[..])),
"expected a discovered hex run decoding to `Hello`, got: {:?}",
found.iter().map(|e| &e.value).collect::<Vec<_>>()
);
}
#[test]
fn find_strings_return_nothing_for_text_without_encoded_runs() {
assert!(find_base64_strings("just some plain english words here", 16).is_empty());
assert!(find_hex_strings("no hex digits in this sentence!!", 16).is_empty());
}