From bd352051e08cce76def5c4891504f2811462419c Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Mon, 26 Oct 2026 12:06:16 +0800 Subject: [PATCH] Typed but unhandled extensions preserve DER via public_bytes() --- .../kca-core/src/kca/core/extensions.py | 6 ++-- server/packages/kca-core/tests/test_core.py | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/server/packages/kca-core/src/kca/core/extensions.py b/server/packages/kca-core/src/kca/core/extensions.py index 70ec512..ade5f7f 100644 --- a/server/packages/kca-core/src/kca/core/extensions.py +++ b/server/packages/kca-core/src/kca/core/extensions.py @@ -793,11 +793,11 @@ def _netscape_to_spec(ext: x509.Extension) -> Optional[Dict[str, Any]]: return spec -def _raw_value(ext: x509.Extension) -> Optional[bytes]: +def _raw_value(ext: x509.Extension) -> bytes: value = ext.value if isinstance(value, x509.UnrecognizedExtension): return value.value - return None + return value.public_bytes() def extension_specs(extensions: Iterable[x509.Extension]) -> Dict[str, Any]: @@ -892,7 +892,7 @@ def extension_specs(extensions: Iterable[x509.Extension]) -> Dict[str, Any]: { "oid": oid, "critical": ext.critical, - "der_hex": (value.value if isinstance(value, x509.UnrecognizedExtension) else b"").hex(), + "der_hex": _raw_value(ext).hex(), } ) if netscape: diff --git a/server/packages/kca-core/tests/test_core.py b/server/packages/kca-core/tests/test_core.py index eda4d6f..5e6bed8 100644 --- a/server/packages/kca-core/tests/test_core.py +++ b/server/packages/kca-core/tests/test_core.py @@ -82,6 +82,37 @@ class ExtensionTest(unittest.TestCase): self.assertEqual(exts[0].oid.dotted_string, "1.2.3.4") self.assertTrue(exts[0].critical) + def test_unhandled_typed_extension_roundtrip(self) -> None: + value = x509.SubjectInformationAccess( + [ + x509.AccessDescription( + x509.oid.AuthorityInformationAccessOID.OCSP, + x509.UniformResourceIdentifier("http://ocsp.example.com"), + ) + ] + ) + ext = x509.Extension( + oid=x509.oid.ExtensionOID.SUBJECT_INFORMATION_ACCESS, + critical=True, + value=value, + ) + + spec = extension_specs([ext]) + + self.assertEqual( + spec["raw"], + [ + { + "oid": ext.oid.dotted_string, + "critical": True, + "der_hex": value.public_bytes().hex(), + } + ], + ) + rebuilt = build_extensions(spec, public_key=None) + self.assertEqual(len(rebuilt), 1) + self.assertEqual(rebuilt[0].value.public_bytes(), value.public_bytes()) + class KeyTest(unittest.TestCase): def test_all_types(self) -> None: