chiark / gitweb /
Extract Subversion ignore data.
[catacomb-python] / catacomb / __init__.py
1 # -*-python-*-
2 #
3 # $Id$
4 #
5 # Setup for Catacomb/Python bindings
6 #
7 # (c) 2004 Straylight/Edgeware
8 #
9
10 #----- Licensing notice -----------------------------------------------------
11 #
12 # This file is part of the Python interface to Catacomb.
13 #
14 # Catacomb/Python is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
18
19 # Catacomb/Python is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23
24 # You should have received a copy of the GNU General Public License
25 # along with Catacomb/Python; if not, write to the Free Software Foundation,
26 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28 import _base
29 import types as _types
30 from binascii import hexlify as _hexify, unhexlify as _unhexify
31 from sys import argv as _argv
32
33 _base._ego(_argv[0])
34
35 def _init():
36   d = globals()
37   b = _base.__dict__;
38   for i in b:
39     if i[0] != '_':
40       d[i] = b[i];
41   for i in ['MP', 'GF', 'Field',
42             'ECPt', 'ECPtCurve', 'ECCurve', 'ECInfo',
43             'DHInfo', 'BinDHInfo', 'RSAPriv', 'PrimeFilter', 'RabinMiller',
44             'Group', 'GE',
45             'KeyData']:
46     c = d[i]
47     pre = '_' + i + '_'
48     plen = len(pre)
49     for j in b:
50       if j[:plen] == pre:
51         setattr(c, j[plen:], classmethod(b[j]))
52   for i in [gcciphers, gchashes, gcmacs]:
53     for j in i:
54       c = i[j]
55       d[c.name.replace('-', '_')] = c
56 _init()
57
58 def _augment(c, cc):
59   for i in cc.__dict__:
60     a = cc.__dict__[i]
61     if type(a) is _types.MethodType:
62       a = a.im_func
63     elif type(a) not in (_types.FunctionType, staticmethod, classmethod):
64       continue
65     setattr(c, i, a)
66
67 class _tmp:
68   def fromhex(x):
69     return ByteString(_unhexify(x))
70   fromhex = staticmethod(fromhex)
71   def __hex__(me):
72     return _hexify(me)
73   def __repr__(me):
74     return 'bytes(%r)' % hex(me)
75 _augment(ByteString, _tmp)
76 bytes = ByteString.fromhex
77
78 class _tmp:
79   def negp(x): return x < 0
80   def posp(x): return x > 0
81   def zerop(x): return x == 0
82   def oddp(x): return x.testbit(0)
83   def evenp(x): return not x.testbit(0)
84   def mont(x): return MPMont(x)
85   def barrett(x): return MPBarrett(x)
86   def reduce(x): return MPReduce(x)
87   def factorial(x):
88     'factorial(X) -> X!'
89     if x < 0: raise ValueError, 'factorial argument must be > 0'
90     return MP.product(xrange(1, x + 1))
91   factorial = staticmethod(factorial)
92 _augment(MP, _tmp)
93
94 def _checkend(r):
95   x, rest = r
96   if rest != '':
97     raise SyntaxError, 'junk at end of string'
98   return x
99
100 class _tmp:
101   def reduce(x): return GReduce(x)
102 _augment(GF, _tmp)
103
104 class _tmp:
105   def fromstring(str): return _checkend(Field.parse(str))
106   fromstring = staticmethod(fromstring)
107 _augment(Field, _tmp)
108
109 class _tmp:
110   def __repr__(me): return '%s(%sL)' % (type(me).__name__, me.p)
111   def ec(me, a, b): return ECPrimeProjCurve(me, a, b)
112 _augment(PrimeField, _tmp)
113
114 class _tmp:
115   def __repr__(me): return '%s(%sL)' % (type(me).__name__, hex(me.p))
116   def ec(me, a, b): return ECBinProjCurve(me, a, b)
117 _augment(BinField, _tmp)
118
119 class _tmp:
120   def __str__(me): return str(me.value)
121   def __repr__(me): return '%s(%s)' % (repr(me.field), repr(me.value))
122 _augment(FE, _tmp)
123
124 class _groupmap (object):
125   def __init__(me, map, nth):
126     me.map = map
127     me.nth = nth
128     me.i = [None] * (max(map.values()) + 1)
129   def __repr__(me):
130     return '{%s}' % ', '.join(['%r: %r' % (k, me[k]) for k in me])
131   def __contains__(me, k):
132     return k in me.map
133   def __getitem__(me, k):
134     i = me.map[k]
135     if me.i[i] is None:
136       me.i[i] = me.nth(i)
137     return me.i[i]
138   def __setitem__(me, k, v):
139     raise TypeError, "immutable object"
140   def __iter__(me):
141     return iter(me.map)
142   def keys(me):
143     return [k for k in me]
144   def values(me):
145     return [me[k] for k in me]
146 eccurves = _groupmap(_base._eccurves, ECInfo._curven)
147 primegroups = _groupmap(_base._pgroups, DHInfo._groupn)
148 bingroups = _groupmap(_base._bingroups, BinDHInfo._groupn)
149
150 class _tmp:
151   def __repr__(me):
152     return '%s(%r, %s, %s)' % (type(me).__name__, me.field, me.a, me.b)
153   def frombuf(me, s):
154     return ecpt.frombuf(me, s)
155   def fromraw(me, s):
156     return ecpt.fromraw(me, s)
157   def pt(me, *args):
158     return ECPt(me, *args)
159 _augment(ECCurve, _tmp)
160
161 class _tmp:
162   def __repr__(me):
163     if not me: return 'ECPt()'
164     return 'ECPt(%s, %s)' % (me.ix, me.iy)
165   def __str__(me):
166     if not me: return 'inf'
167     return '(%s, %s)' % (me.ix, me.iy)
168 _augment(ECPt, _tmp)
169
170 class _tmp:
171   def __repr__(me):
172     return 'ECInfo(curve = %r, G = %r, r = %s, h = %s)' % \
173            (me.curve, me.G, me.r, me.h)
174   def group(me):
175     return ECGroup(me)
176 _augment(ECInfo, _tmp)
177
178 class _tmp:
179   def __repr__(me):
180     if not me: return '%r()' % (me.curve)
181     return '%r(%s, %s)' % (me.curve, me.x, me.y)
182   def __str__(me):
183     if not me: return 'inf'
184     return '(%s, %s)' % (me.x, me.y)
185 _augment(ECPtCurve, _tmp)
186
187 class _tmp:
188   def __repr__(me): return 'KeySZAny(%d)' % me.default
189   def check(me, sz): return True
190   def best(me, sz): return sz
191 _augment(KeySZAny, _tmp)
192
193 class _tmp:
194   def __repr__(me):
195     return 'KeySZRange(%d, %d, %d, %d)' % \
196            (me.default, me.min, me.max, me.mod)
197   def check(me, sz): return me.min <= sz <= me.max and sz % me.mod == 0
198   def best(me, sz):
199     if sz < me.min: raise ValueError, 'key too small'
200     elif sz > me.max: return me.max
201     else: return sz - (sz % me.mod)
202 _augment(KeySZRange, _tmp)
203
204 class _tmp:
205   def __repr__(me): return 'KeySZSet(%d, %s)' % (me.default, me.set)
206   def check(me, sz): return sz in me.set
207   def best(me, sz):
208     found = -1
209     for i in me.set:
210       if found < i <= sz: found = i
211     if found < 0: raise ValueError, 'key too small'
212     return found
213 _augment(KeySZSet, _tmp)
214
215 class _tmp:
216   def __repr__(me):
217     return '%s(p = %s, r = %s, g = %s)' % \
218            (type(me).__name__, me.p, me.r, me.g)
219 _augment(FGInfo, _tmp)
220
221 class _tmp:
222   def group(me): return PrimeGroup(me)
223 _augment(DHInfo, _tmp)
224
225 class _tmp:
226   def group(me): return BinGroup(me)
227 _augment(BinDHInfo, _tmp)
228
229 class _tmp:
230   def __repr__(me):
231     return '%s(%r)' % (type(me).__name__, me.info)
232 _augment(Group, _tmp)
233
234 class _tmp:
235   def __repr__(me):
236     return '%r(%r)' % (me.group, str(me))
237 _augment(GE, _tmp)
238
239 class PKCS1Crypt(object):
240   def __init__(me, ep = '', rng = rand):
241     me.ep = ep
242     me.rng = rng
243   def encode(me, msg, nbits):
244     return _base._p1crypt_encode(msg, nbits, me.ep, me.rng)
245   def decode(me, ct, nbits):
246     return _base._p1crypt_decode(ct, nbits, me.ep, me.rng)
247
248 class PKCS1Sig(object):
249   def __init__(me, ep = '', rng = rand):
250     me.ep = ep
251     me.rng = rng
252   def encode(me, msg, nbits):
253     return _base._p1sig_encode(msg, nbits, me.ep, me.rng)
254   def decode(me, msg, sig, nbits):
255     return _base._p1sig_decode(msg, sig, nbits, me.ep, me.rng)
256
257 class OAEP(object):
258   def __init__(me, mgf = sha_mgf, hash = sha, ep = '', rng = rand):
259     me.mgf = mgf
260     me.hash = hash
261     me.ep = ep
262     me.rng = rng
263   def encode(me, msg, nbits):
264     return _base._oaep_encode(msg, nbits, me.mgf, me.hash, me.ep, me.rng)
265   def decode(me, ct, nbits):
266     return _base._oaep_decode(ct, nbits, me.mgf, me.hash, me.ep, me.rng)
267
268 class PSS(object):
269   def __init__(me, mgf = sha_mgf, hash = sha, saltsz = None, rng = rand):
270     me.mgf = mgf
271     me.hash = hash
272     if saltsz is None:
273       saltsz = hash.hashsz
274     me.saltsz = saltsz
275     me.rng = rng
276   def encode(me, msg, nbits):
277     return _base._pss_encode(msg, nbits, me.mgf, me.hash, me.saltsz, me.rng)
278   def decode(me, msg, sig, nbits):
279     return _base._pss_decode(msg, sig, nbits,
280                              me.mgf, me.hash, me.saltsz, me.rng)
281
282 class _tmp:
283   def encrypt(me, msg, enc):
284     return me.pubop(enc.encode(msg, me.n.nbits))
285   def verify(me, msg, sig, enc):
286     if msg is None: return enc.decode(msg, me.pubop(sig), me.n.nbits)
287     try:
288       x = enc.decode(msg, me.pubop(sig), me.n.nbits)
289       return x is None or x == msg
290     except ValueError:
291       return False      
292 _augment(RSAPub, _tmp)
293
294 class _tmp:
295   def decrypt(me, ct, enc): return enc.decode(me.privop(ct), me.n.nbits)
296   def sign(me, msg, enc): return me.privop(enc.encode(msg, me.n.nbits))
297 _augment(RSAPriv, _tmp)
298
299
300 class SophieGermainStepJump (object):
301   def pg_begin(me, ev):
302     me.lf = PrimeFilter(ev.x)
303     me.hf = me.lf.muladd(2, 1)
304     return me.cont(ev)
305   def pg_try(me, ev):
306     me.step()
307     return me.cont(ev)
308   def cont(me, ev):
309     while me.lf.status == PGEN_FAIL or me.hf.status == PGEN_FAIL:
310       me.step()
311     if me.lf.status == PGEN_ABORT or me.hf.status == PGEN_ABORT:
312       return PGEN_ABORT
313     ev.x = me.lf.x
314     if me.lf.status == PGEN_DONE and me.hf.status == PGEN_DONE:
315       return PGEN_DONE
316     return PGEN_TRY
317   def pg_done(me, ev):
318     del me.lf
319     del me.hf
320
321 class SophieGermainStepper (SophieGermainStepJump):
322   def __init__(me, step):
323     me.lstep = step;
324     me.hstep = 2 * step
325   def step(me):
326     me.lf.step(me.lstep)
327     me.hf.step(me.hstep)
328
329 class SophieGermainJumper (SophieGermainStepJump):
330   def __init__(me, jump):
331     me.ljump = PrimeFilter(jump);
332     me.hjump = me.ljump.muladd(2, 0)
333   def step(me):
334     me.lf.jump(me.ljump)
335     me.hf.jump(me.hjump)
336   def pg_done(me, ev):
337     del me.ljump
338     del me.hjump
339     SophieGermainStepJump.pg_done(me, ev)
340
341 class SophieGermainTester (object):
342   def __init__(me):
343     pass
344   def pg_begin(me, ev):
345     me.lr = RabinMiller(ev.x)
346     me.hr = RabinMiller(2 * ev.x + 1)
347   def pg_try(me, ev):
348     lst = me.lr.test(ev.rng.range(me.lr.x))
349     if lst != PGEN_PASS and lst != PGEN_DONE:
350       return lst
351     rst = me.hr.test(ev.rng.range(me.hr.x))
352     if rst != PGEN_PASS and rst != PGEN_DONE:
353       return rst
354     if lst == PGEN_DONE and rst == PGEN_DONE:
355       return PGEN_DONE
356     return PGEN_PASS
357   def pg_done(me, ev):
358     del me.lr
359     del me.hr
360
361 class PrimeGenEventHandler (object):
362   def pg_begin(me, ev):
363     return me.pg_try(ev)
364   def pg_done(me, ev):
365     return PGEN_DONE
366   def pg_abort(me, ev):
367     return PGEN_TRY
368   def pg_fail(me, ev):
369     return PGEN_TRY
370   def pg_pass(me, ev):
371     return PGEN_TRY
372
373 class PrimitiveStepper (PrimeGenEventHandler):
374   def __init__(me):
375     pass
376   def pg_try(me, ev):
377     ev.x = me.i.next()
378     return PGEN_TRY
379   def pg_begin(me, ev):
380     me.i = iter(smallprimes)
381     return me.pg_try(ev)
382
383 class PrimitiveTester (PrimeGenEventHandler):
384   def __init__(me, mod, hh = [], exp = None):
385     me.mod = MPMont(mod)
386     me.exp = exp
387     me.hh = hh
388   def pg_try(me, ev):
389     x = ev.x
390     if me.exp is not None:
391       x = me.mod.exp(x, me.exp)
392       if x == 1: return PGEN_FAIL
393     for h in me.hh:
394       if me.mod.exp(x, h) == 1: return PGEN_FAIL
395     ev.x = x
396     return PGEN_DONE
397
398 class SimulStepper (PrimeGenEventHandler):
399   def __init__(me, mul = 2, add = 1, step = 2):
400     me.step = step
401     me.mul = mul
402     me.add = add
403   def _stepfn(me, step):
404     if step <= 0:
405       raise ValueError, 'step must be positive'
406     if step <= MPW_MAX:
407       return lambda f: f.step(step)
408     j = PrimeFilter(step)
409     return lambda f: f.jump(j)
410   def pg_begin(me, ev):
411     x = ev.x
412     me.lf = PrimeFilter(x)
413     me.hf = PrimeFilter(x * me.mul + me.add)
414     me.lstep = me._stepfn(me.step)
415     me.hstep = me._stepfn(me.step * me.mul)
416     SimulStepper._cont(me, ev)
417   def pg_try(me, ev):
418     me._step()
419     me._cont(ev)
420   def _step(me):
421     me.lstep(me.lf)
422     me.hstep(me.hf)
423   def _cont(me, ev):
424     while me.lf.status == PGEN_FAIL or me.hf.status == PGEN_FAIL:
425       me._step()
426     if me.lf.status == PGEN_ABORT or me.hf.status == PGEN_ABORT:
427       return PGEN_ABORT
428     ev.x = me.lf.x
429     if me.lf.status == PGEN_DONE and me.hf.status == PGEN_DONE:
430       return PGEN_DONE
431     return PGEN_TRY
432   def pg_done(me, ev):
433     del me.lf
434     del me.hf
435     del me.lstep
436     del me.hstep
437
438 class SimulTester (PrimeGenEventHandler):
439   def __init__(me, mul = 2, add = 1):
440     me.mul = mul
441     me.add = add
442   def pg_begin(me, ev):
443     x = ev.x
444     me.lr = RabinMiller(x)
445     me.hr = RabinMiller(x * me.mul + me.add)
446   def pg_try(me, ev):
447     lst = me.lr.test(ev.rng.range(me.lr.x))
448     if lst != PGEN_PASS and lst != PGEN_DONE:
449       return lst
450     rst = me.hr.test(ev.rng.range(me.hr.x))
451     if rst != PGEN_PASS and rst != PGEN_DONE:
452       return rst
453     if lst == PGEN_DONE and rst == PGEN_DONE:
454       return PGEN_DONE
455     return PGEN_PASS
456   def pg_done(me, ev):
457     del me.lr
458     del me.hr
459
460 def sgprime(start, step = 2, name = 'p', event = pgen_nullev, nsteps = 0):
461   start = MP(start)
462   return pgen(start, name, SimulStepper(step = step), SimulTester(), event,
463               nsteps, RabinMiller.iters(start.nbits))
464
465 def findprimitive(mod, hh = [], exp = None, name = 'g', event = pgen_nullev):
466   return pgen(0, name, PrimitiveStepper(), PrimitiveTester(mod, hh, exp),
467               event, 0, 1)
468
469 def kcdsaprime(pbits, qbits, rng = rand,
470                event = pgen_nullev, name = 'p', nsteps = 0):
471   hbits = pbits - qbits
472   h = pgen(rng.mp(hbits, 1), name + ' [h]',
473            PrimeGenStepper(2), PrimeGenTester(),
474            event, nsteps, RabinMiller.iters(hbits))
475   q = pgen(rng.mp(qbits, 1), name, SimulStepper(2 * h, 1, 2),
476            SimulTester(2 * h, 1), event, nsteps, RabinMiller.iters(qbits))
477   p = 2 * q * h + 1
478   return p, q, h
479
480 import pwsafe
481
482 #----- That's all, folks ----------------------------------------------------