High-level cryptographic message formats including CMS/PKCS#7 for signed and encrypted messages, PKCS#12 for key/certificate storage, Time Stamp Protocol (TSP) for trusted timestamps, and PDF signature structures. These formats provide comprehensive support for secure message exchange and long-term digital preservation.
Comprehensive support for CMS message formats used in secure email, document signing, and other cryptographic applications.
class ContentInfo(core.Sequence):
"""
CMS ContentInfo structure (RFC 5652).
Top-level container for all CMS content types.
Structure:
contentType: OBJECT IDENTIFIER - Content type
content: ANY OPTIONAL - Content data
"""
@property
def content_type(self):
"""Get the content type OID."""
@property
def content(self):
"""Get the content data."""
class SignedData(core.Sequence):
"""
CMS SignedData structure.
Used for digital signatures and can include the signed content.
Structure:
version: INTEGER - Version number
digestAlgorithms: DigestAlgorithmIdentifiers - Digest algorithms
encapContentInfo: EncapsulatedContentInfo - Content information
certificates: CertificateSet OPTIONAL - Signer certificates
crls: RevocationInfoChoices OPTIONAL - CRLs
signerInfos: SignerInfos - Signer information
"""
@property
def version(self):
"""Get the version number."""
@property
def digest_algorithms(self):
"""Get the digest algorithms used."""
@property
def encap_content_info(self):
"""Get the encapsulated content info."""
@property
def certificates(self):
"""Get the included certificates."""
@property
def crls(self):
"""Get the included CRLs."""
@property
def signer_infos(self):
"""Get the signer information."""
class EnvelopedData(core.Sequence):
"""
CMS EnvelopedData structure.
Used for encrypting content for one or more recipients.
Structure:
version: INTEGER - Version number
originatorInfo: OriginatorInfo OPTIONAL - Originator info
recipientInfos: RecipientInfos - Recipient information
encryptedContentInfo: EncryptedContentInfo - Encrypted content
unprotectedAttrs: UnprotectedAttributes OPTIONAL - Attributes
"""
@property
def version(self):
"""Get the version number."""
@property
def recipient_infos(self):
"""Get the recipient information."""
@property
def encrypted_content_info(self):
"""Get the encrypted content info."""
class DigestedData(core.Sequence):
"""
CMS DigestedData structure.
Provides message digest over content.
"""
@property
def version(self):
"""Get the version number."""
@property
def digest_algorithm(self):
"""Get the digest algorithm."""
@property
def encap_content_info(self):
"""Get the encapsulated content info."""
@property
def digest(self):
"""Get the computed digest."""
class EncryptedData(core.Sequence):
"""
CMS EncryptedData structure.
Provides encrypted content without key management.
"""
@property
def version(self):
"""Get the version number."""
@property
def encrypted_content_info(self):
"""Get the encrypted content info."""
class AuthenticatedData(core.Sequence):
"""
CMS AuthenticatedData structure.
Provides message authentication without encryption.
"""
@property
def version(self):
"""Get the version number."""
@property
def recipient_infos(self):
"""Get the recipient information."""
@property
def mac_algorithm(self):
"""Get the MAC algorithm."""
@property
def encap_content_info(self):
"""Get the encapsulated content info."""
@property
def mac(self):
"""Get the message authentication code."""
class CompressedData(core.Sequence):
"""
CMS CompressedData structure.
Provides content compression.
"""
@property
def version(self):
"""Get the version number."""
@property
def compression_algorithm(self):
"""Get the compression algorithm."""
@property
def encap_content_info(self):
"""Get the encapsulated content info."""
class AuthEnvelopedData(core.Sequence):
"""
CMS AuthEnvelopedData structure.
Provides authenticated encryption.
"""
@property
def version(self):
"""Get the version number."""
@property
def recipient_infos(self):
"""Get the recipient information."""
@property
def encrypted_content_info(self):
"""Get the encrypted content info."""
@property
def mac(self):
"""Get the message authentication code."""Supporting structures used within CMS messages.
class SignerInfo(core.Sequence):
"""
Signer information structure.
Contains information about a single signer.
Structure:
version: INTEGER - Version number
sid: SignerIdentifier - Signer identifier
digestAlgorithm: DigestAlgorithmIdentifier - Digest algorithm
signedAttrs: SignedAttributes OPTIONAL - Signed attributes
signatureAlgorithm: SignatureAlgorithmIdentifier - Signature algorithm
signature: OCTET STRING - Signature value
unsignedAttrs: UnsignedAttributes OPTIONAL - Unsigned attributes
"""
@property
def version(self):
"""Get the version number."""
@property
def sid(self):
"""Get the signer identifier."""
@property
def digest_algorithm(self):
"""Get the digest algorithm."""
@property
def signed_attrs(self):
"""Get the signed attributes."""
@property
def signature_algorithm(self):
"""Get the signature algorithm."""
@property
def signature(self):
"""Get the signature value."""
@property
def unsigned_attrs(self):
"""Get the unsigned attributes."""
class RecipientInfo(core.Choice):
"""
Recipient information structure.
Can be one of:
- KeyTransRecipientInfo: RSA key transport
- KeyAgreeRecipientInfo: Diffie-Hellman key agreement
- KEKRecipientInfo: Key encryption key
- PasswordRecipientInfo: Password-based encryption
- OtherRecipientInfo: Other recipient types
"""
@property
def recipient_type(self):
"""Get the recipient type."""
@property
def encrypted_key(self):
"""Get the encrypted key (if applicable)."""
class EncryptedContentInfo(core.Sequence):
"""
Encrypted content information.
Structure:
contentType: OBJECT IDENTIFIER - Content type
contentEncryptionAlgorithm: AlgorithmIdentifier - Encryption algorithm
encryptedContent: OCTET STRING OPTIONAL - Encrypted content
"""
@property
def content_type(self):
"""Get the content type."""
@property
def content_encryption_algorithm(self):
"""Get the encryption algorithm."""
@property
def encrypted_content(self):
"""Get the encrypted content."""Structures for securely storing keys and certificates in a single file.
class Pfx(core.Sequence):
"""
PKCS#12 Personal Information Exchange structure.
Top-level container for PKCS#12 files.
Structure:
version: INTEGER - Version number (always 3)
authSafe: ContentInfo - Authenticated safe
macData: MacData OPTIONAL - MAC for integrity
"""
@property
def version(self):
"""Get the version number."""
@property
def auth_safe(self):
"""Get the authenticated safe."""
@property
def mac_data(self):
"""Get the MAC data."""
class SafeBag(core.Sequence):
"""
Safe bag for storing keys and certificates.
Structure:
bagId: OBJECT IDENTIFIER - Bag type identifier
bagValue: ANY - Bag content
bagAttributes: Attributes OPTIONAL - Bag attributes
"""
@property
def bag_id(self):
"""Get the bag type identifier."""
@property
def bag_value(self):
"""Get the bag content."""
@property
def bag_attributes(self):
"""Get the bag attributes."""
class CertBag(core.Sequence):
"""
Certificate bag structure.
Structure:
certId: OBJECT IDENTIFIER - Certificate type
certValue: ANY - Certificate data
"""
@property
def cert_id(self):
"""Get the certificate type."""
@property
def cert_value(self):
"""Get the certificate data."""
class CrlBag(core.Sequence):
"""
CRL bag structure.
Structure:
crlId: OBJECT IDENTIFIER - CRL type
crlValue: ANY - CRL data
"""
@property
def crl_id(self):
"""Get the CRL type."""
@property
def crl_value(self):
"""Get the CRL data."""
class SecretBag(core.Sequence):
"""
Secret/key bag structure.
Structure:
secretTypeId: OBJECT IDENTIFIER - Secret type
secretValue: ANY - Secret data
"""
@property
def secret_type_id(self):
"""Get the secret type."""
@property
def secret_value(self):
"""Get the secret data."""
class SafeContents(core.SequenceOf):
"""
Sequence of safe bags.
"""Structures for trusted timestamping services (RFC 3161).
class TimeStampReq(core.Sequence):
"""
Time Stamp Request structure.
Structure:
version: INTEGER - Version number
messageImprint: MessageImprint - Message to be timestamped
reqPolicy: TSAPolicyId OPTIONAL - Requested policy
nonce: INTEGER OPTIONAL - Random nonce
certReq: BOOLEAN OPTIONAL - Certificate request flag
extensions: Extensions OPTIONAL - Request extensions
"""
@property
def version(self):
"""Get the version number."""
@property
def message_imprint(self):
"""Get the message imprint."""
@property
def req_policy(self):
"""Get the requested policy."""
@property
def nonce(self):
"""Get the nonce value."""
@property
def cert_req(self):
"""Get the certificate request flag."""
class TimeStampResp(core.Sequence):
"""
Time Stamp Response structure.
Structure:
status: PKIStatus - Response status
timeStampToken: ContentInfo OPTIONAL - Time stamp token
"""
@property
def status(self):
"""Get the response status."""
@property
def time_stamp_token(self):
"""Get the time stamp token."""
class TSTInfo(core.Sequence):
"""
Time Stamp Token Info structure.
Structure:
version: INTEGER - Version number
policy: TSAPolicyId - TSA policy
messageImprint: MessageImprint - Message imprint
serialNumber: INTEGER - Serial number
genTime: GeneralizedTime - Generation time
accuracy: Accuracy OPTIONAL - Time accuracy
ordering: BOOLEAN OPTIONAL - Ordering flag
nonce: INTEGER OPTIONAL - Nonce
tsa: GeneralName OPTIONAL - TSA identifier
extensions: Extensions OPTIONAL - Extensions
"""
@property
def version(self):
"""Get the version number."""
@property
def policy(self):
"""Get the TSA policy."""
@property
def message_imprint(self):
"""Get the message imprint."""
@property
def serial_number(self):
"""Get the serial number."""
@property
def gen_time(self):
"""Get the generation time."""
@property
def accuracy(self):
"""Get the time accuracy."""
class MessageImprint(core.Sequence):
"""
Message imprint structure.
Structure:
hashAlgorithm: AlgorithmIdentifier - Hash algorithm
hashedMessage: OCTET STRING - Message hash
"""
@property
def hash_algorithm(self):
"""Get the hash algorithm."""
@property
def hashed_message(self):
"""Get the message hash."""
class Accuracy(core.Sequence):
"""
Time accuracy specification.
Structure:
seconds: INTEGER OPTIONAL - Seconds accuracy
millis: INTEGER OPTIONAL - Milliseconds accuracy
micros: INTEGER OPTIONAL - Microseconds accuracy
"""
@property
def seconds(self):
"""Get the seconds accuracy."""
@property
def millis(self):
"""Get the milliseconds accuracy."""
@property
def micros(self):
"""Get the microseconds accuracy."""Adobe-specific structures for PDF document digital signatures.
class AdobeTimestamp(core.Sequence):
"""
Adobe timestamp structure for PDF signatures.
Adobe-specific timestamp format used in PDF digital signatures.
"""
class AdobeArchiveRevocationInfo(core.Sequence):
"""
Adobe archive revocation information.
Used in PDF long-term validation signatures.
"""from asn1crypto import cms, pem
# Load CMS signed data from file
with open('signed_message.p7s', 'rb') as f:
cms_data = f.read()
# Handle PEM encoding if present
if pem.detect(cms_data):
_, _, cms_der = pem.unarmor(cms_data)
else:
cms_der = cms_data
# Parse CMS content
content_info = cms.ContentInfo.load(cms_der)
print(f"Content Type: {content_info.content_type}")
if content_info.content_type == 'signed_data':
signed_data = content_info.content
print(f"Version: {signed_data.version}")
print(f"Digest Algorithms: {[alg.algorithm for alg in signed_data.digest_algorithms]}")
# Check encapsulated content
encap_content = signed_data.encap_content_info
print(f"Content Type: {encap_content.content_type}")
if encap_content.content:
print(f"Content Length: {len(encap_content.content)} bytes")
# Check certificates
if signed_data.certificates:
print(f"Number of certificates: {len(signed_data.certificates)}")
for cert in signed_data.certificates:
if hasattr(cert, 'subject'):
print(f" Certificate: {cert.subject.human_friendly}")
# Check signers
print(f"Number of signers: {len(signed_data.signer_infos)}")
for signer in signed_data.signer_infos:
print(f" Signer ID: {signer.sid}")
print(f" Digest Algorithm: {signer.digest_algorithm.algorithm}")
print(f" Signature Algorithm: {signer.signature_algorithm.algorithm}")
# Check signed attributes
if signer.signed_attrs:
for attr in signer.signed_attrs:
print(f" Signed Attr: {attr['type'].dotted}")from asn1crypto import pkcs12
# Load PKCS#12 file
with open('keystore.p12', 'rb') as f:
p12_data = f.read()
# Parse PKCS#12 structure
pfx = pkcs12.Pfx.load(p12_data)
print(f"Version: {pfx.version}")
# Check MAC data for integrity verification
if pfx.mac_data:
mac_data = pfx.mac_data
print(f"MAC Algorithm: {mac_data.mac.algorithm}")
print(f"MAC Iterations: {mac_data.iterations}")
print(f"MAC Salt: {mac_data.mac_salt.hex()}")
# Parse authenticated safe
auth_safe = pfx.auth_safe
if auth_safe.content_type == 'data':
# Content is DER-encoded SafeContents
safe_contents_der = auth_safe.content
safe_contents = pkcs12.SafeContents.load(safe_contents_der)
print(f"Number of safe bags: {len(safe_contents)}")
for bag in safe_contents:
bag_type = bag.bag_id
print(f"Bag Type: {bag_type}")
if bag_type == 'cert_bag':
cert_bag = bag.bag_value
print(f" Certificate Type: {cert_bag.cert_id}")
elif bag_type == 'pkcs8_shrouded_key_bag':
# Encrypted private key
encrypted_key = bag.bag_value
print(f" Encryption Algorithm: {encrypted_key.encryption_algorithm}")
# Check bag attributes
if bag.bag_attributes:
for attr in bag.bag_attributes:
print(f" Attribute: {attr.type}")from asn1crypto import tsp, algos
import hashlib
# Create a timestamp request
message_data = b"Document to be timestamped"
message_hash = hashlib.sha256(message_data).digest()
# Create message imprint
message_imprint = tsp.MessageImprint({
'hash_algorithm': algos.DigestAlgorithm('sha256'),
'hashed_message': message_hash
})
# Create timestamp request
ts_request = tsp.TimeStampReq({
'version': 1,
'message_imprint': message_imprint,
'cert_req': True, # Request TSA certificate
'nonce': 123456789 # Random nonce
})
# Serialize request for sending to TSA
request_der = ts_request.dump()
print(f"Timestamp request size: {len(request_der)} bytes")
# Parse timestamp response (assuming we received response_der from TSA)
ts_response = tsp.TimeStampResp.load(response_der)
# Check response status
status = ts_response.status
print(f"Status: {status.status}")
if status.status == 'granted':
# Extract timestamp token
ts_token = ts_response.time_stamp_token
if ts_token.content_type == 'signed_data':
signed_data = ts_token.content
# The signed data contains the TSTInfo in its encapsulated content
tst_info_der = signed_data.encap_content_info.content
tst_info = tsp.TSTInfo.load(tst_info_der)
print(f"TSA Policy: {tst_info.policy}")
print(f"Serial Number: {tst_info.serial_number}")
print(f"Generation Time: {tst_info.gen_time}")
print(f"Message Imprint Hash: {tst_info.message_imprint.hashed_message.hex()}")
if tst_info.accuracy:
accuracy = tst_info.accuracy
print(f"Accuracy: {accuracy.seconds}s {accuracy.millis}ms {accuracy.micros}μs")
else:
print(f"Timestamp request failed: {status.status}")
if status.failure_info:
print(f"Failure info: {status.failure_info}")from asn1crypto import cms, keys, x509, algos
# Assuming we have recipient certificates
recipient_certs = [x509.Certificate.load(cert_der) for cert_der in cert_ders]
# Create recipient infos for each certificate
recipient_infos = []
for cert in recipient_certs:
# Key transport recipient info (RSA)
recipient_info = cms.RecipientInfo({
'ktri': {
'version': 0,
'rid': {
'issuer_and_serial_number': {
'issuer': cert.issuer,
'serial_number': cert.serial_number
}
},
'key_encryption_algorithm': {
'algorithm': 'rsa'
},
'encrypted_key': b'\\x00' * 256 # Placeholder for encrypted key
}
})
recipient_infos.append(recipient_info)
# Create encrypted content info
encrypted_content_info = cms.EncryptedContentInfo({
'content_type': 'data',
'content_encryption_algorithm': {
'algorithm': 'aes256_cbc',
'parameters': b'\\x00' * 16 # IV placeholder
},
'encrypted_content': b'\\x00' * 32 # Placeholder for encrypted content
})
# Create enveloped data
enveloped_data = cms.EnvelopedData({
'version': 0,
'recipient_infos': recipient_infos,
'encrypted_content_info': encrypted_content_info
})
# Create content info
content_info = cms.ContentInfo({
'content_type': 'enveloped_data',
'content': enveloped_data
})
print(f"Created enveloped data for {len(recipient_infos)} recipients")These cryptographic message formats are used in: