From ef2eb240e8e12d35c3642d2e8d04c56c47252c70 Mon Sep 17 00:00:00 2001 From: PascalDR Date: Wed, 23 Apr 2025 16:37:06 +0200 Subject: [PATCH 1/3] feat: added status descriptor dict --- pymdoccbor/mdoc/exceptions.py | 3 +++ pymdoccbor/mdoc/issuer.py | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pymdoccbor/mdoc/exceptions.py b/pymdoccbor/mdoc/exceptions.py index 1cb70ad..2b25da3 100644 --- a/pymdoccbor/mdoc/exceptions.py +++ b/pymdoccbor/mdoc/exceptions.py @@ -9,3 +9,6 @@ class NoSignedDocumentProvided(Exception): class MissingIssuerAuth(Exception): pass + +class InvalidStatusDescriptor(Exception): + pass \ No newline at end of file diff --git a/pymdoccbor/mdoc/issuer.py b/pymdoccbor/mdoc/issuer.py index a8b0a5d..f56ad01 100644 --- a/pymdoccbor/mdoc/issuer.py +++ b/pymdoccbor/mdoc/issuer.py @@ -11,6 +11,7 @@ from pymdoccbor.mso.issuer import MsoIssuer from cbor_diag import cbor2diag +from pymdoccbor.mdoc.exceptions import InvalidStatusDescriptor logger = logging.getLogger("pymdoccbor") @@ -74,7 +75,8 @@ def new( validity: dict = None, devicekeyinfo: Union[dict, CoseKey, str] = None, cert_path: str = None, - revocation: dict = None + revocation: dict = None, + status: dict = None ) -> dict: """ create a new mdoc with signed mso @@ -85,6 +87,7 @@ def new( :param devicekeyinfo: Union[dict, CoseKey, str]: device key info :param cert_path: str: path to the certificate :param revocation: dict: revocation status dict it may include status_list and identifier_list keys + :param status: dict: status dict that includes the status list's uri and the idx following the "https://datatracker.ietf.org/doc/draft-ietf-oauth-status-list" specification :return: dict: signed mdoc """ @@ -188,6 +191,17 @@ def new( "status": self.status, } + if status: + if not "status_list" in status: + raise InvalidStatusDescriptor("status_list is required") + + if not "uri" in status["status_list"]: + raise InvalidStatusDescriptor("uri is required") + if not "idx" in status["status_list"]: + raise InvalidStatusDescriptor("idx is required") + + res["status"] = status + logger.debug(f"MSO diagnostic notation: {cbor2diag(mso_cbor)}") self.signed = res From c0e394b420b4108c1e861c18cbbdfe73a8a085be Mon Sep 17 00:00:00 2001 From: PascalDR Date: Wed, 23 Apr 2025 16:41:09 +0200 Subject: [PATCH 2/3] feat: added status field --- pymdoccbor/mdoc/verifier.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pymdoccbor/mdoc/verifier.py b/pymdoccbor/mdoc/verifier.py index 5311c8b..6c9bd3a 100644 --- a/pymdoccbor/mdoc/verifier.py +++ b/pymdoccbor/mdoc/verifier.py @@ -200,6 +200,8 @@ def verify(self) -> bool: doc_cnt += 1 + self.status = cdict.get('status', None) + return False if self.documents_invalid else True def __repr__(self) -> str: From 310c4d82d4529566c539c74e7bbc6c105a8b71c5 Mon Sep 17 00:00:00 2001 From: PascalDR Date: Wed, 23 Apr 2025 16:46:31 +0200 Subject: [PATCH 3/3] tests: added tests for status descriptor --- pymdoccbor/tests/test_08_mdoc_cbor.py | 77 ++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/pymdoccbor/tests/test_08_mdoc_cbor.py b/pymdoccbor/tests/test_08_mdoc_cbor.py index c184a34..390c007 100644 --- a/pymdoccbor/tests/test_08_mdoc_cbor.py +++ b/pymdoccbor/tests/test_08_mdoc_cbor.py @@ -18,6 +18,12 @@ def test_mdoc_cbor_creation(): "issuance_date": "2024-12-31", "expiry_date": "2050-12-31" }, + status={ + "status_list": { + "idx": 412, + "uri": "https://example.com/statuslists/1" + } + } ) data = cbor2.dumps(mdoc) @@ -28,4 +34,73 @@ def test_mdoc_cbor_creation(): assert mdoc assert 'org.micov.medical.1' in mdocp.disclosure_map - assert mdocp.disclosure_map == MICOV_DATA \ No newline at end of file + assert mdocp.disclosure_map == MICOV_DATA + assert mdocp.status == { + "status_list": { + "idx": 412, + "uri": "https://example.com/statuslists/1" + } + } + +def test_mdoc_cbor_invalid_status(): + mdoci = MdocCborIssuer( + private_key=PKEY, + alg="ES256", + ) + + try: + mdoci.new( + data=MICOV_DATA, + #devicekeyinfo=PKEY, # TODO + doctype="org.micov.medical.1", + validity={ + "issuance_date": "2024-12-31", + "expiry_date": "2050-12-31" + }, + status={ + "status_list": { + "idx": 412, + # "uri": "https://example.com/statuslists/1" # Missing URI + } + } + ) + except Exception as e: + assert str(e) == "uri is required" + + try: + mdoci.new( + data=MICOV_DATA, + #devicekeyinfo=PKEY, # TODO + doctype="org.micov.medical.1", + validity={ + "issuance_date": "2024-12-31", + "expiry_date": "2050-12-31" + }, + status={ + "status_list": { + #"idx": 412, + "uri": "https://example.com/statuslists/1" # Missing URI + } + } + ) + except Exception as e: + assert str(e) == "idx is required" + + try: + mdoci.new( + data=MICOV_DATA, + #devicekeyinfo=PKEY, # TODO + doctype="org.micov.medical.1", + validity={ + "issuance_date": "2024-12-31", + "expiry_date": "2050-12-31" + }, + status={ + "not_status_list": { + "idx": 412, + "uri": "https://example.com/statuslists/1" # Missing URI + } + } + ) + except Exception as e: + assert str(e) == "status_list is required" \ No newline at end of file