From 483c492cf1cd86b379d59e3c956e1b6dffbfec0d Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Wed, 17 Jun 2026 11:57:46 +0200 Subject: [PATCH 1/2] feat: CryptoPrimitive cases for CycloneDX 1.7 Signed-off-by: Jan Kowalleck --- cyclonedx/model/crypto.py | 58 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/cyclonedx/model/crypto.py b/cyclonedx/model/crypto.py index a3d32d0ea..a38271973 100644 --- a/cyclonedx/model/crypto.py +++ b/cyclonedx/model/crypto.py @@ -59,6 +59,8 @@ class CryptoAssetType(str, Enum): @serializable.serializable_enum class CryptoPrimitive(str, Enum): + # TODO: rename to `CryptoAlgorithmPrimitive` + """ This is our internal representation of the cryptoPropertiesType.algorithmProperties.primitive ENUM type within the CycloneDX standard. @@ -78,16 +80,69 @@ class CryptoPrimitive(str, Enum): KDF = 'kdf' KEM = 'kem' KEY_AGREE = 'key-agree' + KEY_WRAP = 'key-wrap' # since CDX1.7 MAC = 'mac' PKE = 'pke' SIGNATURE = 'signature' STREAM_CIPHER = 'stream-cipher' XOF = 'xof' - + # -- OTHER = 'other' UNKNOWN = 'unknown' +class _CryptoPrimitiveSerializationHelper(serializable.helpers.BaseHelper): + """ THIS CLASS IS NON-PUBLIC API """ + + __CASES: dict[type[serializable.ViewType], frozenset[CryptoPrimitive]] = dict() + __CASES[SchemaVersion1Dot6] = frozenset({ + CryptoPrimitive.AE, + CryptoPrimitive.BLOCK_CIPHER, + CryptoPrimitive.COMBINER, + CryptoPrimitive.DRBG, + CryptoPrimitive.HASH, + CryptoPrimitive.KDF, + CryptoPrimitive.KEM, + CryptoPrimitive.KEY_AGREE, + CryptoPrimitive.MAC, + CryptoPrimitive.PKE, + CryptoPrimitive.SIGNATURE, + CryptoPrimitive.STREAM_CIPHER, + CryptoPrimitive.XOF, + CryptoPrimitive.OTHER, + CryptoPrimitive.UNKNOWN, + }) + __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] | { + CryptoPrimitive.KEY_WRAP, + } + + @classmethod + def __normalize(cls, cp: CryptoPrimitive, view: type[serializable.ViewType]) -> str: + return ( + cp + if cp in cls.__CASES.get(view, ()) + else CryptoPrimitive.OTHER + ).value + + @classmethod + def json_normalize(cls, o: Any, *, + view: Optional[type[serializable.ViewType]], + **__: Any) -> str: + assert view is not None + return cls.__normalize(o, view) + + @classmethod + def xml_normalize(cls, o: Any, *, + view: Optional[type[serializable.ViewType]], + **__: Any) -> str: + assert view is not None + return cls.__normalize(o, view) + + @classmethod + def deserialize(cls, o: Any) -> CryptoPrimitive: + return CryptoPrimitive(o) + + @serializable.serializable_enum class CryptoExecutionEnvironment(str, Enum): """ @@ -303,6 +358,7 @@ def __init__( self.nist_quantum_security_level = nist_quantum_security_level @property + @serializable.type_mapping(_CryptoPrimitiveSerializationHelper) @serializable.xml_sequence(1) def primitive(self) -> Optional[CryptoPrimitive]: """ From 2e7d79c6e35b90760fbe38b529a04a3fea43dd1b Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Wed, 17 Jun 2026 11:59:53 +0200 Subject: [PATCH 2/2] feat: CryptoPrimitive cases for CycloneDX 1.7 Signed-off-by: Jan Kowalleck --- cyclonedx/model/crypto.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cyclonedx/model/crypto.py b/cyclonedx/model/crypto.py index a38271973..46dbf46d1 100644 --- a/cyclonedx/model/crypto.py +++ b/cyclonedx/model/crypto.py @@ -59,8 +59,6 @@ class CryptoAssetType(str, Enum): @serializable.serializable_enum class CryptoPrimitive(str, Enum): - # TODO: rename to `CryptoAlgorithmPrimitive` - """ This is our internal representation of the cryptoPropertiesType.algorithmProperties.primitive ENUM type within the CycloneDX standard.