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