1#
2#   Encodings and Formats for Elliptic Curve Cryptography
3#
4
5import StringIO
6
7# Big-Endian Encoding
8
9def enc_long(n):
10    '''Encodes arbitrarily large number n to a sequence of bytes.
11    Big endian byte order is used.'''
12    s = ""
13    while n > 0:
14        s = chr(n & 0xFF) + s
15        n >>= 8
16    return s
17
18def enc_int(n):
19    '''Encodes an integer n to a 4-byte string.
20    Big endian byte order is used.'''
21    return chr((n >> 24) & 0xFF) + chr((n >> 16) & 0xFF) + \
22           chr((n >>  8) & 0xFF) + chr( n        & 0xFF)
23
24def enc_fixed_long(n, length):
25    return enc_long(n)[:length].rjust(length, '\x00')
26
27def dec_long(s):
28    '''Decodes s to its numeric representation.
29    Big endian byte order is used.'''
30    n = 0
31    for c in s:
32        n = (n << 8) | ord(c)
33    return n
34
35# dec_int not necessary,
36# dec_long does the same when provided with 4 bytes input.
37
38# Chunks
39
40def enc_chunks(*args):
41    '''Chain given string args or sub-chunks to a single chunk'''
42    return ''.join([enc_int(len(a)) + a for a in args])
43
44def dec_chunks(s):
45    '''Split a chunk into strings or sub-chunks'''
46    i = 0
47    result = []
48    while i < len(s):
49        size = dec_long(s[i : i + 4])
50        i += 4
51        result.append(s[i : i + size])
52        i += size
53    return result
54
55# Point and signature data
56
57def enc_point(p):
58    '''Encode a point p = (x, y)'''
59    x, y = p
60    sx = enc_long(x)
61    sy = enc_long(y)
62    diff = len(sx) - len(sy)
63    if diff > 0:
64        sy = '\x00' * diff + sy
65    elif diff < 0:
66        sx = '\x00' * -diff + sx
67    return sx + sy
68
69def dec_point(s):
70    '''Decode an even length string s to a point(x, y)'''
71    d = len(s) / 2
72    return (dec_long(s[:d]), dec_long(s[d:]))
73
74
75class Encoder:
76
77    def __init__(self):
78        self._io = StringIO.StringIO()
79
80    def int(self, n, size = 4):
81        self._io.write(enc_fixed_long(n, size))
82        return self
83
84    def long(self, n, pre = 2):
85        lstr = enc_long(n)
86        self._io.write(enc_fixed_long(len(lstr), pre) + lstr)
87        return self
88
89    def str(self, s, pre = 2):
90        self._io.write(enc_fixed_long(len(s), pre) + s)
91        return self
92
93    def point(self, p, pre = 2):
94        lstr = enc_point(p)
95        self._io.write(enc_fixed_long(len(lstr), pre) + lstr)
96        return self
97
98    def chunk(self, enc, pre = 2):
99        lstr = enc.out()
100        self._io.write(enc_fixed_long(len(lstr), pre) + lstr)
101        return self
102
103    def out(self):
104        return self._io.getvalue()
105
106class Decoder:
107
108    def __init__(self, data, offset = 0):
109        self._io = StringIO.StringIO(data)
110        self._io.seek(offset)
111        self._res = []
112        self._limit = None
113        self._parent = None
114
115    def _ret(self):
116##        if self._parent and self._io.tell() >= self._limit:
117##            return self.exit()
118##        else:
119##            return self
120        return self
121
122    def int(self, size = 4):
123        self._res.append(dec_long(self._io.read(size)))
124        return self._ret()
125
126
127    def long(self, pre = 2):
128        llen = dec_long(self._io.read(pre))
129        self._res.append(dec_long(self._io.read(llen)))
130        return self._ret()
131
132    def str(self, pre = 2):
133        llen = dec_long(self._io.read(pre))
134        self._res.append(self._io.read(llen))
135        return self._ret()
136
137    def point(self, pre = 2):
138        llen = dec_long(self._io.read(pre))
139        self._res.append(dec_point(self._io.read(llen)))
140        return self._ret()
141
142    def enter(self, pre = 2):
143        llen = dec_long(self._io.read(pre))
144        subcoder = Decoder("")
145        subcoder._io = self._io
146        subcoder._parent = self
147        subcoder._limit = self._io.tell() + llen
148        return subcoder
149
150    def chunk(self, pre = 2):
151        llen = dec_long(self._io.read(pre))
152        self._res.append(Decoder(self._io.read(llen)))
153        return self._ret()
154
155    def exit(self):
156        if self._parent:
157            self._parent._io.seek(self._limit)
158            self._parent._res.append(self._res)
159            return self._parent
160        else:
161            raise RuntimeError, "Cannont exit top level Decoder"
162
163    def continues(self):
164        return (not self._limit) or (self._io.tell() < self._limit)
165
166    def out(self, exit_all = False):
167        if exit_all and self._parent:
168            return self.exit().out()
169        else:
170            r = self._res
171            self._res = []
172            return r
173
174    def only(self):
175        if self._res:
176            return self._res.pop(0)
177        else:
178            return RuntimeError, "Only what? (Empty decoder stack)"
179