"""A basic ASN.1 parser to parse private SSH keys.
This module is unstable.
Maintainer: U{Paul Swartz<mailto:z3p@twistedmatrix.com>}
"""
from Crypto.Util import number
def parse(data):
things = []
while data:
t = ord(data[0])
assert (t & 0xc0) == 0, 'not a universal value: 0x%02x' % t
l = ord(data[1])
assert data != 0x80, "shouldn't be an indefinite length"
if l & 0x80: ll = l & 0x7f
l = number.bytes_to_long(data[2:2+ll])
s = 2 + ll
else:
s = 2
body, data = data[s:s+l], data[s+l:]
t = t&(~0x20)
assert t in (SEQUENCE, INTEGER), 'bad type: 0x%02x' % t
if t == SEQUENCE:
things.append(parse(body))
elif t == INTEGER:
things.append(number.bytes_to_long(body))
if len(things) == 1:
return things[0]
return things
def pack(data):
ret = ''
for part in data:
if type(part) in (type(()), type([])):
partData = pack(part)
partType = SEQUENCE|0x20
elif type(part) in (type(1), type(1L)):
partData = number.long_to_bytes(part)
if ord(partData[0])&(0x80):
partData = '\x00' + partData
partType = INTEGER
else:
raise 'unknown type %s' % type(part)
ret += chr(partType)
if len(partData) > 127:
l = number.long_to_bytes(len(partData))
ret += chr(len(l)|0x80) + l
else:
ret += chr(len(partData))
ret += partData
return ret
INTEGER = 0x02
SEQUENCE = 0x10