asn1.py   [plain text]


# -*- test-case-name: twisted.test.test_asn1 -*-

from record import Record, Integer

universalTypeTags = {
    'INTEGER': 2,
    'BIT STRING': 3, # string of ones and zeros
    'NULL': 5,
    'OCTET STRING': 4, # string of 8-bit values
    'OBJECT IDENTIFIER': 6, # sequence of integer components
                            # identifying an object
    'SEQUENCE': 16,
    'SET': 17,
    'PrintableString': 19, # string of printable characters
    'T61String': 20, # string of T.61 characters
    'IA5String': 22, # string of ASCII characters
    'UTCTime': 23}


class Identifier(Record):
    UNIVERSAL = 0
    APPLICATION = 1
    CONTEXT_SPECIFIC = 2
    PRIVATE = 3

    def __decode__(self):
        yield ('tagNumber', Integer(5))
        yield ('primitiveTag', Integer(1))
        yield ('classType', Integer(2))

        if self.tagNumber == 63:
            # High-tag-number form
            byteArray = [255]
            while byteArray[-1] > 127:
                yield byteArray.append, Integer(8)
            accum = 0
            i = iter(byteArray)
            i.next()
            for byte in i:
                accum <<= 8
                accum |= byte
            self.tagNumber = accum

    def __encode__(self):
        raise NotImplementedError

class Length(Record):
    def __decode__(self):
        yield "payload", Integer(7)
        yield "form", Integer(1)

        if self.form == 0:
            self.length = self.payload
        else:
            yield "length", Integer(self.payload * 8)

    def __encode__(self):
        raise NotImplementedError

class Any(Record):

    baseFormat = [('identifier', Identifier),
                  ('length', Length)]

    def __decode__(self):
        for f in self.baseFormat:
            yield f

        # Do something with self.length here

    def __encode__(self):
        for f in self.baseFormat:
            yield f

        # Do, uh, more stuff