mr. Holiday
mr. Holiday

Reputation: 1800

Object Identifier conversion ASN1

I'm trying to implement custom object identifier of ASN1 in Python, these are sample test cases.

asn1_objectidentifier([1,2])
asn1_objectidentifier([1,2,840])
asn1_objectidentifier([1,2,840,5,1000000])
asn1_objectidentifier([1,2,840,5,127,128,129])

What I couldn't manage to do is encoding value3 ... value n in base 128. This is my code so far

def asn1_objectidentifier(oid):
    first_octet = 40 * oid[0] + oid[1]
    rest = ""
    length = 1
    for v in range(2, len(oid)):
       if oid[v] < 127:
          rest += chr(oid[v])
          length += 1
       else:
          rem = oid[v] / 128
          first = (rem * 128) ^ 1
          second = (oid[v] - first) * 128 ^ 0
          rest += int_to_bytestring(first)
          rest += int_to_bytestring(second)
          length += 2 

    rest = chr(first_octet) + rest
    return chr(0x06) + chr(length) + rest

Upvotes: 0

Views: 1616

Answers (2)

martineau
martineau

Reputation: 123491

Here's a way to do base 128 encoding of non-negative integers:

def base128_encode(n): # int/long to byte string
    if n > 0:
        arr = []
        while n:
            n, rem = divmod(n, 128)
            arr.append(chr(rem))
        return ''.join(reversed(arr))
    elif n == 0:
        return '\x00'
    else:
        raise ValueError

print [ord(c) for c in base128_encode(840)]  # --> [6, 72]

Upvotes: 2

Norman Gray
Norman Gray

Reputation: 12514

The excellent article A Layman's Guide to a Subset of ASN.1, BER, and DER describes this in some detail, and – most valuably – gives a number of good test-cases and edge-cases.

By the way: That document doesn't seem to have a canonical home on the web. The above is a link to the CiteseerX reference information; other PDFs exist; and HTML versions.

Upvotes: 2

Related Questions