Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SignedData and SignerInfo

SignedData

Encapsulates signed content plus signer information (RFC 5652 §5).

class SignedData:
    @staticmethod
    def from_der(data: bytes) -> SignedData: ...
    def to_der(self) -> bytes: ...

    version: int
    encap_content_type: ObjectIdentifier
    encap_content: bytes | None     # OCTET STRING value bytes
    certificates: bytes | None      # raw [0] IMPLICIT value bytes
    crls: bytes | None              # raw [1] IMPLICIT value bytes
    signer_infos: list[SignerInfo]

Usage

from synta.cms import SignedData
import synta

# Parse a PKCS#7 SignedData blob (the [0] EXPLICIT wrapping from ContentInfo is
# handled internally when using synta.load_der_pkcs7_certificates; strip it
# manually if you have a raw ContentInfo).
data = open("message.p7s", "rb").read()
sd = SignedData.from_der(data)

print(f"version: {sd.version}")
print(f"content type: {sd.encap_content_type}")
print(f"signers: {len(sd.signer_infos)}")

# Access embedded certificates
if sd.certificates:
    # certificates is the raw [0] IMPLICIT bytes; wrap with SEQUENCE tag for Decoder
    certs_der = bytes([0x30]) + sd.certificates[1:]  # swap IMPLICIT [0] tag with SEQUENCE
    # ... decode with synta.Decoder

# Iterate signer infos
for si in sd.signer_infos:
    print(f"  digest alg: {si.digest_algorithm_oid}")
    print(f"  signature alg: {si.signature_algorithm_oid}")

SignerInfo

Per-signer structure within SignedData (RFC 5652 §5.3).

class SignerInfo:
    @staticmethod
    def from_der(data: bytes) -> SignerInfo: ...
    def to_der(self) -> bytes: ...

    version: int
    sid: bytes
    # Raw TLV bytes of the SignerIdentifier CHOICE:
    # - SEQUENCE tag (0x30) → issuerAndSerialNumber
    # - tag 0x80           → subjectKeyIdentifier

    digest_algorithm_oid: ObjectIdentifier
    digest_algorithm_params: bytes | None
    signature_algorithm_oid: ObjectIdentifier
    signature_algorithm_params: bytes | None
    signature: bytes

    signed_attrs: bytes | None
    # Raw [0] IMPLICIT bytes.  Replace the tag byte with 0x31 before hashing.

    unsigned_attrs: bytes | None

Usage

from synta.cms import SignedData
import synta

sd = SignedData.from_der(data)
for si in sd.signer_infos:
    print(f"digest:    {si.digest_algorithm_oid}")
    print(f"signature: {si.signature_algorithm_oid}")
    print(f"sig bytes: {si.signature.hex()}")

    if si.signed_attrs:
        # signed_attrs carries an IMPLICIT [0] tag; replace the first byte with 0x31
        # to get a valid SET TLV for hashing.
        attrs_set = b'\x31' + si.signed_attrs[1:]
        dec = synta.Decoder(attrs_set, synta.Encoding.DER)
        attrs_seq = dec.decode_set()
        while not attrs_seq.is_empty():
            attr_tlv = attrs_seq.decode_raw_tlv()
            # each attr_tlv is a complete Attribute SEQUENCE

See also CMS Overview and PKCS Loaders for load_der_pkcs7_certificates which extracts certificates from a SignedData automatically.