Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sds/src/scanner/regex_rule/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ pub enum SecondaryValidator {
ItalianNationalIdChecksum,
JapanCorporateNumberChecksum,
JapanDrivingLicenseChecksum,
JapanMyNumberChecksum,
JwtClaimsValidator {
config: JwtClaimsValidatorConfig,
},
Expand Down
67 changes: 67 additions & 0 deletions sds/src/secondary_validation/japan_my_number_checksum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::secondary_validation::{Validator, validate_mod11_weighted_checksum};

/// Check digit defined by Article 5 of Japanese ordinance No. 85:
/// https://laws.e-gov.go.jp/law/426M60000008085#Mp-At_5
pub struct JapanMyNumberChecksum;

const WEIGHTS: &[u32; 11] = &[6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2];

impl Validator for JapanMyNumberChecksum {
fn is_valid_match(&self, regex_match: &str) -> bool {
validate_mod11_weighted_checksum(regex_match, WEIGHTS, |remainder| {
Some(if remainder <= 1 { 0 } else { 11 - remainder })
})
}
}

#[cfg(test)]
mod test {
use crate::secondary_validation::{JapanMyNumberChecksum, Validator};

#[test]
fn test_published_japan_my_numbers() {
// TKC examples:
// https://www.prft.tkc.co.jp/SystemqaCPNYFree/Main/QaItem.aspx?category_id=2044&item_id=83412&system_id=260
assert!(JapanMyNumberChecksum.is_valid_match("123456789018"));
assert!(!JapanMyNumberChecksum.is_valid_match("923456789018"));
}

#[test]
fn test_generated_japan_my_numbers() {
// Generated fixtures from https://box4.dev/en/japan/my-number-generator
for number in [
"6637 6256 7333",
"8834 6653 3261",
"7680 7456 4211",
"3385 0214 0532",
"5800 0094 7110",
] {
assert!(JapanMyNumberChecksum.is_valid_match(number), "{number}");
assert!(JapanMyNumberChecksum.is_valid_match(&number.replace(' ', "")));
}
}

#[test]
fn test_incorrect_check_digit() {
assert!(!JapanMyNumberChecksum.is_valid_match("123456789012"));
assert!(!JapanMyNumberChecksum.is_valid_match("1234 5678 9012"));
}

#[test]
fn test_incorrect_digit_count() {
for number in ["", "12345678901", "1234567890180"] {
assert!(!JapanMyNumberChecksum.is_valid_match(number), "{number}");
}
}

#[test]
fn test_zero_check_digit_for_small_remainders() {
// Synthetic arithmetic cases: sums 11 and 12 give remainders 0 and 1.
for number in ["000000000140", "000000000060"] {
assert!(JapanMyNumberChecksum.is_valid_match(number), "{number}");
}
for number in ["000000000141", "000000000061"] {
assert!(!JapanMyNumberChecksum.is_valid_match(number), "{number}");
}
}
}
3 changes: 3 additions & 0 deletions sds/src/secondary_validation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod iso_7064_checksum;
mod italian_national_id_checksum;
mod japan_corporate_number_checksum;
mod japan_driving_license_checksum;
mod japan_my_number_checksum;
pub mod jwt_claims_validator;
mod jwt_expiration_checker;
mod latvia_national_id_checksum;
Expand Down Expand Up @@ -104,6 +105,7 @@ pub use crate::secondary_validation::iso_7064_checksum::{
pub use crate::secondary_validation::italian_national_id_checksum::ItalianNationalIdChecksum;
pub use crate::secondary_validation::japan_corporate_number_checksum::JapanCorporateNumberChecksum;
pub use crate::secondary_validation::japan_driving_license_checksum::JapanDrivingLicenseChecksum;
pub use crate::secondary_validation::japan_my_number_checksum::JapanMyNumberChecksum;
pub use crate::secondary_validation::jwt_claims_validator::JwtClaimsValidator;
pub use crate::secondary_validation::jwt_expiration_checker::JwtExpirationChecker;
pub use crate::secondary_validation::latvia_national_id_checksum::LatviaNationalIdChecksum;
Expand Down Expand Up @@ -251,6 +253,7 @@ impl SecondaryValidator {
SecondaryValidator::IbanChecker => Arc::new(IbanChecker),
SecondaryValidator::IrishPpsChecksum => Arc::new(IrishPpsChecksum),
SecondaryValidator::ItalianNationalIdChecksum => Arc::new(ItalianNationalIdChecksum),
SecondaryValidator::JapanMyNumberChecksum => Arc::new(JapanMyNumberChecksum),
SecondaryValidator::JapanCorporateNumberChecksum => {
Arc::new(JapanCorporateNumberChecksum)
}
Expand Down
Loading