dd_sds/secondary_validation/
mod.rs

1mod aba_rtn_checksum;
2mod belgium_national_register_checksum;
3mod brazilian_cnpj_checksum;
4mod brazilian_cpf_checksum;
5mod btc_checksum;
6mod bulgarian_egn_checksum;
7mod chinese_id_checksum;
8mod coordination_number_checksum;
9mod czech_tin_checksum;
10mod dutch_bsn_checksum;
11mod dutch_passport_checksum;
12mod entropy;
13mod estonia_personal_code_checksum;
14mod ethereum_checksum;
15mod finnish_hetu_checksum;
16mod france_nif_checksum;
17mod france_ssn_checksum;
18mod german_ids_checksum;
19mod german_svnr_checksum;
20mod github_token_checksum;
21mod greece_amka_checksum;
22mod greece_tin_checksum;
23mod hungarian_tin_checksum;
24mod iban_checker;
25mod irish_pps_checksum;
26mod iso_7064_checksum;
27mod italian_national_id_checksum;
28pub mod jwt_claims_validator;
29mod jwt_expiration_checker;
30mod latvia_national_id_checksum;
31mod lithuanian_personal_identification_number_checksum;
32mod luhn_checksum;
33mod luxembourg_individual_nin_checksum;
34mod monero_address;
35mod nhs_check_digit;
36mod nir_checksum;
37mod polish_national_id_checksum;
38mod polish_nip_checksum;
39mod portuguese_tax_id_checksum;
40mod rodne_cislo_checksum;
41mod romanian_personal_numeric_code;
42mod slovenia_tin_checksum;
43mod slovenian_pin_checksum;
44mod spain_dni_checksum;
45mod spanish_nuss_checksum;
46mod sweden_pin_checksum;
47mod us_dea_checksum;
48mod us_npi_checksum;
49mod verhoeff_checksum;
50
51#[cfg(test)]
52pub use jwt_expiration_checker::generate_jwt;
53
54use crate::scanner::regex_rule::config::SecondaryValidator;
55pub use crate::secondary_validation::aba_rtn_checksum::AbaRtnChecksum;
56pub use crate::secondary_validation::belgium_national_register_checksum::BelgiumNationalRegisterChecksum;
57pub use crate::secondary_validation::brazilian_cnpj_checksum::BrazilianCnpjChecksum;
58pub use crate::secondary_validation::brazilian_cpf_checksum::BrazilianCpfChecksum;
59pub use crate::secondary_validation::btc_checksum::BtcChecksum;
60pub use crate::secondary_validation::bulgarian_egn_checksum::BulgarianEGNChecksum;
61pub use crate::secondary_validation::chinese_id_checksum::ChineseIdChecksum;
62pub use crate::secondary_validation::coordination_number_checksum::CoordinationNumberChecksum;
63pub use crate::secondary_validation::czech_tin_checksum::CzechTaxIdentificationNumberChecksum;
64pub use crate::secondary_validation::dutch_bsn_checksum::DutchBsnChecksum;
65pub use crate::secondary_validation::dutch_passport_checksum::DutchPassportChecksum;
66pub use crate::secondary_validation::entropy::EntropyCheck;
67pub use crate::secondary_validation::estonia_personal_code_checksum::EstoniaPersonalCodeChecksum;
68pub use crate::secondary_validation::ethereum_checksum::EthereumChecksum;
69pub use crate::secondary_validation::finnish_hetu_checksum::FinnishHetuChecksum;
70use crate::secondary_validation::france_nif_checksum::FranceNifChecksum;
71pub use crate::secondary_validation::france_ssn_checksum::FranceSsnChecksum;
72pub use crate::secondary_validation::german_ids_checksum::GermanIdsChecksum;
73pub use crate::secondary_validation::german_svnr_checksum::GermanSvnrChecksum;
74pub use crate::secondary_validation::github_token_checksum::GithubTokenChecksum;
75pub use crate::secondary_validation::greece_amka_checksum::GreeceAmkaChecksum;
76pub use crate::secondary_validation::greece_tin_checksum::GreekTinChecksum;
77pub use crate::secondary_validation::hungarian_tin_checksum::HungarianTinChecksum;
78pub use crate::secondary_validation::iban_checker::IbanChecker;
79pub use crate::secondary_validation::irish_pps_checksum::IrishPpsChecksum;
80pub use crate::secondary_validation::iso_7064_checksum::{
81    Mod11_2checksum, Mod11_10checksum, Mod27_26checksum, Mod37_2checksum, Mod37_36checksum,
82    Mod97_10checksum, Mod661_26checksum, Mod1271_36Checksum,
83};
84pub use crate::secondary_validation::italian_national_id_checksum::ItalianNationalIdChecksum;
85pub use crate::secondary_validation::jwt_claims_validator::JwtClaimsValidator;
86pub use crate::secondary_validation::jwt_expiration_checker::JwtExpirationChecker;
87pub use crate::secondary_validation::latvia_national_id_checksum::LatviaNationalIdChecksum;
88use crate::secondary_validation::lithuanian_personal_identification_number_checksum::LithuanianPersonalIdentificationNumberChecksum;
89pub use crate::secondary_validation::luhn_checksum::LuhnChecksum;
90pub use crate::secondary_validation::luxembourg_individual_nin_checksum::LuxembourgIndividualNINChecksum;
91pub use crate::secondary_validation::monero_address::MoneroAddress;
92pub use crate::secondary_validation::nhs_check_digit::NhsCheckDigit;
93pub use crate::secondary_validation::nir_checksum::NirChecksum;
94pub use crate::secondary_validation::polish_national_id_checksum::PolishNationalIdChecksum;
95pub use crate::secondary_validation::polish_nip_checksum::PolishNipChecksum;
96pub use crate::secondary_validation::portuguese_tax_id_checksum::PortugueseTaxIdChecksum;
97pub use crate::secondary_validation::rodne_cislo_checksum::RodneCisloNumberChecksum;
98pub use crate::secondary_validation::romanian_personal_numeric_code::RomanianPersonalNumericCode;
99pub use crate::secondary_validation::slovenia_tin_checksum::SloveniaTinChecksum;
100pub use crate::secondary_validation::slovenian_pin_checksum::SlovenianPINChecksum;
101pub use crate::secondary_validation::spain_dni_checksum::SpanishDniChecksum;
102pub use crate::secondary_validation::spanish_nuss_checksum::SpanishNussChecksum;
103pub use crate::secondary_validation::sweden_pin_checksum::SwedenPINChecksum;
104pub use crate::secondary_validation::us_dea_checksum::UsDeaChecksum;
105pub use crate::secondary_validation::us_npi_checksum::UsNpiChecksum;
106pub use crate::secondary_validation::verhoeff_checksum::VerhoeffChecksum;
107
108use std::str::Chars;
109use std::sync::Arc;
110
111pub trait Validator: Send + Sync {
112    fn is_valid_match(&self, regex_match: &str) -> bool;
113}
114
115fn get_previous_digit(chars: &mut Chars<'_>) -> Option<u32> {
116    while let Some(char) = chars.next_back() {
117        if let Some(digit) = char.to_digit(10) {
118            return Some(digit);
119        }
120    }
121    None
122}
123fn get_next_digit(chars: &mut Chars<'_>) -> Option<u32> {
124    for char in chars.by_ref() {
125        if let Some(digit) = char.to_digit(10) {
126            return Some(digit);
127        }
128    }
129    None
130}
131
132/// Sum all the digits from a number
133#[inline]
134fn sum_all_digits(digits: u32) -> u32 {
135    let mut sum = 0;
136    let mut num = digits;
137    while num > 0 {
138        sum += num % 10;
139        num /= 10;
140    }
141    sum
142}
143
144/// Validates a checksum using modulo 11 algorithm with configurable weights and edge case handling
145pub(crate) fn validate_mod11_weighted_checksum<F>(
146    regex_match: &str,
147    weights: &[u32],
148    edge_case_handler: F,
149) -> bool
150where
151    F: Fn(u32) -> Option<u32>,
152{
153    let mut chars = regex_match.chars();
154    let mut sum: u32 = 0;
155
156    for &weight in weights {
157        let digit = match get_next_digit(&mut chars) {
158            Some(d) => d,
159            None => return false,
160        };
161        sum += digit * weight;
162    }
163
164    let actual_checksum = match get_next_digit(&mut chars) {
165        Some(d) => d,
166        None => return false,
167    };
168
169    if get_next_digit(&mut chars).is_some() {
170        return false; // too many digits
171    }
172
173    let remainder = sum % 11;
174    match edge_case_handler(remainder) {
175        Some(expected_checksum) => expected_checksum == actual_checksum,
176        None => false,
177    }
178}
179
180impl SecondaryValidator {
181    pub fn compile(&self) -> Arc<dyn Validator> {
182        match self {
183            SecondaryValidator::AbaRtnChecksum => Arc::new(AbaRtnChecksum),
184            SecondaryValidator::BelgiumNationalRegisterChecksum => {
185                Arc::new(BelgiumNationalRegisterChecksum)
186            }
187            SecondaryValidator::BrazilianCnpjChecksum => Arc::new(BrazilianCnpjChecksum),
188            SecondaryValidator::BrazilianCpfChecksum => Arc::new(BrazilianCpfChecksum),
189            SecondaryValidator::BtcChecksum => Arc::new(BtcChecksum),
190            SecondaryValidator::BulgarianEGNChecksum => Arc::new(BulgarianEGNChecksum),
191            SecondaryValidator::ChineseIdChecksum => Arc::new(ChineseIdChecksum),
192            SecondaryValidator::CoordinationNumberChecksum => Arc::new(CoordinationNumberChecksum),
193            SecondaryValidator::CzechPersonalIdentificationNumberChecksum => {
194                Arc::new(RodneCisloNumberChecksum)
195            }
196            SecondaryValidator::CzechTaxIdentificationNumberChecksum => {
197                Arc::new(CzechTaxIdentificationNumberChecksum)
198            }
199            SecondaryValidator::DutchBsnChecksum => Arc::new(DutchBsnChecksum),
200            SecondaryValidator::DutchPassportChecksum => Arc::new(DutchPassportChecksum),
201            SecondaryValidator::EntropyCheck => Arc::new(EntropyCheck),
202            SecondaryValidator::EstoniaPersonalCodeChecksum => {
203                Arc::new(EstoniaPersonalCodeChecksum)
204            }
205            SecondaryValidator::EthereumChecksum => Arc::new(EthereumChecksum),
206            SecondaryValidator::FinnishHetuChecksum => Arc::new(FinnishHetuChecksum),
207            SecondaryValidator::FranceNifChecksum => Arc::new(FranceNifChecksum),
208            SecondaryValidator::FranceSsnChecksum => Arc::new(FranceSsnChecksum),
209            SecondaryValidator::GermanIdsChecksum => Arc::new(GermanIdsChecksum),
210            SecondaryValidator::GermanSvnrChecksum => Arc::new(GermanSvnrChecksum),
211            SecondaryValidator::GithubTokenChecksum => Arc::new(GithubTokenChecksum),
212            SecondaryValidator::GreeceAmkaChecksum => Arc::new(GreeceAmkaChecksum),
213            SecondaryValidator::GreekTinChecksum => Arc::new(GreekTinChecksum),
214            SecondaryValidator::HungarianTinChecksum => Arc::new(HungarianTinChecksum),
215            SecondaryValidator::IbanChecker => Arc::new(IbanChecker),
216            SecondaryValidator::IrishPpsChecksum => Arc::new(IrishPpsChecksum),
217            SecondaryValidator::ItalianNationalIdChecksum => Arc::new(ItalianNationalIdChecksum),
218            SecondaryValidator::JwtClaimsValidator { config } => {
219                Arc::new(JwtClaimsValidator::new(config.clone()))
220            }
221            SecondaryValidator::JwtExpirationChecker => Arc::new(JwtExpirationChecker),
222            SecondaryValidator::LatviaNationalIdChecksum => Arc::new(LatviaNationalIdChecksum),
223            SecondaryValidator::LithuanianPersonalIdentificationNumberChecksum => {
224                Arc::new(LithuanianPersonalIdentificationNumberChecksum)
225            }
226            SecondaryValidator::LuhnChecksum => Arc::new(LuhnChecksum),
227            SecondaryValidator::LuxembourgIndividualNINChecksum => {
228                Arc::new(LuxembourgIndividualNINChecksum)
229            }
230            SecondaryValidator::Mod11_10checksum => Arc::new(Mod11_10checksum),
231            SecondaryValidator::Mod11_2checksum => Arc::new(Mod11_2checksum),
232            SecondaryValidator::Mod1271_36Checksum => Arc::new(Mod1271_36Checksum),
233            SecondaryValidator::Mod27_26checksum => Arc::new(Mod27_26checksum),
234            SecondaryValidator::Mod37_2checksum => Arc::new(Mod37_2checksum),
235            SecondaryValidator::Mod37_36checksum => Arc::new(Mod37_36checksum),
236            SecondaryValidator::Mod661_26checksum => Arc::new(Mod661_26checksum),
237            SecondaryValidator::Mod97_10checksum => Arc::new(Mod97_10checksum),
238            SecondaryValidator::MoneroAddress => Arc::new(MoneroAddress),
239            SecondaryValidator::NhsCheckDigit => Arc::new(NhsCheckDigit),
240            SecondaryValidator::NirChecksum => Arc::new(NirChecksum),
241            SecondaryValidator::PolishNationalIdChecksum => Arc::new(PolishNationalIdChecksum),
242            SecondaryValidator::PolishNipChecksum => Arc::new(PolishNipChecksum),
243            SecondaryValidator::PortugueseTaxIdChecksum => Arc::new(PortugueseTaxIdChecksum),
244            SecondaryValidator::RodneCisloNumberChecksum => Arc::new(RodneCisloNumberChecksum),
245            SecondaryValidator::RomanianPersonalNumericCode => {
246                Arc::new(RomanianPersonalNumericCode)
247            }
248            SecondaryValidator::SlovenianPINChecksum => Arc::new(SlovenianPINChecksum),
249            SecondaryValidator::SloveniaTinChecksum => Arc::new(SloveniaTinChecksum),
250            SecondaryValidator::SpanishDniChecksum => Arc::new(SpanishDniChecksum),
251            SecondaryValidator::SpanishNussChecksum => Arc::new(SpanishNussChecksum),
252            SecondaryValidator::SwedenPINChecksum => Arc::new(SwedenPINChecksum),
253            SecondaryValidator::UsDeaChecksum => Arc::new(UsDeaChecksum),
254            SecondaryValidator::UsNpiChecksum => Arc::new(UsNpiChecksum),
255            SecondaryValidator::VerhoeffChecksum => Arc::new(VerhoeffChecksum),
256        }
257    }
258}