mod compiled;
pub(crate) use compiled::{CompiledDetectorValidators, CompiledValidatorIndex};
use std::sync::LazyLock;
const BASE62_DIGITS: &[u8; 62] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ChecksumResult {
Valid,
StructurallyValid,
Invalid,
NotApplicable,
}
static VALIDATOR_CATALOG: LazyLock<compiled::CompiledValidatorCatalog> = LazyLock::new(|| {
match compiled::CompiledValidatorCatalog::compile(keyhog_core::embedded_detector_specs()) {
Ok(catalog) => catalog,
Err(error) => panic!(
"embedded detector validators failed to compile: {error}. Fix the owning detector TOML"
),
}
});
pub fn validate_checksum(credential: &str) -> ChecksumResult {
VALIDATOR_CATALOG.validate_any(credential).result()
}
#[inline]
pub(crate) fn validate_for_detector(
detector_id: &str,
credential: &str,
) -> ChecksumConfidenceDecision {
VALIDATOR_CATALOG.validate_for_detector(detector_id, credential)
}
pub(crate) fn detector_declared_prefixes() -> Vec<&'static str> {
VALIDATOR_CATALOG.prefixes()
}
pub(crate) fn crc32(data: &[u8]) -> u32 {
const TABLE: [u32; 256] = {
let mut table = [0u32; 256];
let mut i = 0;
while i < 256 {
let mut crc = i as u32;
let mut j = 0;
while j < 8 {
if crc & 1 != 0 {
crc = 0xEDB88320 ^ (crc >> 1);
} else {
crc >>= 1;
}
j += 1;
}
table[i] = crc;
i += 1;
}
table
};
let mut crc: u32 = 0xFFFF_FFFF;
for &byte in data {
crc = TABLE[((crc ^ (byte as u32)) & 0xFF) as usize] ^ (crc >> 8);
}
crc ^ 0xFFFF_FFFF
}
pub(crate) fn base62_encode_u32(mut value: u32, width: usize) -> String {
if value == 0 {
return "0".repeat(width);
}
let mut rev = Vec::with_capacity(width.max(6));
while value > 0 {
rev.push(BASE62_DIGITS[(value % 62) as usize] as char);
value /= 62;
}
while rev.len() < width {
rev.push('0');
}
rev.reverse();
rev.into_iter().collect()
}
pub const CHECKSUM_VALID_FLOOR: f64 = 0.9;
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct ChecksumConfidenceDecision {
result: ChecksumResult,
valid_confidence_floor: Option<f64>,
claimed_family: bool,
}
impl ChecksumConfidenceDecision {
#[inline]
pub(crate) const fn new(result: ChecksumResult, valid_confidence_floor: Option<f64>) -> Self {
Self {
result,
valid_confidence_floor,
claimed_family: true,
}
}
#[inline]
pub(crate) const fn not_applicable() -> Self {
Self {
result: ChecksumResult::NotApplicable,
valid_confidence_floor: None,
claimed_family: false,
}
}
#[inline]
pub(crate) fn for_credential(credential: &str) -> Self {
VALIDATOR_CATALOG.validate_any(credential)
}
#[inline]
pub(crate) fn is_invalid(self) -> bool {
matches!(self.result, ChecksumResult::Invalid)
}
#[inline]
pub(crate) fn result(self) -> ChecksumResult {
self.result
}
#[inline]
pub(crate) fn valid_confidence_floor(self) -> Option<f64> {
self.valid_confidence_floor
}
#[inline]
pub(crate) fn claims_family(self) -> bool {
self.claimed_family
}
#[inline]
pub(crate) fn is_proven_valid(self) -> bool {
matches!(self.result, ChecksumResult::Valid)
}
}
#[inline]
pub fn checksum_adjusted_confidence(confidence: f64, credential: &str) -> Option<f64> {
crate::confidence::policy::apply_checksum_confidence(confidence, credential)
}