ASN.1 Object Model

Each generated Python class representing an ASN.1 type acts as a wrapper around an internal native (C-extension) representation. To provide a natural Python interface, accessing or assigning the value of an ASN.1 object involves conversion between the native format and native Python types.

Reading the Value

When you access the value property of an ASN.1 object, the underlying native value is converted on-demand to the corresponding Python object, for example:

  • ASN.1 INTEGER converts to a Python int

  • ASN.1 BOOLEAN converts to a Python bool

  • ASN.1 OCTET STRING converts to Python bytes

  • ASN.1 named BIT STRING converts to an enum.IntFlag or bitarray.bitarray, depending on the type

This conversion produces a new Python object representing the current state.

Writing to the Value

Assigning to the value property performs the inverse conversion: the provided Python object is converted back into the native ASN.1 internal format.

Important Note

Modifying the Python object obtained from value does not affect the underlying ASN.1 object unless the modified object is explicitly assigned back to the value property.

For example:

# Retrieve a Python integer representing the ASN.1 INTEGER value
py_int = asn1_integer.value

# Modifying py_int has no effect on asn1_integer internally
py_int += 1
assert asn1_integer.value != py_int

# To update the ASN.1 object, assign the modified value explicitly
asn1_integer.value = py_int

Important

When an attribute of an ASN.1 object is itself represented by another generated class (e.g., a nested SEQUENCE, SET, or a user-defined type wrapping a basic ASN.1 type), accessing that attribute does not return a copy of the value, but a direct reference to the contained object.

This means that modifying the returned object will also modify the parent. Unlike attributes that map directly to Python native types (int, str, bool, etc.) — which require explicitly reassigning the attribute to update the encoded value — changes made to generated-class attributes are immediately reflected in the parent object’s internal state.

Example:

person = Person()
person.name = NameType(given="John", family="Smith")

# Access the nested NameType object
n = person.name

# Modifying the nested object updates the parent directly
n.given = "Jonathan"

assert person.name.given == "Jonathan"  # True

This behavior is intentional and allows in-place updates of complex ASN.1 structures without requiring reassignment of the entire sub-object.