EnvelopedData
EnvelopedData implements RFC 5652 §6 — encrypted content with per-recipient key transport.
The content-encryption key (CEK) is encrypted under each recipient’s public key and carried
in RecipientInfo structures. The content itself is encrypted using a symmetric cipher.
Decryption and encryption require the openssl Cargo feature.
EnvelopedData
class EnvelopedData:
@staticmethod
def from_der(data: bytes) -> EnvelopedData: ...
def to_der(self) -> bytes: ...
def decrypt(self, private_key: PrivateKey) -> bytes: ...
# Decrypt using the recipient's private key.
# Raises ValueError if no matching RecipientInfo is found or decryption fails.
# Requires the openssl Cargo feature.
version: int
originator_info: bytes | None
recipient_infos: bytes # raw RecipientInfos SET bytes
content_type: ObjectIdentifier
content_encryption_algorithm_oid: ObjectIdentifier
content_encryption_algorithm_params: bytes | None
encrypted_content: bytes | None
unprotected_attrs: bytes | None
EnvelopedDataBuilder
Fluent builder for EnvelopedData (RFC 5652 §6). Requires the openssl Cargo feature.
class EnvelopedDataBuilder:
def __init__(
self,
plaintext: bytes,
recipients: list[tuple[Certificate | bytes, ObjectIdentifier]],
*,
content_enc_alg: ObjectIdentifier | None = None,
) -> None: ...
# recipients: list of (cert, key_wrap_oid) tuples.
# cert may be a Certificate object or DER bytes.
# key_wrap_oid: ID_RSAES_OAEP (recommended) or ID_RSA_ENCRYPTION (legacy).
# content_enc_alg defaults to id-aes256-CBC.
def add_originator_cert(self, cert: Certificate | bytes) -> EnvelopedDataBuilder: ...
def add_originator_crl(self, crl: CertificateList | bytes) -> EnvelopedDataBuilder: ...
def set_unprotected_attrs(self, attrs: bytes) -> EnvelopedDataBuilder: ...
def build(self) -> EnvelopedData: ...
Usage
import synta
from synta.cms import EnvelopedData, EnvelopedDataBuilder, ID_RSAES_OAEP, ID_AES256_CBC
# Encrypt for one recipient
recipient_cert = synta.Certificate.from_der(open("recipient.der", "rb").read())
plaintext = b"Confidential message."
ed = EnvelopedDataBuilder(
plaintext,
[(recipient_cert, ID_RSAES_OAEP)],
content_enc_alg=ID_AES256_CBC,
).build()
ciphertext_der = ed.to_der()
# Decrypt
priv_key = synta.PrivateKey.from_pem(open("recipient.pem", "rb").read())
ed2 = EnvelopedData.from_der(ciphertext_der)
recovered = ed2.decrypt(priv_key)
assert recovered == plaintext
See also EncryptedData for shared-key symmetric encryption and CMS-KEM for quantum-safe KEM recipient structures.