use keyhog_scanner::testing::{
github_classic_checksum_verdict_for_test, github_fine_grained_checksum_verdict_for_test,
npm_expected_checksum_for_test,
};
fn entropy(n: usize) -> String {
"a".repeat(n)
}
#[test]
fn classic_correct_checksum_validates() {
let body = entropy(30);
let checksum = npm_expected_checksum_for_test(&body); let token = format!("ghp_{body}{checksum}");
assert_eq!(token.len(), 4 + 36);
assert_eq!(github_classic_checksum_verdict_for_test(&token), "valid");
}
#[test]
fn classic_flipped_checksum_is_invalid() {
let body = entropy(30);
let mut bytes = npm_expected_checksum_for_test(&body).into_bytes();
let last = bytes.last_mut().unwrap();
*last = if *last == b'A' { b'B' } else { b'A' };
let token = format!("ghp_{body}{}", String::from_utf8(bytes).unwrap());
assert_eq!(github_classic_checksum_verdict_for_test(&token), "invalid");
}
#[test]
fn classic_overlong_is_invalid_but_short_is_not_applicable() {
assert_eq!(
github_classic_checksum_verdict_for_test(&format!("ghp_{}", entropy(37))),
"invalid"
);
assert_eq!(
github_classic_checksum_verdict_for_test(&format!("ghp_{}", entropy(35))),
"not-applicable"
);
}
#[test]
fn classic_charset_and_missing_prefix() {
let body = format!("{}!", entropy(35)); assert_eq!(
github_classic_checksum_verdict_for_test(&format!("ghp_{body}")),
"invalid"
);
assert_eq!(
github_classic_checksum_verdict_for_test("glpat-0123456789abcdefghij"),
"not-applicable"
);
}
#[test]
fn fine_grained_right_segment_checksum_validates() {
let left = entropy(22);
let right_entropy = entropy(53);
let right = format!(
"{right_entropy}{}",
npm_expected_checksum_for_test(&right_entropy)
);
assert_eq!(right.len(), 59);
let token = format!("github_pat_{left}_{right}");
assert_eq!(
github_fine_grained_checksum_verdict_for_test(&token),
"valid"
);
}
#[test]
fn fine_grained_wrong_segment_lengths_and_missing_prefix() {
let token = format!("github_pat_{}_{}", entropy(21), entropy(59));
assert_eq!(
github_fine_grained_checksum_verdict_for_test(&token),
"invalid"
);
assert_eq!(
github_fine_grained_checksum_verdict_for_test("ghp_0123456789abcdefABCDEF"),
"not-applicable"
);
}
#[test]
fn fine_grained_segment_length_boundaries_are_exact() {
assert_eq!(
github_fine_grained_checksum_verdict_for_test(&format!(
"github_pat_{}_{}",
entropy(23),
entropy(59)
)),
"invalid",
"a 23-char left segment is not the 22-char format"
);
assert_eq!(
github_fine_grained_checksum_verdict_for_test(&format!(
"github_pat_{}_{}",
entropy(22),
entropy(58)
)),
"invalid",
"a 58-char right segment is not the 59-char format"
);
}
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(2_000))]
#[test]
fn classic_correct_checksum_validates_sweep(body in "[A-Za-z0-9]{30}") {
let checksum = npm_expected_checksum_for_test(&body);
let token = format!("ghp_{body}{checksum}");
prop_assert_eq!(github_classic_checksum_verdict_for_test(&token), "valid");
}
#[test]
fn classic_any_checksum_char_change_is_invalid(
body in "[A-Za-z0-9]{30}",
pos in 0usize..6,
) {
let mut cs: Vec<char> = npm_expected_checksum_for_test(&body).chars().collect();
cs[pos] = if cs[pos] == 'a' { 'b' } else { 'a' };
let bad: String = cs.into_iter().collect();
let token = format!("ghp_{body}{bad}");
prop_assert_eq!(github_classic_checksum_verdict_for_test(&token), "invalid");
}
#[test]
fn classic_short_payload_is_not_applicable(payload in "[A-Za-z0-9]{0,35}") {
let token = format!("ghp_{payload}");
prop_assert_eq!(github_classic_checksum_verdict_for_test(&token), "not-applicable");
}
#[test]
fn classic_overlong_payload_is_invalid(payload in "[A-Za-z0-9]{37,60}") {
let token = format!("ghp_{payload}");
prop_assert_eq!(github_classic_checksum_verdict_for_test(&token), "invalid");
}
#[test]
fn fine_grained_correct_right_checksum_validates_sweep(
left in "[A-Za-z0-9]{22}",
right_entropy in "[A-Za-z0-9]{53}",
) {
let checksum = npm_expected_checksum_for_test(&right_entropy);
let token = format!("github_pat_{left}_{right_entropy}{checksum}");
prop_assert_eq!(github_fine_grained_checksum_verdict_for_test(&token), "valid");
}
#[test]
fn fine_grained_wrong_left_length_is_invalid(
off in 1usize..8,
longer in any::<bool>(),
right_entropy in "[A-Za-z0-9]{53}",
) {
let left_len = if longer { 22 + off } else { 22 - off };
let left = "a".repeat(left_len);
let checksum = npm_expected_checksum_for_test(&right_entropy);
let token = format!("github_pat_{left}_{right_entropy}{checksum}");
prop_assert_eq!(github_fine_grained_checksum_verdict_for_test(&token), "invalid");
}
}