or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

certificate-infrastructure.mdcore-types.mdcryptographic-algorithms.mdindex.mdkeys-and-certificates.mdmessage-formats.mdutilities.md
tile.json

utilities.mddocs/

Utilities and Helpers

PEM encoding/decoding, low-level parsing utilities, cross-platform compatibility helpers, and version information. These utilities provide essential support functions for working with ASN.1 data, handling different encodings, and ensuring cross-platform compatibility.

Capabilities

PEM Encoding and Decoding

Functions for converting between PEM (Privacy-Enhanced Mail) and DER (Distinguished Encoding Rules) formats.

def detect(byte_string):
    """
    Detect if data contains PEM-encoded blocks.
    
    Checks for the presence of BEGIN/END delimiters that indicate PEM format.
    
    Args:
        byte_string (bytes): Data to check for PEM encoding
        
    Returns:
        bool: True if PEM blocks are detected, False otherwise
    """

def armor(type_name, der_bytes, headers=None):
    """
    Convert DER-encoded bytes to PEM format.
    
    Wraps binary DER data in base64 encoding with appropriate delimiters.
    
    Args:
        type_name (str): PEM type name (e.g., "CERTIFICATE", "PRIVATE KEY")
        der_bytes (bytes): DER-encoded binary data
        headers (dict): Optional PEM headers as key-value pairs
        
    Returns:
        bytes: PEM-encoded data with delimiters and headers
    """

def unarmor(pem_bytes, multiple=False):
    """
    Convert PEM-encoded bytes to DER format.
    
    Extracts binary DER data from PEM format, removing delimiters and decoding base64.
    
    Args:
        pem_bytes (bytes): PEM-encoded data
        multiple (bool): Whether to expect multiple PEM blocks
        
    Returns:
        tuple: (type_name, headers, der_bytes) for single block
        list: List of (type_name, headers, der_bytes) tuples if multiple=True
    """

ASN.1 Parsing Utilities

Low-level functions for parsing and constructing ASN.1 data structures.

def parse(contents, strict=False):
    """
    Parse ASN.1 BER/DER-encoded data.
    
    Low-level parsing function that extracts ASN.1 tag, length, and content
    without constructing high-level objects.
    
    Args:
        contents (bytes): BER/DER-encoded ASN.1 data
        strict (bool): Whether to enforce strict DER parsing rules
        
    Returns:
        tuple: (class, method, tag, contents, trailer) where:
            - class: Tag class (0=universal, 1=application, 2=context, 3=private)
            - method: Construction method (0=primitive, 1=constructed)
            - tag: Tag number
            - contents: Content bytes
            - trailer: Remaining bytes after this value
    """

def peek(contents):
    """
    Look ahead to determine ASN.1 value information without parsing.
    
    Examines the tag and length fields to determine the size of the next
    ASN.1 value without fully parsing its contents.
    
    Args:
        contents (bytes): BER/DER-encoded ASN.1 data
        
    Returns:
        tuple: (class, method, tag, length) where:
            - class: Tag class
            - method: Construction method  
            - tag: Tag number
            - length: Content length in bytes
    """

def emit(class_, method, tag, contents):
    """
    Construct ASN.1 DER-encoded data from components.
    
    Low-level function for building ASN.1 encoded data from tag and content.
    
    Args:
        class_ (int): Tag class (0=universal, 1=application, 2=context, 3=private)
        method (int): Construction method (0=primitive, 1=constructed)
        tag (int): Tag number
        contents (bytes): Content data
        
    Returns:
        bytes: Complete DER-encoded ASN.1 data
    """

Integer and Byte Utilities

Functions for converting between integers and byte representations.

def int_to_bytes(value, signed=False, width=None):
    """
    Convert integer to bytes representation.
    
    Converts a Python integer to a bytes object with proper encoding
    for ASN.1 INTEGER types.
    
    Args:
        value (int): Integer value to convert
        signed (bool): Whether to use signed representation
        width (int): Optional fixed width in bytes
        
    Returns:
        bytes: Byte representation of the integer
    """

def int_from_bytes(value, signed=False):
    """
    Convert bytes to integer representation.
    
    Converts a bytes object to a Python integer, handling signed/unsigned
    interpretations as needed for ASN.1 INTEGER types.
    
    Args:
        value (bytes): Byte data to convert
        signed (bool): Whether to interpret as signed integer
        
    Returns:
        int: Integer value
    """

Network Address Utilities

Functions for handling IP addresses in certificates and other structures.

def inet_ntop(address_family, packed_ip):
    """
    Convert packed IP address to string representation.
    
    Similar to socket.inet_ntop but with cross-platform compatibility.
    
    Args:
        address_family (int): Address family (AF_INET or AF_INET6)
        packed_ip (bytes): Packed IP address bytes
        
    Returns:
        str: String representation of IP address
    """

def inet_pton(address_family, ip_string):
    """
    Convert string IP address to packed representation.
    
    Similar to socket.inet_pton but with cross-platform compatibility.
    
    Args:
        address_family (int): Address family (AF_INET or AF_INET6)
        ip_string (str): String IP address
        
    Returns:
        bytes: Packed IP address bytes
    """

URI and IRI Utilities

Functions for handling Uniform Resource Identifiers and Internationalized Resource Identifiers.

def uri_to_iri(uri_string):
    """
    Convert URI to IRI (Internationalized Resource Identifier).
    
    Converts percent-encoded URI to IRI with Unicode characters.
    
    Args:
        uri_string (str): URI string with percent encoding
        
    Returns:
        str: IRI string with Unicode characters
    """

def iri_to_uri(iri_string):
    """
    Convert IRI to URI with percent encoding.
    
    Converts IRI with Unicode characters to percent-encoded URI.
    
    Args:
        iri_string (str): IRI string with Unicode characters
        
    Returns:
        str: URI string with percent encoding
    """

Timezone and Date Utilities

Cross-platform compatibility classes for timezone and date handling.

class timezone:
    """
    Timezone class for Python 2 compatibility.
    
    Provides timezone functionality similar to Python 3's datetime.timezone
    for use in older Python versions.
    """
    
    def __init__(self, offset, name=None):
        """
        Initialize timezone with UTC offset.
        
        Args:
            offset (timedelta): UTC offset
            name (str): Optional timezone name
        """
    
    def utcoffset(self, dt):
        """Get UTC offset for this timezone."""
    
    def tzname(self, dt):
        """Get timezone name."""
    
    def dst(self, dt):
        """Get daylight saving time offset."""

def create_timezone(offset):
    """
    Create timezone object with given UTC offset.
    
    Factory function for creating timezone objects with cross-platform
    compatibility.
    
    Args:
        offset (int): UTC offset in minutes
        
    Returns:
        timezone: Timezone object
    """

class utc_with_dst(timezone):
    """
    UTC timezone class that properly handles DST queries.
    
    Special UTC timezone implementation that returns None for DST
    as required by the datetime module.
    """

class extended_date:
    """
    Date class supporting year 0 and negative years.
    
    Extends standard date functionality to handle years that
    standard datetime cannot represent.
    """
    
    def __init__(self, year, month, day):
        """
        Initialize extended date.
        
        Args:
            year (int): Year (can be 0 or negative)
            month (int): Month (1-12)
            day (int): Day (1-31)
        """
    
    @property
    def year(self):
        """Get the year."""
    
    @property
    def month(self):
        """Get the month."""
    
    @property
    def day(self):
        """Get the day."""

class extended_datetime:
    """
    Datetime class supporting year 0 and negative years.
    
    Extends standard datetime functionality to handle years that
    standard datetime cannot represent.
    """
    
    def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
        """
        Initialize extended datetime.
        
        Args:
            year (int): Year (can be 0 or negative)
            month (int): Month (1-12)
            day (int): Day (1-31)
            hour (int): Hour (0-23)
            minute (int): Minute (0-59)
            second (int): Second (0-59)
            microsecond (int): Microsecond (0-999999)
            tzinfo: Timezone info
        """

Compatibility Classes

Classes providing Python 2/3 compatibility for data structures.

class OrderedDict:
    """
    Ordered dictionary implementation for Python 2 compatibility.
    
    Provides OrderedDict functionality on Python versions that don't
    have it built-in. Maintains insertion order of dictionary items.
    """
    
    def __init__(self, items=None):
        """
        Initialize ordered dictionary.
        
        Args:
            items: Optional initial items (list of tuples or dict)
        """
    
    def __getitem__(self, key):
        """Get item by key."""
    
    def __setitem__(self, key, value):
        """Set item by key."""
    
    def __delitem__(self, key):
        """Delete item by key."""
    
    def __iter__(self):
        """Iterate over keys in insertion order."""
    
    def keys(self):
        """Get dictionary keys in order."""
    
    def values(self):
        """Get dictionary values in order."""
    
    def items(self):
        """Get dictionary items in order."""

Version Information

Version constants and information about the asn1crypto library.

__version__ = "1.5.1"
"""
String representation of the library version.

Used for version checking and compatibility verification.
"""

__version_info__ = (1, 5, 1)
"""
Tuple representation of the library version.

Allows for programmatic version comparison:
- Major version: API compatibility level
- Minor version: Feature additions
- Patch version: Bug fixes and minor improvements
"""

Usage Examples

PEM Encoding and Decoding

from asn1crypto import pem

# Check if data is PEM encoded
with open('certificate.pem', 'rb') as f:
    data = f.read()

if pem.detect(data):
    print("Data is PEM encoded")
    
    # Extract DER data from PEM
    type_name, headers, der_bytes = pem.unarmor(data)
    print(f"PEM type: {type_name}")
    print(f"DER size: {len(der_bytes)} bytes")
    
    if headers:
        print("PEM headers:")
        for key, value in headers.items():
            print(f"  {key}: {value}")
    
    # Convert back to PEM
    new_pem = pem.armor(type_name, der_bytes, headers)
    print("Successfully round-tripped PEM data")

else:
    print("Data is already in DER format")
    der_bytes = data
    
    # Convert DER to PEM
    pem_data = pem.armor('CERTIFICATE', der_bytes)
    print("Converted DER to PEM format")

Working with Multiple PEM Blocks

from asn1crypto import pem

# Handle file with multiple certificates
with open('ca_chain.pem', 'rb') as f:
    chain_data = f.read()

if pem.detect(chain_data):
    # Extract all PEM blocks
    pem_blocks = pem.unarmor(chain_data, multiple=True)
    
    print(f"Found {len(pem_blocks)} PEM blocks:")
    
    for i, (type_name, headers, der_bytes) in enumerate(pem_blocks):
        print(f"Block {i+1}: {type_name} ({len(der_bytes)} bytes)")
        
        # Parse each certificate
        if type_name == 'CERTIFICATE':
            from asn1crypto.x509 import Certificate
            cert = Certificate.load(der_bytes)
            print(f"  Subject: {cert.subject.human_friendly}")

Low-Level ASN.1 Parsing

from asn1crypto import parser

# Parse ASN.1 data at low level
der_data = b'\\x02\\x02\\x01\\x00'  # INTEGER 256

class_, method, tag, contents, trailer = parser.parse(der_data)

print(f"Class: {class_}")      # 0 (universal)
print(f"Method: {method}")     # 0 (primitive)
print(f"Tag: {tag}")          # 2 (INTEGER)
print(f"Contents: {contents.hex()}")  # 0100
print(f"Trailer: {trailer}")   # Empty

# Peek at data without full parsing
class_, method, tag, length = parser.peek(der_data)
print(f"Length: {length}")     # 2

# Construct ASN.1 data
new_der = parser.emit(0, 0, 2, b'\\x01\\x00')  # INTEGER 256
print(f"Constructed: {new_der.hex()}")  # 02020100

Integer and Byte Conversion

from asn1crypto import util

# Convert integers to bytes
big_number = 123456789012345678901234567890
byte_data = util.int_to_bytes(big_number)
print(f"Big number as bytes: {byte_data.hex()}")

# Convert back to integer
recovered = util.int_from_bytes(byte_data)
print(f"Recovered: {recovered}")
print(f"Match: {big_number == recovered}")

# Handle negative numbers
negative = -12345
signed_bytes = util.int_to_bytes(negative, signed=True)
print(f"Negative as bytes: {signed_bytes.hex()}")

recovered_negative = util.int_from_bytes(signed_bytes, signed=True)
print(f"Recovered negative: {recovered_negative}")

# Fixed width conversion
fixed_width = util.int_to_bytes(255, width=4)
print(f"Fixed width: {fixed_width.hex()}")  # 000000ff

Network Address Handling

from asn1crypto import util
import socket

# Convert IP addresses
ipv4_str = "192.168.1.1"
ipv4_packed = util.inet_pton(socket.AF_INET, ipv4_str)
print(f"IPv4 packed: {ipv4_packed.hex()}")

ipv4_back = util.inet_ntop(socket.AF_INET, ipv4_packed)
print(f"IPv4 string: {ipv4_back}")

# Handle IPv6
ipv6_str = "2001:db8::1"
ipv6_packed = util.inet_pton(socket.AF_INET6, ipv6_str)
print(f"IPv6 packed: {ipv6_packed.hex()}")

ipv6_back = util.inet_ntop(socket.AF_INET6, ipv6_packed)
print(f"IPv6 string: {ipv6_back}")

URI/IRI Conversion

from asn1crypto import util

# Convert URI to IRI
uri = "http://example.com/path%20with%20spaces?param=%C3%BC"
iri = util.uri_to_iri(uri)
print(f"IRI: {iri}")  # Unicode characters unescaped

# Convert back to URI
uri_back = util.iri_to_uri(iri)
print(f"URI: {uri_back}")  # Percent-encoded

Timezone and Date Handling

from asn1crypto import util
from datetime import timedelta

# Create timezone
eastern = util.create_timezone(-300)  # UTC-5 hours (300 minutes)
print(f"Timezone: {eastern}")

# Work with extended dates (supporting year 0)
old_date = util.extended_date(0, 1, 1)  # Year 0 (1 BC)
print(f"Old date: {old_date.year}-{old_date.month:02d}-{old_date.day:02d}")

# Extended datetime
old_datetime = util.extended_datetime(0, 1, 1, 12, 0, 0)
print(f"Old datetime: {old_datetime}")

# Use OrderedDict for Python 2 compatibility
ordered = util.OrderedDict([('first', 1), ('second', 2), ('third', 3)])
print(f"Ordered keys: {list(ordered.keys())}")

Version Checking

from asn1crypto import version

print(f"ASN1Crypto version: {version.__version__}")
print(f"Version info: {version.__version_info__}")

# Version comparison
if version.__version_info__ >= (1, 5, 0):
    print("Using modern version with full features")
else:
    print("Consider upgrading for latest features")

# Feature detection based on version
major, minor, patch = version.__version_info__
if major > 1 or (major == 1 and minor >= 4):
    print("Extended time type support available")

Cross-Platform Compatibility

The utilities module provides several compatibility features:

  • Python 2/3 Support: Works across Python versions 2.6-3.10
  • Platform Independence: Pure Python with no C extensions
  • Encoding Handling: Proper Unicode and byte string handling
  • Network Functions: Cross-platform IP address conversion
  • Date/Time: Extended date range support beyond standard datetime
  • Collections: OrderedDict for older Python versions

Performance Optimizations

  • Lazy Loading: Deferred parsing of complex structures
  • Byte Preservation: Original encoded data preserved when possible
  • Efficient Parsing: Minimal copying during parse operations
  • Caching: Computed values cached to avoid recalculation