Python-ASN1
Python-ASN1 is a straightforward library for encoding and decoding ASN.1 data, compatible with Python 2.7+ and 3.5+. It supports both BER (Basic Encoding Rules) for parsing and DER (Distinguished Encoding Rules) for parsing and generation, including indefinite lengths. The library is written entirely in Python and supports most common ASN.1 types, including the REAL type. The latest version is 3.2.0, with a regular release cadence addressing new Python versions and API enhancements.
Warnings
- breaking In version 3.0.0, the `Encoder` incorrectly defaulted to CER encoding, diverging from previous versions which used DER. This was a significant behavioral change for users who did not explicitly specify the encoding method.
- gotcha Due to ASN.1 having more distinct data types than Python, a single Python type might map to multiple ASN.1 types. The library uses the most frequently expected ASN.1 type by default. If a different ASN.1 type (e.g., 'IA5String' vs. 'UTF8String' for a Python string) is intended, it must be explicitly specified during encoding using `encoder.write(value, asn1.Numbers.DesiredType)`.
- gotcha Version 3.2.0 introduced a new, more Pythonic context manager API for `Encoder` and `Decoder` (e.g., `with asn1.Encoder() as encoder:`). While the older `encoder.start()` / `encoder.output()` methods remain backward-compatible, the context manager approach is recommended for cleaner code and proper resource handling, especially for constructed types and streams.
Install
-
pip install asn1
Imports
- Encoder
from asn1 import Encoder
- Decoder
from asn1 import Decoder
- Numbers
from asn1 import Numbers
Quickstart
import asn1
# 1. Encoding an ObjectIdentifier and a Sequence
with asn1.Encoder() as encoder:
# Encode an ObjectIdentifier (e.g., "1.2.3")
encoder.write('1.2.3', asn1.Numbers.ObjectIdentifier)
# Encode a Sequence containing an Integer and a UTF8String
with encoder.enter(asn1.Numbers.Sequence) as sequence_encoder:
sequence_encoder.write(123, asn1.Numbers.Integer)
sequence_encoder.write('hello', asn1.Numbers.UTF8String)
encoded_bytes = encoder.output()
print(f"Encoded bytes: {encoded_bytes.hex()}")
# 2. Decoding the ASN.1 data
decoded_elements = []
with asn1.Decoder(stream=encoded_bytes) as decoder:
# Decode the first element (ObjectIdentifier)
tag, value = decoder.read()
decoded_elements.append(f"Tag: {tag.nr} (ObjectIdentifier), Class: {tag.cls}, Value: {value}")
# Decode the next element, which is the Sequence
tag, value = decoder.read()
if tag.nr == asn1.Numbers.Sequence:
decoded_elements.append(f"Tag: {tag.nr} (Sequence), Class: {tag.cls}")
# Enter the sequence to decode its elements
with decoder.enter() as sequence_decoder:
while not sequence_decoder.eof():
tag, value = sequence_decoder.read()
decoded_elements.append(f" -> Tag: {tag.nr}, Class: {tag.cls}, Value: {value}")
print("\nDecoded data:")
for item in decoded_elements:
print(item)