# CMS-KEM Types
`synta.kem` provides `KEMRecipientInfo` and `CMSORIforKEMOtherInfo` for RFC 9629
quantum-safe KEM recipient structures, along with ML-KEM (FIPS 203) OID constants.
`KEMRecipientInfo` is carried as an `OtherRecipientInfo` alternative identified by
`id-ori-kem` (`1.2.840.113549.1.9.16.13.3`).
```python
import synta.kem as kem
```
These types are also re-exported from `synta.cms`.
## KEMRecipientInfo
RFC 9629 §5 recipient structure for KEM-based key transport.
```python
class KEMRecipientInfo:
@staticmethod
def from_der(data: bytes) -> KEMRecipientInfo: ...
def to_der(self) -> bytes: ...
version: int # always 0
recipient_id: bytes # raw RecipientIdentifier CHOICE TLV
kem_algorithm_oid: ObjectIdentifier # KEM algorithm (e.g. ML-KEM-768)
kem_algorithm_params: bytes | None
kem_ciphertext: bytes # KEM ciphertext (kemct field)
kdf_algorithm_oid: ObjectIdentifier # key-derivation algorithm
kdf_algorithm_params: bytes | None
kek_length: int # KEK length in bytes (1–65535)
ukm: bytes | None # user keying material
key_encryption_algorithm_oid: ObjectIdentifier # key-wrap algorithm
key_encryption_algorithm_params: bytes | None
encrypted_key: bytes # encrypted content-encryption key
```
## CMSORIforKEMOtherInfo
RFC 9629 §5.3 — `otherInfo` input to the KDF when deriving a KEK from a KEM shared secret.
```python
class CMSORIforKEMOtherInfo:
@staticmethod
def from_der(data: bytes) -> CMSORIforKEMOtherInfo: ...
def to_der(self) -> bytes: ...
key_encryption_algorithm_oid: ObjectIdentifier
key_encryption_algorithm_params: bytes | None
kek_length: int
ukm: bytes | None
```
## OID constants
### ML-KEM OIDs (FIPS 203)
| `ID_ML_KEM_512` | `2.16.840.1.101.3.4.4.1` | ML-KEM-512 key encapsulation |
| `ID_ML_KEM_768` | `2.16.840.1.101.3.4.4.2` | ML-KEM-768 key encapsulation |
| `ID_ML_KEM_1024` | `2.16.840.1.101.3.4.4.3` | ML-KEM-1024 key encapsulation |
### CMS OtherRecipientInfo OIDs (RFC 9629 §6.2)
| `ID_ORI` | `1.2.840.113549.1.9.16.13` | Root arc for OtherRecipientInfo alternatives |
| `ID_ORI_KEM` | `1.2.840.113549.1.9.16.13.3` | Identifies a `KEMRecipientInfo` |
## Usage
```python
import synta
import synta.kem as kem
# Parse a KEMRecipientInfo from an OtherRecipientInfo body
kri = kem.KEMRecipientInfo.from_der(ori_body_der)
print(f"KEM algorithm: {kri.kem_algorithm_oid}")
print(f"KDF algorithm: {kri.kdf_algorithm_oid}")
print(f"KEK length: {kri.kek_length}")
print(f"ciphertext: {kri.kem_ciphertext.hex()}")
# Check if this is an ML-KEM-768 recipient
if kri.kem_algorithm_oid == kem.ID_ML_KEM_768:
# Decapsulate with a PrivateKey
priv_key = synta.PrivateKey.from_der(kem_priv_der)
shared_secret = priv_key.kem_decapsulate(kri.kem_ciphertext)
# Then apply KDF (kri.kdf_algorithm_oid) over shared_secret + kri.ukm to derive KEK
```
See also [Keys](../pki/keys.md) for `PublicKey.kem_encapsulate()` and
`PrivateKey.kem_decapsulate()`, and [CMS Overview](overview.md) for the full module import.