EncryptedData Class

Overview

The EncryptedData class represents envelope-encrypted data with access control. It encapsulates envelope (hybrid) encryption of a given cleartext, comprising the ciphertext of the symmetric encryption, authenticated metadata, and a list of key locks that provide public-key encryption of the symmetric key.

Package: keychain.core.encrypted_data

from keychain.core.encrypted_data import EncryptedData

Class Definition

class EncryptedData(SerializableObject):
    """Represents envelope-encrypted data with access control."""

Constructor

def __init__(
    self,
    serialized_string: Optional[bytes] = None,
    serialization_format: SerializationFormat = SerializationFormat.PROTOBUF,
    serialized_data: Optional[SerializedData] = None,
    c_pointer: Optional[ctypes.c_void_p] = None,
) -> None

Initialize EncryptedData from various sources.

Parameters:

  • serialized_string (bytes, optional) - Serialized encrypted data bytes to deserialize

  • serialization_format (SerializationFormat) - Format of the serialized string (default: PROTOBUF)

  • serialized_data (SerializedData, optional) - SerializedData object to construct from

  • c_pointer (ctypes.c_void_p, optional) - Existing C pointer to wrap

Class Methods

from_copy()

@classmethod
def from_copy(cls, other: "EncryptedData") -> "EncryptedData"

Create a deep copy of encrypted data.

Parameters:

  • other (EncryptedData) - The encrypted data to copy

Returns: A new EncryptedData instance that is a deep copy

Properties

version

def version(self) -> Version

Get the data format version.

Returns: The version of the encrypted data format

cipher

def cipher(self) -> Cipher

Get the symmetric cipher used for encryption.

Returns: The cipher algorithm used

iv

def iv(self) -> str

Get the initialization vector used for encryption.

Returns: The IV as a hex-encoded string

ciphertext

def ciphertext(self) -> str

Get the encrypted data content.

Returns: The ciphertext as a hex-encoded string

ciphertext_hash

def ciphertext_hash(self) -> str

Get a hash of the ciphertext for integrity verification.

Returns: The ciphertext hash as a hex-encoded string

access_list

def access_list(self) -> List[KeyLock]

Get the list of key locks providing access to the encrypted data.

Returns: List of KeyLock objects that can decrypt the symmetric key

Methods

copy()

def copy(self) -> "EncryptedData"

Create a copy of this encrypted data.

Returns: A new EncryptedData instance that is a deep copy

attach_lock()

def attach_lock(self, key_lock: KeyLock) -> None

Attach a key lock to provide access for additional recipients.

Parameters:

  • key_lock (KeyLock) - The key lock to attach

serialize()

def serialize(self) -> bytes

Serialize the encrypted data to bytes.

Returns: The serialized encrypted data

data_type()

def data_type(self) -> DataType

Get the data type identifier.

Returns: DataType.ENCRYPTED_DATA

Comparison

eq()

def __eq__(self, other: object) -> bool

Check equality with another EncryptedData object.

Parameters:

  • other (object) - Object to compare with

Returns: True if the encrypted data objects are equal

Usage Examples

Basic Encryption

from keychain.core.encrypted_data import EncryptedData
from keychain.core.serialized_data import SerializedData
from keychain.constants import SerializationFormat

# Create data to encrypt
data = SerializedData("Confidential information")

# Encrypt data (typically done through Gateway)
# encrypted = gateway.encrypt(persona, data, recipients)

# Work with encrypted data
print(f"Cipher: {encrypted.cipher().name}")
print(f"Version: {encrypted.version().name}")
print(f"Access list size: {len(encrypted.access_list())}")

Working with Key Locks

# Get access information
access_locks = encrypted.access_list()
for i, lock in enumerate(access_locks):
    print(f"Key lock {i}: {lock}")

# Add additional recipient
additional_lock = gateway.create_key_lock_for(encrypted, new_recipient)
encrypted.attach_lock(additional_lock)

print(f"Updated access list size: {len(encrypted.access_list())}")

Serialization and Deserialization

# Serialize encrypted data
serialized_bytes = encrypted.serialize()

# Reconstruct from serialized data
reconstructed = EncryptedData(
    serialized_string=serialized_bytes,
    serialization_format=SerializationFormat.PROTOBUF
)

# Verify they're equal
assert encrypted == reconstructed

Copying

# Create a copy
copied_encrypted = encrypted.copy()

# Or use class method
another_copy = EncryptedData.from_copy(encrypted)

# Both copies are independent but equal
assert copied_encrypted == encrypted
assert another_copy == encrypted

Security Considerations

Access Control

  • Key locks control who can decrypt the data

  • Each recipient has their own key lock

  • Key locks can be added without re-encrypting the data

Integrity Protection

  • Ciphertext hash provides integrity verification

  • Authenticated encryption protects against tampering

  • Metadata is authenticated during encryption

Key Management

  • Symmetric keys are protected by public-key encryption

  • Multiple recipients can access the same data

  • Key rotation doesn’t require data re-encryption

See Also

  • KeyLock - Access control for encrypted data

  • SerializedData - Data serialization with metadata

  • Cipher - Symmetric encryption algorithms

  • Version - Data format versioning

  • Gateway - Encryption and decryption operations