From 69e21289a45f3d5f8cc9150aac84b496e89b97b4 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 2 Feb 2024 18:33:51 +0100 Subject: Improve NL cert_id rules. --- src/sec_certs/rules.yaml | 14 ++++++-------- src/sec_certs/sample/cc_certificate_id.py | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 3cce1ab8..b0d421f1 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -21,14 +21,12 @@ cc_cert_id: - "Certification Report [0-9]+/[0-9]+" # French or Australia! Solved because we limit ourselves to scheme when doing heuristics. - "Rapport de certification [0-9]+/[0-9]+" # French NL: - - "NSCIB-CC-[0-9]{4}.+?" # Netherlands - - "NSCIB-CC-[0-9]{4}[0-9]*-CR" # Netherlands - - "NSCIB-CC-[0-9][0-9]-[0-9]+?-CR[0-9]+?" # Netherlands - - "NSCIB-CC-[0-9][0-9]-[0-9]+(-CR[0-9]+)*" # Netherlands (old number NSCIB-CC-05-6609 or NSCIB-CC-05-6609-CR) - - "NSCIB-CC-[0-9]+-CR[0-9]*" # Netherlands (new number NSCIB-CC-111441-CR NSCIB-CC-111441-CR1) - - "NSCIB-CC-[0-9]+-MA[0-9]*" # Netherlands (new number NSCIB-CC-222073-MA NSCIB-CC-200716-MA2) - - "NSCIB-CC-[0-9][0-9]-[0-9]+" # Netherlands (old number NSCIB-CC-05-6609) - - "NSCIB-CC-[0-9][0-9]-[0-9]+-CR[0-9]+" # Netherlands (NSCIB-CC-year2digits-number-CR) + - "(?:NSCIB-|CC-|NSCIB-CC-)(?P((?P[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P(?:CR|MA|MR)[0-9]*))?" + # Examples: + # NSCIB-CC-22-0428888-CR2 (with year=22 and CR2) + # NSCIB-CC-228723-CR (no year) + # CC-16-31801-CR4 (no NSCIB) + # NSCIB-CC-98209 (no year, no CR) "NO": - "SERTIT-[0-9]+" # Norway US: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 254c8e05..74cba680 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -126,7 +126,7 @@ class CertificateId: new_cert_id = self.clean if new_cert_id.startswith("CC-"): new_cert_id = f"NSCIB-{new_cert_id}" - if not new_cert_id.endswith("-CR"): + if not re.match(".*-(CR|MA|MR)[0-9]*$", new_cert_id): new_cert_id = f"{new_cert_id}-CR" return new_cert_id -- cgit v1.3.1 From c380870abd04c84da69a9dd438abf22d430568a8 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 2 Feb 2024 19:11:22 +0100 Subject: Cleanup ANSSI rules. --- src/sec_certs/rules.yaml | 18 ++++++++++-------- src/sec_certs/sample/cc_certificate_id.py | 28 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index b0d421f1..87acd04b 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -13,13 +13,15 @@ cc_cert_id: - "BSI-DSZ-CC-[0-9]+-(?:V|v)[0-9]+(?!-)" # German BSI (number + version but no year => no - after version) # - "BSI-DSZ-CC-[0-9]+" # Maybe? FR: - - "ANSS[Ii](?:-|-CC-|-CC )[0-9]{4}/[0-9]+(v[1-9])?" # French - - "ANSS[Ii]-CC[ -][0-9]{4}[/-_][0-9][0-9]+(?!-M|-S|-R)" # French (/two or more digits then NOT -M or -S) - - "ANSS[Ii]-CC[ -][0-9]{4}[/-_][0-9]+(?:v[0-9])?[_/-][MSR][0-9]+" # French, maintenance or surveillance report (ANSSI-CC-2014_46_M01) - # 'ANSSI-CC-CER-F-.+?', # French - - "DCSS[Ii]-[0-9]+/[0-9]+" # French (DCSSI-2009/07) - - "Certification Report [0-9]+/[0-9]+" # French or Australia! Solved because we limit ourselves to scheme when doing heuristics. - - "Rapport de certification [0-9]+/[0-9]+" # French + - "DCSS[Ii]-(?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" + - "Certification Report (?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" + - "Rapport de certification (?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" + - "ANSS[Ii](?:-CC)?[ -](?P[0-9]{2,4})[/_-](?P[0-9]+)(?:-(?P(?:[MSR][0-9]+)))?([vV](?P[0-9]))?" + # Examples: + # DCSSI-2009/07 + # ANSSI-CC 2001/02-R01 + # Rapport de certification 2001/02v2 + # Certification Report 2003/20 NL: - "(?:NSCIB-|CC-|NSCIB-CC-)(?P((?P[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P(?:CR|MA|MR)[0-9]*))?" # Examples: @@ -28,7 +30,7 @@ cc_cert_id: # CC-16-31801-CR4 (no NSCIB) # NSCIB-CC-98209 (no year, no CR) "NO": - - "SERTIT-[0-9]+" # Norway + - "SERTIT-(?P[0-9]+)" # Norway US: - "CCEVS-VR-(?:CC-|VID)?[0-9]+-[0-9]+[a-z]?(?:-[0-9]+)?" # US NSA (CCEVS-VR-10884-2018 CCEVS-VR-VID10877-2018) CA: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 74cba680..9bce0764 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -3,6 +3,8 @@ from __future__ import annotations import re from dataclasses import dataclass +from sec_certs.cert_rules import rules + @dataclass(eq=True, frozen=True) class CertificateId: @@ -14,22 +16,20 @@ class CertificateId: raw: str def _canonical_fr(self) -> str: - def pad_last_segment_with_zero(id_str: str) -> str: - splitted = id_str.split("/") - if len(splitted) > 1: - num = splitted[-1].zfill(2) - return f"{''.join(splitted[:-1])}/{num}" - return id_str - new_cert_id = self.clean - rules = [ - "(?:Rapport de certification|Certification Report) ([0-9]+[/-_][0-9]+(?:[vV][1-9])?(?:[_/-][MSR][0-9]+)?)", - "(?:ANSS[Ii]|DCSSI)(?:-CC)?[- ]([0-9]+[/-_][0-9]+(?:[vV][1-9])?(?:[_/-][MSR][0-9]+)?)", - "([0-9]+[/-_][0-9]+(?:[vV][1-9])?(?:[_/-][MSR][0-9]+)?)", - ] - for rule in rules: + for rule in rules["cc_cert_id"]["FR"]: if match := re.match(rule, new_cert_id): - return pad_last_segment_with_zero("ANSSI-CC-" + match.group(1).replace("_", "/").replace("V", "v")) + groups = match.groupdict() + year = int(groups["year"]) if len(groups["year"]) == 4 else int(groups["year"]) + 2000 + counter = groups["counter"] + doc = groups.get("doc") + version = groups.get("version") + new_cert_id = f"ANSSI-CC-{year}/{counter}" + if doc: + new_cert_id += f"-{doc}" + if version: + new_cert_id += f"v{version}" + return new_cert_id return new_cert_id -- cgit v1.3.1 From 67861ffd16f215f7d476e90bb8e480a5c60dc01b Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 00:11:20 +0100 Subject: Improve BSI regexes. --- src/sec_certs/rules.yaml | 20 +++++----- src/sec_certs/sample/cc_certificate_id.py | 61 ++++++++++++++++--------------- tests/cc/test_cc_misc.py | 3 ++ 3 files changed, 45 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 87acd04b..5604b709 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -5,17 +5,17 @@ ##### cc_cert_id: DE: - - "BSI-DSZ-CC-[0-9]+?-[0-9]+" - - "BSI-DSZ-CC-[0-9]+?-(?:V|v)[0-9]+-[0-9]+" - - "BSI-DSZ-CC-[0-9]+?-(?:V|v)[0-9]+" - - "BSI-DSZ-CC-[0-9]+-(?:V|v)[0-9]+(-[0-9]{4})*" # German BSI (number + version + year or without year) - - "BSI-DSZ-CC-[0-9]+-[0-9]{4}" # German BSI (number + year, no version) - - "BSI-DSZ-CC-[0-9]+-(?:V|v)[0-9]+(?!-)" # German BSI (number + version but no year => no - after version) - # - "BSI-DSZ-CC-[0-9]+" # Maybe? + - "BSI-DSZ-CC-(?:(?PS)-)?(?P[0-9]{3,5})-(?:(?P[vV][0-9])-)?(?P[0-9]{4})?(?:-(?P(?:RA|MA)(?:-[0-9]+)?))?" + # Examples: + # BSI-DSZ-CC-1004 + # BSI-DSZ-CC-0973-2016 + # BSI-DSZ-CC-0831-V4-2021 + # BSI-DSZ-CC-0837-V2-2014-MA-01 + # BSI-DSZ-CC-S-0192-2021 FR: - "DCSS[Ii]-(?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" - - "Certification Report (?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" - "Rapport de certification (?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" + - "Certification Report (?P[0-9]{2,4})/(?P[0-9]+)([vV](?P[0-9]))?" - "ANSS[Ii](?:-CC)?[ -](?P[0-9]{2,4})[/_-](?P[0-9]+)(?:-(?P(?:[MSR][0-9]+)))?([vV](?P[0-9]))?" # Examples: # DCSSI-2009/07 @@ -30,7 +30,9 @@ cc_cert_id: # CC-16-31801-CR4 (no NSCIB) # NSCIB-CC-98209 (no year, no CR) "NO": - - "SERTIT-(?P[0-9]+)" # Norway + - "SERTIT-(?P[0-9]+)" + # Examples: + # SERTIT-101 US: - "CCEVS-VR-(?:CC-|VID)?[0-9]+-[0-9]+[a-z]?(?:-[0-9]+)?" # US NSA (CCEVS-VR-10884-2018 CCEVS-VR-VID10877-2018) CA: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 9bce0764..188a2163 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -6,6 +6,16 @@ from dataclasses import dataclass from sec_certs.cert_rules import rules +def _parse_year(year: str | None) -> int | None: + if year is None: + return None + y = int(year) + if y < 100: + return y + 1900 + else: + return y + + @dataclass(eq=True, frozen=True) class CertificateId: """ @@ -20,7 +30,7 @@ class CertificateId: for rule in rules["cc_cert_id"]["FR"]: if match := re.match(rule, new_cert_id): groups = match.groupdict() - year = int(groups["year"]) if len(groups["year"]) == 4 else int(groups["year"]) + 2000 + year = _parse_year(groups["year"]) counter = groups["counter"] doc = groups.get("doc") version = groups.get("version") @@ -34,35 +44,26 @@ class CertificateId: return new_cert_id def _canonical_de(self) -> str: - def extract_parts(bsi_parts: list[str]) -> tuple: - cert_num = None - cert_version = None - cert_year = None - - if len(bsi_parts) > 3: - cert_num = bsi_parts[3] - if len(bsi_parts) > 4: - if bsi_parts[4].startswith("V") or bsi_parts[4].startswith("v"): - cert_version = bsi_parts[4].upper() # get version in uppercase - else: - cert_year = bsi_parts[4] - if len(bsi_parts) > 5: - cert_year = bsi_parts[5] - - return cert_num, cert_version, cert_year - - bsi_parts = self.clean.split("-") - - cert_num, cert_version, cert_year = extract_parts(bsi_parts) - - # reconstruct BSI number again - new_cert_id = "BSI-DSZ-CC" - if cert_num is not None: - new_cert_id += "-" + cert_num - if cert_version is not None: - new_cert_id += "-" + cert_version - if cert_year is not None: - new_cert_id += "-" + cert_year + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["DE"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + s = groups.get("s") + counter = groups["counter"] + version = groups.get("version") + year = _parse_year(groups.get("year")) + doc = groups.get("doc") + new_cert_id = "BSI-DSZ-CC" + if s: + new_cert_id += f"-{s}" + new_cert_id += f"-{counter}" + if version: + new_cert_id += f"-{version.upper()}" + if year: + new_cert_id += f"-{year}" + if doc: + new_cert_id += f"-{doc}" + return new_cert_id return new_cert_id diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index ae9a83aa..b9654c91 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -8,6 +8,9 @@ def test_canonicalize_fr(): def test_canonicalize_de(): assert canonicalize("BSI-DSZ-CC-0420-2007", "DE") == "BSI-DSZ-CC-0420-2007" + assert canonicalize("BSI-DSZ-CC-1004", "DE") == "BSI-DSZ-CC-1004" + assert canonicalize("BSI-DSZ-CC-0831-V4-2021", "DE") == "BSI-DSZ-CC-0831-V4-2021" + assert canonicalize("BSI-DSZ-CC-0837-V2-2014-MA-01", "DE") == "BSI-DSZ-CC-0837-V2-2014-MA-01" def test_canonicalize_es(): -- cgit v1.3.1 From c60fece36b7e7c5300b25cf83b9e34d338675067 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 15:41:11 +0100 Subject: Improve US scheme rules. --- src/sec_certs/rules.yaml | 7 ++++++- src/sec_certs/sample/cc_certificate_id.py | 29 ++++++++++++++++++++++++++--- tests/cc/test_cc_misc.py | 6 ++++++ 3 files changed, 38 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 5604b709..fa188052 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -34,7 +34,12 @@ cc_cert_id: # Examples: # SERTIT-101 US: - - "CCEVS-VR-(?:CC-|VID)?[0-9]+-[0-9]+[a-z]?(?:-[0-9]+)?" # US NSA (CCEVS-VR-10884-2018 CCEVS-VR-VID10877-2018) + - "CCEVS-VR-(?:(?PCC)-)?(?:(?PVID)-?)?(?P[0-9]{2})-(?P[0-9]+)" + - "CCEVS-VR-(?:(?PCC)-)?(?:(?PVID)-?)?(?P[0-9]{4,5})-(?P[0-9]{4})?" + # Examples: + # CCEVS-VR-VID10015-2008 + # CCEVS-VR-10880-2018 + # CCEVS-VR-04-0082 CA: # '[0-9][0-9\-]+?-CR', # Canada - "[0-9][0-9][0-9]-[347]-[0-9][0-9][0-9]?(?:-CR|P)?" # Canada xxx-{347}-xxx (383-4-438, 383-4-82-CR, 383-4-422P) diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 188a2163..e84f6df2 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -10,7 +10,9 @@ def _parse_year(year: str | None) -> int | None: if year is None: return None y = int(year) - if y < 100: + if y < 50: + return y + 2000 + elif y < 100: return y + 1900 else: return y @@ -39,7 +41,7 @@ class CertificateId: new_cert_id += f"-{doc}" if version: new_cert_id += f"v{version}" - return new_cert_id + break return new_cert_id @@ -63,7 +65,27 @@ class CertificateId: new_cert_id += f"-{year}" if doc: new_cert_id += f"-{doc}" - return new_cert_id + break + + return new_cert_id + + def _canonical_us(self) -> str: + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["US"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + year = _parse_year(groups["year"]) + counter = groups["counter"] + cc = groups.get("cc") + vid = groups.get("VID") + new_cert_id = "CCEVS-VR" + if cc: + new_cert_id += f"-{cc}" + if vid: + new_cert_id += f"-{vid}" + new_cert_id += f"-{counter}" + new_cert_id += f"-{year}" + break return new_cert_id @@ -147,6 +169,7 @@ class CertificateId: schemes = { "FR": self._canonical_fr, "DE": self._canonical_de, + "US": self._canonical_us, "ES": self._canonical_es, "IT": self._canonical_it, "IN": self._canonical_in, diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index b9654c91..6fde3339 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -13,6 +13,12 @@ def test_canonicalize_de(): assert canonicalize("BSI-DSZ-CC-0837-V2-2014-MA-01", "DE") == "BSI-DSZ-CC-0837-V2-2014-MA-01" +def test_canonicalize_us(): + assert canonicalize("CCEVS-VR-VID10015-2008", "US") == "CCEVS-VR-VID-10015-2008" + assert canonicalize("CCEVS-VR-10880-2018", "US") == "CCEVS-VR-10880-2018" + assert canonicalize("CCEVS-VR-04-0082", "US") == "CCEVS-VR-0082-2004" + + def test_canonicalize_es(): assert canonicalize("2011-14-INF-1095-v1", "ES") == "2011-14-INF-1095" -- cgit v1.3.1 From 48876d5979adf8a63e2141262acd16608fc2aeda Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 17:14:17 +0100 Subject: Improve Malaysian rules. --- src/sec_certs/rules.yaml | 6 +++++- src/sec_certs/sample/cc_certificate_id.py | 14 ++++++++++++++ tests/cc/test_cc_misc.py | 6 ++++++ 3 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index fa188052..6b63b991 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -60,7 +60,11 @@ cc_cert_id: - "JISEC-CC-CRP-C[0-9]+-[0-9]+-[0-9]+" # Japan (JISEC-CC-CRP-C0689-01-2020) - "Certification No. [cC][0-9]+" # Japan (Certification No. C0090) MY: - - "ISCB-[0-9]+-(?:RPT|FRM)-[CM][0-9]+[A-Z]?-(?:CR|AMR)(?:-[0-9])?-[vV][0-9](?:\\.[0-9])?[a-z]?" # Malaysia (ISCB-3-RPT-C092-CR-v1, ISCB-3-RPT-C068-CR-1-v1) + - "ISCB-(?P[0-9])-RPT-C(?P[0-9]{3})-CR(?:-[0-9])?-(?P[vV][0-9][a-z]?)" + # Examples: + # ISCB-3-RPT-C068-CR-1-v1 + # ISCB-5-RPT-C075-CR-v2 + # ISCB-5-RPT-C046-CR-V1a IT: - "OCSI/CERT/.+?" # Italy - "OCSI/CERT/.+?/20[0-9]+(?:\\w|/RC)" # Italy (OCSI/CERT/ATS/01/2018/RC) diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index e84f6df2..42dc9e6f 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -89,6 +89,19 @@ class CertificateId: return new_cert_id + def _canonical_my(self) -> str: + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["MY"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + digit = groups["digit"] + counter = groups["counter"] + version = groups["version"] + new_cert_id = f"ISCB-{digit}-RPT-C{counter}-CR-{version.lower()}" + break + + return new_cert_id + def _canonical_es(self) -> str: cert_id = self.clean spain_parts = cert_id.split("-") @@ -170,6 +183,7 @@ class CertificateId: "FR": self._canonical_fr, "DE": self._canonical_de, "US": self._canonical_us, + "MY": self._canonical_my, "ES": self._canonical_es, "IT": self._canonical_it, "IN": self._canonical_in, diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 6fde3339..d439d508 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -19,6 +19,12 @@ def test_canonicalize_us(): assert canonicalize("CCEVS-VR-04-0082", "US") == "CCEVS-VR-0082-2004" +def test_canonicalize_my(): + assert canonicalize("ISCB-5-RPT-C075-CR-v2", "MY") == "ISCB-5-RPT-C075-CR-v2" + assert canonicalize("ISCB-5-RPT-C046-CR-V1a", "MY") == "ISCB-5-RPT-C046-CR-v1a" + assert canonicalize("ISCB-3-RPT-C068-CR-1-v1", "MY") == "ISCB-3-RPT-C068-CR-v1" + + def test_canonicalize_es(): assert canonicalize("2011-14-INF-1095-v1", "ES") == "2011-14-INF-1095" -- cgit v1.3.1 From affffb9fc08b09d39806815a741832df79cd95e5 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 18:37:48 +0100 Subject: Improve Japanese rules. --- src/sec_certs/rules.yaml | 10 +++++++--- src/sec_certs/sample/cc_certificate_id.py | 16 ++++++++++++---- tests/cc/test_cc_misc.py | 6 +++--- 3 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 6b63b991..95a834ba 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -56,9 +56,13 @@ cc_cert_id: # - "KECS[-‐]CR[-‐][0-9]+[-‐][0-9]+" # Korea KECS-CR-20-61 - "KECS[-‐](?:ISIS|NISS|CISS)[-‐][0-9]+[-‐][0-9]{4}" # Korea KECS-ISIS-1234-2011 JP: - - "(?:CRP|ACR)-C[0-9]+-[0-9]+" # Japan (CRP-C0595-01 ACR-C0417-03) - - "JISEC-CC-CRP-C[0-9]+-[0-9]+-[0-9]+" # Japan (JISEC-CC-CRP-C0689-01-2020) - - "Certification No. [cC][0-9]+" # Japan (Certification No. C0090) + - "(?:CRP|ACR)-C(?P[0-9]+)-(?P[0-9]+)" + - "JISEC-CC-CRP-C(?P[0-9]+)-(?P[0-9]+)-(?P[0-9]{4})" + - "Certification No. [cC](?P[0-9]+)" + # Examples: + # CRP-C0595-01 + # JISEC-CC-CRP-C0689-01-2020 + # Certification No. C0090 MY: - "ISCB-(?P[0-9])-RPT-C(?P[0-9]{3})-CR(?:-[0-9])?-(?P[vV][0-9][a-z]?)" # Examples: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 42dc9e6f..fe362b99 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -147,10 +147,18 @@ class CertificateId: def _canonical_jp(self): new_cert_id = self.clean - if match := re.match("Certification No. (C[0-9]+)", new_cert_id): - return match.group(1) - if match := re.search("CRP-(C[0-9]+)-", new_cert_id): - return match.group(1) + for rule in rules["cc_cert_id"]["JP"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + counter = groups["counter"] + digit = groups.get("digit") + year = _parse_year(groups.get("year")) + new_cert_id = f"JISEC-CC-CRP-C{counter}" + if digit: + new_cert_id += f"-{digit}" + if year: + new_cert_id += f"-{year}" + break return new_cert_id def _canonical_no(self): diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index d439d508..3772340f 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -53,9 +53,9 @@ def test_canonicalize_ca(): def test_canonicalize_jp(): - assert canonicalize("Certification No. C01234", "JP") == "C01234" - assert canonicalize("CRP-C01234-01", "JP") == "C01234" - assert canonicalize("JISEC-CC-CRP-C0689-01-2020", "JP") == "C0689" + assert canonicalize("Certification No. C01234", "JP") == "JISEC-CC-CRP-C01234" + assert canonicalize("CRP-C01234-01", "JP") == "JISEC-CC-CRP-C01234-01" + assert canonicalize("JISEC-CC-CRP-C0689-01-2020", "JP") == "JISEC-CC-CRP-C0689-01-2020" def test_canonicalize_no(): -- cgit v1.3.1 From a096f7ed6c4637dc700bd53df2d110bb8a428394 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 18:45:46 +0100 Subject: Improve UK rules. --- src/sec_certs/rules.yaml | 7 +++++-- src/sec_certs/sample/cc_certificate_id.py | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 95a834ba..8f5c6fd4 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -46,8 +46,11 @@ cc_cert_id: - "[0-9][0-9][0-9][ -](?:EWA|LSS|CCS)(?:[ -]20[0-9][0-9])?" # Canada (522-EWA-2020, 524 LSS 2020, 503-LSS) - "[0-9][0-9][0-9](?:%20|-)(?:EWA|LSS|CCS)(?:%20|-)(?:20[0-9][0-9]%20|)CR%20v[0-9]\\.[0-9]" # Canada filename with space (518-LSS%20CR%20v1.0) UK: - - "CRP[0-9]+[A-Z]?" # UK CESG - - "CERTIFICATION REPORT No. P[0-9]+[A-Z]?" # UK CESG + - "CRP(?P[0-9]+[A-Z]?)" + - "CERTIFICATION REPORT No. P(?P[0-9]+[A-Z]?)" + # Examples: + # CRP208 + # CERTIFICATION REPORT No. P123A ES: - "20[0-9][0-9][-‐][0-9]+[-‐]INF[-‐][0-9]+([-‐]?[ -‐](?:V|v)[0-9]+)?" # Spain ("2006-4-INF-98 v2" or "2006-4-INF-98-v2" or "2020-34-INF-3784- v1") KR: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index fe362b99..5ec168ee 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -133,8 +133,12 @@ class CertificateId: def _canonical_uk(self): new_cert_id = self.clean - if match := re.match("CERTIFICATION REPORT No. P([0-9]+[A-Z]?)", new_cert_id): - new_cert_id = "CRP" + match.group(1) + for rule in rules["cc_cert_id"]["UK"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + counter = groups["counter"] + new_cert_id = f"CRP{counter}" + break return new_cert_id def _canonical_ca(self): -- cgit v1.3.1 From 3efe520d01726c5c00428b9fd4b4d07d8bb4da5c Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 18:52:17 +0100 Subject: Improve Swedish rules. --- src/sec_certs/rules.yaml | 5 ++++- src/sec_certs/sample/cc_certificate_id.py | 9 ++++++++- tests/cc/test_cc_misc.py | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 8f5c6fd4..404931fc 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -79,7 +79,10 @@ cc_cert_id: - "[0-9\\.]+?/TSE-CCCS-[0-9]+" # Turkish CCCS (21.0.0sc/TSE-CCCS-75) - "(?:[0-9]{1,2}\\.){2}[0-9]{1,2}/[0-9]{1,4}-[0-9]{3}" # 21.0.01/13-028 SE: - - "CSEC ?[0-9]{6,7}" # Sweden (CSEC2019015) + - "CSEC ?(?P[0-9]{4})(?P[0-9]{2,3})" + # Examples: + # CSEC2019015 + # CSEC 2019012 IN: # India (IC3S/DEL01/VALIANT/EAL1/0317/0007/CR STQC/CC/14-15/12/ETR/0017 IC3S/MUM01/CISCO/cPP/0119/0016/CR) # will miss STQC/CC/14-15/12/ETR/0017 diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 5ec168ee..bdca0ab6 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -129,7 +129,14 @@ class CertificateId: return self.clean.replace(" ", "") def _canonical_se(self): - return self.clean.replace(" ", "") + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["SE"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + year = _parse_year(groups["year"]) + counter = int(groups["counter"]) + new_cert_id = f"CSEC{year}{counter:03}" + return new_cert_id def _canonical_uk(self): new_cert_id = self.clean diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 3772340f..b25620e4 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -4,6 +4,7 @@ from sec_certs.sample.cc_certificate_id import canonicalize def test_canonicalize_fr(): assert canonicalize("Rapport de certification 2001/02v2", "FR") == "ANSSI-CC-2001/02v2" assert canonicalize("ANSSI-CC 2001/02-R01", "FR") == "ANSSI-CC-2001/02-R01" + assert canonicalize("ANSSI-CC 2001_02-M01", "FR") == "ANSSI-CC-2001/02-M01" def test_canonicalize_de(): @@ -40,6 +41,7 @@ def test_canonicalize_in(): def test_canonicalize_se(): assert canonicalize("CSEC2017020", "SE") == "CSEC2017020" assert canonicalize("CSEC 2017020", "SE") == "CSEC2017020" + assert canonicalize("CSEC201003", "SE") == "CSEC2010003" def test_canonicalize_uk(): -- cgit v1.3.1 From 22fad93ad165e858d4fb55e2b9b0166aac6d32a3 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 19:09:54 +0100 Subject: Improve Spanish rules. --- src/sec_certs/rules.yaml | 6 +++++- src/sec_certs/sample/cc_certificate_id.py | 24 +++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 404931fc..b4e54d20 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -52,7 +52,11 @@ cc_cert_id: # CRP208 # CERTIFICATION REPORT No. P123A ES: - - "20[0-9][0-9][-‐][0-9]+[-‐]INF[-‐][0-9]+([-‐]?[ -‐](?:V|v)[0-9]+)?" # Spain ("2006-4-INF-98 v2" or "2006-4-INF-98-v2" or "2020-34-INF-3784- v1") + - "(?P[0-9]{4})[-‐](?P[0-9]+)[-‐]INF[-‐](?P[0-9]+)[ -‐]{1,2}[vV](?P[0-9])" + # Examples: + # 2006-4-INF-98 v2 + # 2020-34-INF-3784- v1 + # 2019-20-INF-3379-v1 KR: # Korea # XXX: Do not use KECS-CR as those refer to the certificate report and do not represent the certificate id. diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index bdca0ab6..be30bcf5 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -103,19 +103,17 @@ class CertificateId: return new_cert_id def _canonical_es(self) -> str: - cert_id = self.clean - spain_parts = cert_id.split("-") - cert_year = spain_parts[0] - cert_batch = spain_parts[1].lstrip("0") - cert_num = spain_parts[3].lstrip("0") - - if "v" in cert_num: - cert_num = cert_num[: cert_num.find("v")] - if "V" in cert_num: - cert_num = cert_num[: cert_num.find("V")] - - new_cert_id = f"{cert_year}-{cert_batch}-INF-{cert_num.strip()}" # drop version # TODO: Maybe do not drop? - + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["ES"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + year = _parse_year(groups["year"]) + project = groups["project"] + counter = groups["counter"] + # Version is intentionally cut here, as it seems to refer to an internal version of the report. + # version = groups["version"] + new_cert_id = f"{year}-{project}-INF-{counter}" + break return new_cert_id def _canonical_it(self): -- cgit v1.3.1 From 7d56381b408dd6ab1ed7d7ebaa84d192419eb140 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 19:27:40 +0100 Subject: Improve Singaporean and Australian rules. --- src/sec_certs/rules.yaml | 14 +++++++++----- src/sec_certs/sample/cc_certificate_id.py | 17 +++++++++++++++++ tests/cc/test_cc_misc.py | 7 +++++++ 3 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index b4e54d20..b2b4a979 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -92,13 +92,17 @@ cc_cert_id: # will miss STQC/CC/14-15/12/ETR/0017 - "(?:IC3S|STQC/CC)/[^ ]+? ?/CR" SG: - - "CSA_CC_[0-9]+" # Singapore (CSA_CC_19001) + - "CSA_CC_(?P[0-9]{2})(?P[0-9]{3})" + # Examples: + # CSA_CC_19001 AU: - # Australia (EFS-T048 ETR 1.0, EFS-T056-ETR 1.0, DXC-EFC-T092-ETR 1.0) + - "(?:Certificate Number:|Certification Report) (?P[0-9]{2,4})/(?P[0-9]+)" # XXX: Do not use Australian ETR numbers, they are not certificate id. - # - "(?:EFS|EFT|DXC-EFC)-T[0-9]+(?: |-)ETR [0-9]+.[0-9]+" - - "Certificate Number: [0-9]{1,4}/[0-9]{1,4}" - - "Certification Report [0-9]+/[0-9]+" + # Examples: + # Certification Report 2007/06 + # Certificate Number: 2010/67 + # Certificate Number: 37/2006 !mistake + # Certification Report 97/76 !short year ##### # Common Criteria protection profile IDs, grouped by certification body (e.g. BSI) diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index be30bcf5..7e0b7f4a 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -183,6 +183,21 @@ class CertificateId: new_cert_id = f"{new_cert_id}-CR" return new_cert_id + def _canonical_au(self): + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["AU"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + counter = groups["counter"] + year_s = groups["year"] + if len(year_s) < len(counter): + # Hack for some mistakes in their ordering + year_s, counter = counter, year_s + year = _parse_year(year_s) + new_cert_id = f"Certificate Number: {year}/{counter}" + break + return new_cert_id + @property def clean(self) -> str: """ @@ -210,6 +225,8 @@ class CertificateId: "JP": self._canonical_jp, "NO": self._canonical_no, "NL": self._canonical_nl, + "AU": self._canonical_au, + # SG is canonical by default } if self.scheme in schemes: diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index b25620e4..e1d516b3 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -49,6 +49,13 @@ def test_canonicalize_uk(): assert canonicalize("CRP123A", "UK") == "CRP123A" +def test_canonicalize_au(): + assert canonicalize("Certification Report 2007/02", "AU") == "Certificate Number: 2007/02" + assert canonicalize("Certificate Number: 37/2006", "AU") == "Certificate Number: 2006/37" + assert canonicalize("Certificate Number: 2011/73", "AU") == "Certificate Number: 2011/73" + assert canonicalize("Certification Report 97/76", "AU") == "Certificate Number: 1997/76" + + def test_canonicalize_ca(): assert canonicalize("383-4-123-CR", "CA") == "383-4-123" assert canonicalize("383-4-123P", "CA") == "383-4-123" -- cgit v1.3.1 From 5e852ac4e42afaf7fb7a6f7b9493d276723fd7e7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Feb 2024 19:36:05 +0100 Subject: Improve Italian rules. --- src/sec_certs/rules.yaml | 8 ++++++-- src/sec_certs/sample/cc_certificate_id.py | 9 +-------- tests/cc/test_cc_misc.py | 4 ---- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index b2b4a979..c0acd3d4 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -77,8 +77,12 @@ cc_cert_id: # ISCB-5-RPT-C075-CR-v2 # ISCB-5-RPT-C046-CR-V1a IT: - - "OCSI/CERT/.+?" # Italy - - "OCSI/CERT/.+?/20[0-9]+(?:\\w|/RC)" # Italy (OCSI/CERT/ATS/01/2018/RC) + - "OCSI/CERT/(?:(?P[A-Z]{3})/)?(?P[0-9]{2,3})/(?P[0-9]{4})/RC" + # Examples: + # OCSI/CERT/SYS/04/2018/RC + # OCSI/CERT/CCL/10/2022/RC + # OCSI/CERT/TEC/09/2017/RC + # OCSI/CERT/ATS/06/2020/RC TR: - "[0-9\\.]+?/TSE-CCCS-[0-9]+" # Turkish CCCS (21.0.0sc/TSE-CCCS-75) - "(?:[0-9]{1,2}\\.){2}[0-9]{1,2}/[0-9]{1,4}-[0-9]{3}" # 21.0.01/13-028 diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 7e0b7f4a..88e1f4a7 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -116,13 +116,6 @@ class CertificateId: break return new_cert_id - def _canonical_it(self): - new_cert_id = self.clean - if not new_cert_id.endswith("/RC"): - new_cert_id = new_cert_id + "/RC" - - return new_cert_id - def _canonical_in(self): return self.clean.replace(" ", "") @@ -217,7 +210,6 @@ class CertificateId: "US": self._canonical_us, "MY": self._canonical_my, "ES": self._canonical_es, - "IT": self._canonical_it, "IN": self._canonical_in, "SE": self._canonical_se, "UK": self._canonical_uk, @@ -227,6 +219,7 @@ class CertificateId: "NL": self._canonical_nl, "AU": self._canonical_au, # SG is canonical by default + # IT is canonucal by default } if self.scheme in schemes: diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index e1d516b3..2c93c546 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -30,10 +30,6 @@ def test_canonicalize_es(): assert canonicalize("2011-14-INF-1095-v1", "ES") == "2011-14-INF-1095" -def test_canonicalize_it(): - assert canonicalize("OCSI/CERT/SYS/10/2016", "IT") == "OCSI/CERT/SYS/10/2016/RC" - - def test_canonicalize_in(): assert canonicalize("IC3S/KOL01/ADVA/EAL2/0520/0021 /CR", "IN") == "IC3S/KOL01/ADVA/EAL2/0520/0021/CR" -- cgit v1.3.1 From 4fbb063846eb2375ac735c88ca0abb7df7c11267 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 13:50:58 +0100 Subject: Improve Korean rules. --- src/sec_certs/rules.yaml | 8 +++++--- src/sec_certs/sample/cc_certificate_id.py | 13 +++++++++++++ tests/cc/test_cc_misc.py | 5 +++++ 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index c0acd3d4..5e000144 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -58,10 +58,12 @@ cc_cert_id: # 2020-34-INF-3784- v1 # 2019-20-INF-3379-v1 KR: - # Korea + - "KECS[-‐](?PISIS|NISS|CISS)[-‐](?P[0-9]{2,4})[-‐](?P[0-9]{4})" # XXX: Do not use KECS-CR as those refer to the certificate report and do not represent the certificate id. - # - "KECS[-‐]CR[-‐][0-9]+[-‐][0-9]+" # Korea KECS-CR-20-61 - - "KECS[-‐](?:ISIS|NISS|CISS)[-‐][0-9]+[-‐][0-9]{4}" # Korea KECS-ISIS-1234-2011 + # Examples: + # KECS-ISIS-0579-2015 + # KECS-NISS-0792-2017 + # KECS-CISS-1210-2023 JP: - "(?:CRP|ACR)-C(?P[0-9]+)-(?P[0-9]+)" - "JISEC-CC-CRP-C(?P[0-9]+)-(?P[0-9]+)-(?P[0-9]{4})" diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 88e1f4a7..5facf1a5 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -163,6 +163,18 @@ class CertificateId: break return new_cert_id + def _canonical_kr(self): + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["KR"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + word = groups["word"] + counter = int(groups["counter"]) + year = _parse_year(groups["year"]) + new_cert_id = f"KECS-{word}-{counter:04}-{year}" + break + return new_cert_id + def _canonical_no(self): new_cert_id = self.clean cert_num = int(new_cert_id.split("-")[1]) @@ -218,6 +230,7 @@ class CertificateId: "NO": self._canonical_no, "NL": self._canonical_nl, "AU": self._canonical_au, + "KR": self._canonical_kr, # SG is canonical by default # IT is canonucal by default } diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 2c93c546..50bd81c0 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -63,6 +63,11 @@ def test_canonicalize_jp(): assert canonicalize("JISEC-CC-CRP-C0689-01-2020", "JP") == "JISEC-CC-CRP-C0689-01-2020" +def test_canonicalize_KR(): + assert canonicalize("KECS-ISIS-0579-2015", "KR") == "KECS-ISIS-0579-2015" + assert canonicalize("KECS-CISS-10-2023", "KR") == "KECS-CISS-0010-2023" + + def test_canonicalize_no(): assert canonicalize("SERTIT-12", "NO") == "SERTIT-012" -- cgit v1.3.1 From 520ce49b95c7f79481a68f23ec74bffbc93a80c1 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 14:05:28 +0100 Subject: Improve Indian rules. --- src/sec_certs/rules.yaml | 10 +++++++--- src/sec_certs/sample/cc_certificate_id.py | 14 ++++++++++++-- tests/cc/test_cc_misc.py | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 5e000144..41357015 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -94,9 +94,13 @@ cc_cert_id: # CSEC2019015 # CSEC 2019012 IN: - # India (IC3S/DEL01/VALIANT/EAL1/0317/0007/CR STQC/CC/14-15/12/ETR/0017 IC3S/MUM01/CISCO/cPP/0119/0016/CR) - # will miss STQC/CC/14-15/12/ETR/0017 - - "(?:IC3S|STQC/CC)/[^ ]+? ?/CR" + - "IC3S/(?P[A-Z]+[0-9]+)/(?P[a-zA-Z_]+)/(?P[a-zA-Z0-9]+)/(?P[0-9]+)/(?P[0-9]+) ?(?:/CR)?" + # XXX: The cert IDs are often present only in the certificate and not in the report. + # The report often only has the report id, of the format "STQC/CC/1617/18/CR" + # Examples: + # IC3S/BG01/HALTDOS/EAL2/0317/0008/CR + # IC3S/KOL01/ADVA/EAL2/0520/0021/CR + # IC3S/MUM01/Symantec/NDcPP/0722/0032/CR SG: - "CSA_CC_(?P[0-9]{2})(?P[0-9]{3})" # Examples: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 5facf1a5..7997b846 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -117,7 +117,17 @@ class CertificateId: return new_cert_id def _canonical_in(self): - return self.clean.replace(" ", "") + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["IN"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + lab = groups["lab"] + vendor = groups["vendor"] + level = groups["level"] + number1, number2 = groups["number1"], groups["number2"] + new_cert_id = f"IC3S/{lab}/{vendor}/{level}/{number1}/{number2}" + break + return new_cert_id def _canonical_se(self): new_cert_id = self.clean @@ -232,7 +242,7 @@ class CertificateId: "AU": self._canonical_au, "KR": self._canonical_kr, # SG is canonical by default - # IT is canonucal by default + # IT is canonical by default } if self.scheme in schemes: diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 50bd81c0..ca32fe91 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -31,7 +31,7 @@ def test_canonicalize_es(): def test_canonicalize_in(): - assert canonicalize("IC3S/KOL01/ADVA/EAL2/0520/0021 /CR", "IN") == "IC3S/KOL01/ADVA/EAL2/0520/0021/CR" + assert canonicalize("IC3S/KOL01/ADVA/EAL2/0520/0021 /CR", "IN") == "IC3S/KOL01/ADVA/EAL2/0520/0021" def test_canonicalize_se(): -- cgit v1.3.1 From 1927e44223723c038c98ee0516bf67f6a20eff8e Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 15:28:41 +0100 Subject: Improve Turkish rules. --- src/sec_certs/rules.yaml | 7 +++++-- src/sec_certs/sample/cc_certificate_id.py | 12 ++++++++++++ tests/cc/test_cc_misc.py | 7 ++++++- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 41357015..3cb5d4d3 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -86,8 +86,11 @@ cc_cert_id: # OCSI/CERT/TEC/09/2017/RC # OCSI/CERT/ATS/06/2020/RC TR: - - "[0-9\\.]+?/TSE-CCCS-[0-9]+" # Turkish CCCS (21.0.0sc/TSE-CCCS-75) - - "(?:[0-9]{1,2}\\.){2}[0-9]{1,2}/[0-9]{1,4}-[0-9]{3}" # 21.0.01/13-028 + - "(?P[0-9\\.]+)/TSE-CCCS-(?P[0-9]+)" + # XXX: The report numbers are like "21.0.01/13-028" + # Examples: + # 21.0.03.0.00.00/TSE-CCCS-85 + # 21.0.03/TSE-CCCS-33 SE: - "CSEC ?(?P[0-9]{4})(?P[0-9]{2,3})" # Examples: diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 7997b846..901629c7 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -185,6 +185,17 @@ class CertificateId: break return new_cert_id + def _canonical_tr(self): + new_cert_id = self.clean + for rule in rules["cc_cert_id"]["TR"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + prefix = groups["prefix"] + number = groups["number"] + new_cert_id = f"{prefix}/TSE-CCCS-{number}" + break + return new_cert_id + def _canonical_no(self): new_cert_id = self.clean cert_num = int(new_cert_id.split("-")[1]) @@ -241,6 +252,7 @@ class CertificateId: "NL": self._canonical_nl, "AU": self._canonical_au, "KR": self._canonical_kr, + "TR": self._canonical_tr, # SG is canonical by default # IT is canonical by default } diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index ca32fe91..5204b89e 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -63,7 +63,7 @@ def test_canonicalize_jp(): assert canonicalize("JISEC-CC-CRP-C0689-01-2020", "JP") == "JISEC-CC-CRP-C0689-01-2020" -def test_canonicalize_KR(): +def test_canonicalize_kr(): assert canonicalize("KECS-ISIS-0579-2015", "KR") == "KECS-ISIS-0579-2015" assert canonicalize("KECS-CISS-10-2023", "KR") == "KECS-CISS-0010-2023" @@ -72,6 +72,11 @@ def test_canonicalize_no(): assert canonicalize("SERTIT-12", "NO") == "SERTIT-012" +def test_canonicalize_tr(): + assert canonicalize("21.0.03.0.00.00/TSE-CCCS-85", "TR") == "21.0.03.0.00.00/TSE-CCCS-85" + assert canonicalize("21.0.03/TSE-CCCS-33", "TR") == "21.0.03/TSE-CCCS-33" + + def test_canonicalize_nl(): assert canonicalize("NSCIB-CC-22-0428888-CR2", "NL") == "NSCIB-CC-22-0428888-CR2" assert canonicalize("NSCIB-CC-22-0428888", "NL") == "NSCIB-CC-22-0428888-CR" -- cgit v1.3.1 From d1b16b7086c63ee9b837f9a5b77971d9d7db9874 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 15:47:21 +0100 Subject: Improve Canadian rules. --- src/sec_certs/rules.yaml | 12 ++++++++---- src/sec_certs/sample/cc_certificate_id.py | 22 +++++++++++++++++----- tests/cc/test_cc_misc.py | 1 + 3 files changed, 26 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 3cb5d4d3..13d81c18 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -41,10 +41,14 @@ cc_cert_id: # CCEVS-VR-10880-2018 # CCEVS-VR-04-0082 CA: - # '[0-9][0-9\-]+?-CR', # Canada - - "[0-9][0-9][0-9]-[347]-[0-9][0-9][0-9]?(?:-CR|P)?" # Canada xxx-{347}-xxx (383-4-438, 383-4-82-CR, 383-4-422P) - - "[0-9][0-9][0-9][ -](?:EWA|LSS|CCS)(?:[ -]20[0-9][0-9])?" # Canada (522-EWA-2020, 524 LSS 2020, 503-LSS) - - "[0-9][0-9][0-9](?:%20|-)(?:EWA|LSS|CCS)(?:%20|-)(?:20[0-9][0-9]%20|)CR%20v[0-9]\\.[0-9]" # Canada filename with space (518-LSS%20CR%20v1.0) + - "(?P[0-9]+)[ -](?P[0-9])[ -](?P[0-9]+)(?:-CR|P)?" + - "(?P[0-9]+)[ -](?PEWA|LSS|CCS)(?:[ -](?P[0-9]+))?" + # Examples: + # 383-4-123-CR + # 383-4-123P + # 522 EWA 2020 + # Filename rule: + #- "[0-9][0-9][0-9](?:%20|-)(?:EWA|LSS|CCS)(?:%20|-)(?:20[0-9][0-9]%20|)CR%20v[0-9]\\.[0-9]" # Canada filename with space (518-LSS%20CR%20v1.0) UK: - "CRP(?P[0-9]+[A-Z]?)" - "CERTIFICATION REPORT No. P(?P[0-9]+[A-Z]?)" diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 901629c7..e5f86bba 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -151,11 +151,23 @@ class CertificateId: def _canonical_ca(self): new_cert_id = self.clean - if new_cert_id.endswith("-CR"): - new_cert_id = new_cert_id[:-3] - if new_cert_id.endswith("P"): - new_cert_id = new_cert_id[:-1] - return new_cert_id.replace(" ", "-") + for rule in rules["cc_cert_id"]["CA"]: + if match := re.match(rule, new_cert_id): + groups = match.groupdict() + if "lab" in groups: + year = _parse_year(groups.get("year")) + number = groups["number"] + lab = groups["lab"] + new_cert_id = f"{number}-{lab}" + if year: + new_cert_id += f"-{year}" + else: + number1 = groups["number1"] + digit = groups["digit"] + number2 = groups["number2"] + new_cert_id = f"{number1}-{digit}-{number2}" + break + return new_cert_id def _canonical_jp(self): new_cert_id = self.clean diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 5204b89e..5e67a58f 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -55,6 +55,7 @@ def test_canonicalize_au(): def test_canonicalize_ca(): assert canonicalize("383-4-123-CR", "CA") == "383-4-123" assert canonicalize("383-4-123P", "CA") == "383-4-123" + assert canonicalize("522 EWA 2020", "CA") == "522-EWA-2020" def test_canonicalize_jp(): -- cgit v1.3.1 From b05b86c32eb6068be317af1ce15e032f88d48807 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 15:55:36 +0100 Subject: Add certificateId meta property. --- src/sec_certs/sample/cc_certificate_id.py | 18 ++++++++++++++++++ tests/cc/test_cc_misc.py | 8 +++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index e5f86bba..023e6e54 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -2,6 +2,7 @@ from __future__ import annotations import re from dataclasses import dataclass +from functools import cached_property from sec_certs.cert_rules import rules @@ -27,6 +28,13 @@ class CertificateId: scheme: str raw: str + @cached_property + def meta(self): + for rule in rules["cc_cert_id"][self.scheme]: + if match := re.match(rule, self.clean): + return match.groupdict() + return {} + def _canonical_fr(self) -> str: new_cert_id = self.clean for rule in rules["cc_cert_id"]["FR"]: @@ -274,6 +282,16 @@ class CertificateId: else: return self.clean + def __hash__(self): + return hash((self.scheme, self.raw)) + + def __eq__(self, other): + if isinstance(other, str): + return self.canonical == other + if not isinstance(other, CertificateId): + return False + return self.canonical == other.canonical and self.scheme == other.scheme + def canonicalize(cert_id_str: str, scheme: str) -> str: return CertificateId(scheme, cert_id_str).canonical diff --git a/tests/cc/test_cc_misc.py b/tests/cc/test_cc_misc.py index 5e67a58f..5de22216 100644 --- a/tests/cc/test_cc_misc.py +++ b/tests/cc/test_cc_misc.py @@ -1,4 +1,10 @@ -from sec_certs.sample.cc_certificate_id import canonicalize +from sec_certs.sample.cc_certificate_id import CertificateId, canonicalize + + +def test_meta_parse(): + i = CertificateId("FR", "Rapport de certification 2001/02v2") + assert "year" in i.meta + assert i.meta["year"] == "2001" def test_canonicalize_fr(): -- cgit v1.3.1 From 9ad30df4652a3246bb316a9d98cf96e102745768 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 17:38:50 +0100 Subject: Add filename cert id rules. --- src/sec_certs/rules.yaml | 37 +++++++++++++++++++++++++++++++ src/sec_certs/sample/cc_certificate_id.py | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 13d81c18..7cd5996e 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -121,6 +121,43 @@ cc_cert_id: # Certificate Number: 37/2006 !mistake # Certification Report 97/76 !short year +##### +# Common Criteria certificate IDs as they appear in report filenames, grouped by scheme (Alpha-2 ISO country code). +##### +cc_filename_cert_id: + DE: + - "(?P[0-9]{3,5})(?:(?P[vV][0-9]))?a?(?:_pdf)?" + - "(?P[0-9]{4})(?P[0-9]{2})(?P[0-9]{2})_(?P[0-9]{3,5})(?:(?P[vV][0-9]))?a?(?:_pdf)?" + FR: + - "(?P[0-9]{4})[_-](?P[0-9]{2})([vV](?P[0-9]))?" + - "(?P[0-9]{2})(?P[0-9]{2})([vV](?P[0-9]))?" + NL: + - "(?:NSCIB-|CC-|NSCIB-CC-)(?P((?P[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P(?:CR|MA|MR)[0-9]*))?" + "NO": + - "SERTIT-(?P[0-9]+)" + US: + CA: + - "(?P[0-9]+)[ -](?P[0-9])[ -](?P[0-9]+)(?:-CR|P)?" + - "(?P[0-9]+)[ -](?PEWA|LSS|CCS)(?:[ -](?P[0-9]+))?" + UK: + - "CRP(?P[0-9]+[A-Z]?)" + ES: + - "(?P[0-9]{4})[-‐](?P[0-9]+)[-‐]INF[-‐](?P[0-9]+)[ -‐_]{1,2}[vV](?P[0-9])" + KR: + - "(?PISIS|NISS|CISS)[-‐](?P[0-9]{2,4})(?:[-‐](?P[0-9]{4}))?" + JP: + - "[cC](?P[0-9]+)" + MY: + - "ISCB-(?P[0-9])-RPT-C(?P[0-9]{3})-CR(?:-[0-9])?-(?P[vV][0-9][a-z]?)" + IT: + TR: + SE: + - "CR(?P[0-9]{4})(?P[0-9]{2,3})" + IN: + SG: + AU: + - "(?P[0-9]{2,4})_(?P[0-9]+)" + ##### # Common Criteria protection profile IDs, grouped by certification body (e.g. BSI) ##### diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 023e6e54..584039b6 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -19,7 +19,7 @@ def _parse_year(year: str | None) -> int | None: return y -@dataclass(eq=True, frozen=True) +@dataclass(frozen=True) class CertificateId: """ A Common Criteria certificate id. -- cgit v1.3.1 From 836139707bc2a826a1ff1c900c6e92854cb3d8bb Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 18:07:10 +0100 Subject: Move the meta -> str functions out of cert_id class. --- src/sec_certs/rules.yaml | 2 +- src/sec_certs/sample/cc_certificate_id.py | 414 ++++++++++++++---------------- tests/test_common.py | 2 +- 3 files changed, 188 insertions(+), 230 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index 7cd5996e..a0e1c82d 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -5,7 +5,7 @@ ##### cc_cert_id: DE: - - "BSI-DSZ-CC-(?:(?PS)-)?(?P[0-9]{3,5})-(?:(?P[vV][0-9])-)?(?P[0-9]{4})?(?:-(?P(?:RA|MA)(?:-[0-9]+)?))?" + - "BSI-DSZ-CC-(?:(?PS)-)?(?P[0-9]{3,5})-?(?:(?P[vV][0-9])-)?(?P[0-9]{4})?(?:-(?P(?:RA|MA)(?:-[0-9]+)?))?" # Examples: # BSI-DSZ-CC-1004 # BSI-DSZ-CC-0973-2016 diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index 584039b6..ee715082 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -19,6 +19,169 @@ def _parse_year(year: str | None) -> int | None: return y +def FR(meta) -> str: + year = _parse_year(meta["year"]) + counter = meta["counter"] + doc = meta.get("doc") + version = meta.get("version") + cert_id = f"ANSSI-CC-{year}/{counter}" + if doc: + cert_id += f"-{doc}" + if version: + cert_id += f"v{version}" + return cert_id + + +def DE(meta) -> str: + s = meta.get("s") + counter = meta["counter"] + version = meta.get("version") + year = _parse_year(meta.get("year")) + doc = meta.get("doc") + cert_id = "BSI-DSZ-CC" + if s: + cert_id += f"-{s}" + cert_id += f"-{counter}" + if version: + cert_id += f"-{version.upper()}" + if year: + cert_id += f"-{year}" + if doc: + cert_id += f"-{doc}" + return cert_id + + +def US(meta) -> str: + year = _parse_year(meta["year"]) + counter = meta["counter"] + cc = meta.get("cc") + vid = meta.get("VID") + cert_id = "CCEVS-VR" + if cc: + cert_id += f"-{cc}" + if vid: + cert_id += f"-{vid}" + cert_id += f"-{counter}" + cert_id += f"-{year}" + return cert_id + + +def MY(meta) -> str: + digit = meta["digit"] + counter = meta["counter"] + version = meta["version"] + return f"ISCB-{digit}-RPT-C{counter}-CR-{version.lower()}" + + +def ES(meta) -> str: + year = _parse_year(meta["year"]) + project = meta["project"] + counter = meta["counter"] + # Version is intentionally cut here, as it seems to refer to an internal version of the report. + # version = groups["version"] + return f"{year}-{project}-INF-{counter}" + + +def IN(meta) -> str: + lab = meta["lab"] + vendor = meta["vendor"] + level = meta["level"] + number1, number2 = meta["number1"], meta["number2"] + return f"IC3S/{lab}/{vendor}/{level}/{number1}/{number2}" + + +def SE(meta) -> str: + year = _parse_year(meta["year"]) + counter = int(meta["counter"]) + return f"CSEC{year}{counter:03}" + + +def UK(meta) -> str: + counter = meta["counter"] + return f"CRP{counter}" + + +def CA(meta) -> str: + if "lab" in meta: + year = _parse_year(meta.get("year")) + number = meta["number"] + lab = meta["lab"] + cert_id = f"{number}-{lab}" + if year: + cert_id += f"-{year}" + return cert_id + else: + number1 = meta["number1"] + digit = meta["digit"] + number2 = meta["number2"] + return f"{number1}-{digit}-{number2}" + + +def JP(meta) -> str: + counter = meta["counter"] + digit = meta.get("digit") + year = _parse_year(meta.get("year")) + cert_id = f"JISEC-CC-CRP-C{counter}" + if digit: + cert_id += f"-{digit}" + if year: + cert_id += f"-{year}" + return cert_id + + +def KR(meta) -> str: + word = meta["word"] + counter = int(meta["counter"]) + year = _parse_year(meta["year"]) + return f"KECS-{word}-{counter:04}-{year}" + + +def TR(meta) -> str: + prefix = meta["prefix"] + number = meta["number"] + return f"{prefix}/TSE-CCCS-{number}" + + +def NO(meta) -> str: + counter = int(meta["counter"]) + return f"SERTIT-{counter:03}" + + +def NL(meta) -> str: + core = meta["core"] + doc = meta.get("doc") + if doc is None: + doc = "CR" + return f"NSCIB-CC-{core}-{doc}" + + +def AU(meta) -> str: + counter = meta["counter"] + year_s = meta["year"] + if len(year_s) < len(counter): + # Hack for some mistakes in their ordering + year_s, counter = counter, year_s + year = _parse_year(year_s) + return f"Certificate Number: {year}/{counter}" + + +def SG(meta) -> str: + year = meta["year"] + counter = meta["counter"] + return f"CSA_CC_{year}{counter}" + + +def IT(meta) -> str: + lab = meta.get("lab") + counter = meta["counter"] + year = _parse_year(meta["year"]) + cert_id = "OCSI/CERT/" + if lab: + cert_id += f"{lab}/" + cert_id += f"{counter}/{year}/RC" + return cert_id + + @dataclass(frozen=True) class CertificateId: """ @@ -35,215 +198,6 @@ class CertificateId: return match.groupdict() return {} - def _canonical_fr(self) -> str: - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["FR"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - year = _parse_year(groups["year"]) - counter = groups["counter"] - doc = groups.get("doc") - version = groups.get("version") - new_cert_id = f"ANSSI-CC-{year}/{counter}" - if doc: - new_cert_id += f"-{doc}" - if version: - new_cert_id += f"v{version}" - break - - return new_cert_id - - def _canonical_de(self) -> str: - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["DE"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - s = groups.get("s") - counter = groups["counter"] - version = groups.get("version") - year = _parse_year(groups.get("year")) - doc = groups.get("doc") - new_cert_id = "BSI-DSZ-CC" - if s: - new_cert_id += f"-{s}" - new_cert_id += f"-{counter}" - if version: - new_cert_id += f"-{version.upper()}" - if year: - new_cert_id += f"-{year}" - if doc: - new_cert_id += f"-{doc}" - break - - return new_cert_id - - def _canonical_us(self) -> str: - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["US"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - year = _parse_year(groups["year"]) - counter = groups["counter"] - cc = groups.get("cc") - vid = groups.get("VID") - new_cert_id = "CCEVS-VR" - if cc: - new_cert_id += f"-{cc}" - if vid: - new_cert_id += f"-{vid}" - new_cert_id += f"-{counter}" - new_cert_id += f"-{year}" - break - - return new_cert_id - - def _canonical_my(self) -> str: - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["MY"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - digit = groups["digit"] - counter = groups["counter"] - version = groups["version"] - new_cert_id = f"ISCB-{digit}-RPT-C{counter}-CR-{version.lower()}" - break - - return new_cert_id - - def _canonical_es(self) -> str: - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["ES"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - year = _parse_year(groups["year"]) - project = groups["project"] - counter = groups["counter"] - # Version is intentionally cut here, as it seems to refer to an internal version of the report. - # version = groups["version"] - new_cert_id = f"{year}-{project}-INF-{counter}" - break - return new_cert_id - - def _canonical_in(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["IN"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - lab = groups["lab"] - vendor = groups["vendor"] - level = groups["level"] - number1, number2 = groups["number1"], groups["number2"] - new_cert_id = f"IC3S/{lab}/{vendor}/{level}/{number1}/{number2}" - break - return new_cert_id - - def _canonical_se(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["SE"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - year = _parse_year(groups["year"]) - counter = int(groups["counter"]) - new_cert_id = f"CSEC{year}{counter:03}" - return new_cert_id - - def _canonical_uk(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["UK"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - counter = groups["counter"] - new_cert_id = f"CRP{counter}" - break - return new_cert_id - - def _canonical_ca(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["CA"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - if "lab" in groups: - year = _parse_year(groups.get("year")) - number = groups["number"] - lab = groups["lab"] - new_cert_id = f"{number}-{lab}" - if year: - new_cert_id += f"-{year}" - else: - number1 = groups["number1"] - digit = groups["digit"] - number2 = groups["number2"] - new_cert_id = f"{number1}-{digit}-{number2}" - break - return new_cert_id - - def _canonical_jp(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["JP"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - counter = groups["counter"] - digit = groups.get("digit") - year = _parse_year(groups.get("year")) - new_cert_id = f"JISEC-CC-CRP-C{counter}" - if digit: - new_cert_id += f"-{digit}" - if year: - new_cert_id += f"-{year}" - break - return new_cert_id - - def _canonical_kr(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["KR"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - word = groups["word"] - counter = int(groups["counter"]) - year = _parse_year(groups["year"]) - new_cert_id = f"KECS-{word}-{counter:04}-{year}" - break - return new_cert_id - - def _canonical_tr(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["TR"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - prefix = groups["prefix"] - number = groups["number"] - new_cert_id = f"{prefix}/TSE-CCCS-{number}" - break - return new_cert_id - - def _canonical_no(self): - new_cert_id = self.clean - cert_num = int(new_cert_id.split("-")[1]) - return f"SERTIT-{cert_num:03}" - - def _canonical_nl(self): - new_cert_id = self.clean - if new_cert_id.startswith("CC-"): - new_cert_id = f"NSCIB-{new_cert_id}" - if not re.match(".*-(CR|MA|MR)[0-9]*$", new_cert_id): - new_cert_id = f"{new_cert_id}-CR" - return new_cert_id - - def _canonical_au(self): - new_cert_id = self.clean - for rule in rules["cc_cert_id"]["AU"]: - if match := re.match(rule, new_cert_id): - groups = match.groupdict() - counter = groups["counter"] - year_s = groups["year"] - if len(year_s) < len(counter): - # Hack for some mistakes in their ordering - year_s, counter = counter, year_s - year = _parse_year(year_s) - new_cert_id = f"Certificate Number: {year}/{counter}" - break - return new_cert_id - @property def clean(self) -> str: """ @@ -258,29 +212,33 @@ class CertificateId: """ # We have rules for some schemes to make canonical cert_ids. schemes = { - "FR": self._canonical_fr, - "DE": self._canonical_de, - "US": self._canonical_us, - "MY": self._canonical_my, - "ES": self._canonical_es, - "IN": self._canonical_in, - "SE": self._canonical_se, - "UK": self._canonical_uk, - "CA": self._canonical_ca, - "JP": self._canonical_jp, - "NO": self._canonical_no, - "NL": self._canonical_nl, - "AU": self._canonical_au, - "KR": self._canonical_kr, - "TR": self._canonical_tr, - # SG is canonical by default - # IT is canonical by default + "FR": FR, + "DE": DE, + "US": US, + "MY": MY, + "ES": ES, + "IN": IN, + "SE": SE, + "UK": UK, + "CA": CA, + "JP": JP, + "NO": NO, + "NL": NL, + "AU": AU, + "KR": KR, + "TR": TR, + "SG": SG, + "IT": IT, } + clean = self.clean if self.scheme in schemes: - return schemes[self.scheme]() + return schemes[self.scheme](self.meta) else: - return self.clean + return clean + + def __str__(self): + return self.canonical def __hash__(self): return hash((self.scheme, self.raw)) diff --git a/tests/test_common.py b/tests/test_common.py index fa7a3775..7b29dd8d 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -5,5 +5,5 @@ def test_rules(): assert "cc_cert_id" in cc_rules assert "fips_cert_id" in fips_rules for rule_group in rules: - if rule_group not in ("cc_rules", "fips_rules"): + if rule_group not in ("cc_rules", "fips_rules", "cc_filename_cert_id"): assert rule_group in cc_rules or rule_group in fips_rules -- cgit v1.3.1 From 4e24bb278c9da4e4f6c75f92187c6173d4269010 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 18:12:34 +0100 Subject: Extract and reconstruct cert ids from filenames. Before this, the regular cert_id regexes were used to extract the cert_id from the report filename. However, the filenames often do not use the same cert_id format, but contain all of the information necessary to reconstruct the cert_id, but with different order for example. This commit along with those before it introduce a new set of regular expressions that better match the ones in the filenames. To extract the correctly formatted canonical cert_id, the regexes are used to obtain the parts of the cert_id (using named groups in regexes) and those are then reconstructed into a canonical version of the cert_id via one of the scheme-dependent functions. --- src/sec_certs/sample/cc.py | 14 +++++++---- src/sec_certs/sample/cc_certificate_id.py | 42 ++++++++++++++++--------------- 2 files changed, 31 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/sec_certs/sample/cc.py b/src/sec_certs/sample/cc.py index 6ee2bd1b..8948bb76 100644 --- a/src/sec_certs/sample/cc.py +++ b/src/sec_certs/sample/cc.py @@ -19,7 +19,7 @@ import sec_certs.utils.pdf import sec_certs.utils.sanitization from sec_certs import constants from sec_certs.cert_rules import SARS_IMPLIED_FROM_EAL, cc_rules, rules, security_level_csv_scan -from sec_certs.sample.cc_certificate_id import canonicalize +from sec_certs.sample.cc_certificate_id import canonicalize, schemes from sec_certs.sample.certificate import Certificate, References, logger from sec_certs.sample.certificate import Heuristics as BaseHeuristics from sec_certs.sample.certificate import PdfData as BasePdfData @@ -337,13 +337,17 @@ class CCCertificate( """ if not self.report_filename: return {} - scheme_rules = rules["cc_cert_id"][scheme] + scheme_filename_rules = rules["cc_filename_cert_id"][scheme] + scheme_meta = schemes[scheme] matches: Counter = Counter() - for rule in scheme_rules: + for rule in scheme_filename_rules: match = re.search(rule, self.report_filename) if match: - cert_id = normalize_match_string(match.group()) - matches[cert_id] += 1 + try: + cert_id = scheme_meta(match.groupdict()) + matches[cert_id] += 1 + except Exception: + continue if not matches: return {} total = max(matches.values()) diff --git a/src/sec_certs/sample/cc_certificate_id.py b/src/sec_certs/sample/cc_certificate_id.py index ee715082..1fb7b046 100644 --- a/src/sec_certs/sample/cc_certificate_id.py +++ b/src/sec_certs/sample/cc_certificate_id.py @@ -182,6 +182,28 @@ def IT(meta) -> str: return cert_id +# We have rules for some schemes to make canonical cert_ids. +schemes = { + "FR": FR, + "DE": DE, + "US": US, + "MY": MY, + "ES": ES, + "IN": IN, + "SE": SE, + "UK": UK, + "CA": CA, + "JP": JP, + "NO": NO, + "NL": NL, + "AU": AU, + "KR": KR, + "TR": TR, + "SG": SG, + "IT": IT, +} + + @dataclass(frozen=True) class CertificateId: """ @@ -210,26 +232,6 @@ class CertificateId: """ The canonical version of this certificate id. """ - # We have rules for some schemes to make canonical cert_ids. - schemes = { - "FR": FR, - "DE": DE, - "US": US, - "MY": MY, - "ES": ES, - "IN": IN, - "SE": SE, - "UK": UK, - "CA": CA, - "JP": JP, - "NO": NO, - "NL": NL, - "AU": AU, - "KR": KR, - "TR": TR, - "SG": SG, - "IT": IT, - } clean = self.clean if self.scheme in schemes: -- cgit v1.3.1 From 40d89ff77f3e59455082da48e49b0e9f7b57d78a Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Feb 2024 18:28:01 +0100 Subject: Fix broken filename rules. --- src/sec_certs/rules.yaml | 4 ++-- src/sec_certs/sample/cc.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index a0e1c82d..4305b8cd 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -126,11 +126,11 @@ cc_cert_id: ##### cc_filename_cert_id: DE: - - "(?P[0-9]{3,5})(?:(?P[vV][0-9]))?a?(?:_pdf)?" + #- "(?P[0-9]{3,5})(?:(?P[vV][0-9]))?a?(?:_pdf)?" - "(?P[0-9]{4})(?P[0-9]{2})(?P[0-9]{2})_(?P[0-9]{3,5})(?:(?P[vV][0-9]))?a?(?:_pdf)?" FR: - "(?P[0-9]{4})[_-](?P[0-9]{2})([vV](?P[0-9]))?" - - "(?P[0-9]{2})(?P[0-9]{2})([vV](?P[0-9]))?" + #- "(?P[0-9]{2})(?P[0-9]{2})([vV](?P[0-9]))?" NL: - "(?:NSCIB-|CC-|NSCIB-CC-)(?P((?P[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P(?:CR|MA|MR)[0-9]*))?" "NO": diff --git a/src/sec_certs/sample/cc.py b/src/sec_certs/sample/cc.py index 8948bb76..ef1ff984 100644 --- a/src/sec_certs/sample/cc.py +++ b/src/sec_certs/sample/cc.py @@ -338,13 +338,16 @@ class CCCertificate( if not self.report_filename: return {} scheme_filename_rules = rules["cc_filename_cert_id"][scheme] + if not scheme_filename_rules: + return {} scheme_meta = schemes[scheme] matches: Counter = Counter() for rule in scheme_filename_rules: match = re.search(rule, self.report_filename) if match: try: - cert_id = scheme_meta(match.groupdict()) + meta = match.groupdict() + cert_id = scheme_meta(meta) matches[cert_id] += 1 except Exception: continue -- cgit v1.3.1