X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/4abb54de656f0d5c1b35de940fe75e7e3159dee4..f845cee4f9afa3b1591a3bef4787bb381acd6473:/catacomb/__init__.py diff --git a/catacomb/__init__.py b/catacomb/__init__.py index 8038815..c810c42 100644 --- a/catacomb/__init__.py +++ b/catacomb/__init__.py @@ -27,7 +27,8 @@ from __future__ import with_statement from binascii import hexlify as _hexify, unhexlify as _unhexify from contextlib import contextmanager as _ctxmgr -import DLFCN as _dlfcn +try: import DLFCN as _dlfcn +except ImportError: _dlfcn = None import os as _os from struct import pack as _pack import sys as _sys @@ -67,6 +68,15 @@ del _dlflags, _odlflags ## For the benefit of the default keyreporter, we need the program name. _base._ego(_sys.argv[0]) +## Register our module. +_base._set_home_module(_sys.modules[__name__]) +def default_lostexchook(why, ty, val, tb): + """`catacomb.lostexchook(WHY, TY, VAL, TB)' reports lost exceptions.""" + _sys.stderr.write("\n\n!!! LOST EXCEPTION: %s\n" % why) + _sys.excepthook(ty, val, tb) + _sys.stderr.write("\n") +lostexchook = default_lostexchook + ## How to fix a name back into the right identifier. Alas, the rules are not ## consistent. def _fixname(name): @@ -75,7 +85,7 @@ def _fixname(name): name = name.replace('-', '_') ## But slashes might become underscores or just vanish. - if name.startswith('salsa20'): name = name.translate(None, '/') + if name.startswith('salsa20'): name = name.replace('/', '') else: name = name.replace('/', '_') ## Done. @@ -89,19 +99,6 @@ def _init(): for i in b: if i[0] != '_': d[i] = b[i]; - for i in ['ByteString', - 'MP', 'GF', 'Field', - 'ECPt', 'ECPtCurve', 'ECCurve', 'ECInfo', - 'DHInfo', 'BinDHInfo', 'RSAPriv', 'BBSPriv', - 'PrimeFilter', 'RabinMiller', - 'Group', 'GE', - 'KeySZ', 'KeyData']: - c = d[i] - pre = '_' + i + '_' - plen = len(pre) - for j in b: - if j[:plen] == pre: - setattr(c, j[plen:], classmethod(b[j])) for i in [gcciphers, gcaeads, gchashes, gcmacs, gcprps]: for c in i.itervalues(): d[_fixname(c.name)] = c @@ -217,15 +214,31 @@ _augment(Poly1305Hash, _tmp) class _HashBase (object): ## The standard hash methods. Assume that `hash' is defined and returns ## the receiver. - def hashu8(me, n): return me.hash(_pack('B', n)) - def hashu16l(me, n): return me.hash(_pack('H', n)) + def _check_range(me, n, max): + if not (0 <= n <= max): raise OverflowError("out of range") + def hashu8(me, n): + me._check_range(n, 0xff) + return me.hash(_pack('B', n)) + def hashu16l(me, n): + me._check_range(n, 0xffff) + return me.hash(_pack('H', n)) hashu16 = hashu16b - def hashu32l(me, n): return me.hash(_pack('L', n)) + def hashu32l(me, n): + me._check_range(n, 0xffffffff) + return me.hash(_pack('L', n)) hashu32 = hashu32b - def hashu64l(me, n): return me.hash(_pack('Q', n)) + def hashu64l(me, n): + me._check_range(n, 0xffffffffffffffff) + return me.hash(_pack('Q', n)) hashu64 = hashu64b def hashbuf8(me, s): return me.hashu8(len(s)).hash(s) def hashbuf16l(me, s): return me.hashu16l(len(s)).hash(s) @@ -248,8 +261,8 @@ class _ShakeBase (_HashBase): me._h = me._SHAKE(perso = perso, func = me._FUNC) ## Delegate methods... - def copy(me): new = me.__class__(); new._copy(me) - def _copy(me, other): me._h = other._h + def copy(me): new = me.__class__._bare_new(); new._copy(me); return new + def _copy(me, other): me._h = other._h.copy() def hash(me, m): me._h.hash(m); return me def xof(me): me._h.xof(); return me def get(me, n): return me._h.get(n) @@ -262,6 +275,8 @@ class _ShakeBase (_HashBase): def buffered(me): return me._h.buffered @property def rate(me): return me._h.rate + @classmethod + def _bare_new(cls): return cls() class _tmp: def check(me, h): @@ -300,6 +315,8 @@ class KMAC (_ShakeBase): def xof(me): me.rightenc(0) return super(KMAC, me).xof() + @classmethod + def _bare_new(cls): return cls("") class KMAC128 (KMAC): _SHAKE = Shake128; _TAGSZ = 16 class KMAC256 (KMAC): _SHAKE = Shake256; _TAGSZ = 32 @@ -353,15 +370,18 @@ class BaseRat (object): def __mul__(me, you): n, d = _split_rat(you) return type(me)(me._n*n, me._d*d) - def __div__(me, you): + __rmul__ = __mul__ + def __truediv__(me, you): n, d = _split_rat(you) return type(me)(me._n*d, me._d*n) - def __rdiv__(me, you): + def __rtruediv__(me, you): n, d = _split_rat(you) return type(me)(me._d*n, me._n*d) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ def __cmp__(me, you): n, d = _split_rat(you) - return type(me)(me._n*d, n*me._d) + return cmp(me._n*d, n*me._d) def __rcmp__(me, you): n, d = _split_rat(you) return cmp(n*me._d, me._n*d) @@ -381,8 +401,10 @@ class _tmp: def mont(x): return MPMont(x) def barrett(x): return MPBarrett(x) def reduce(x): return MPReduce(x) - def __div__(me, you): return IntRat(me, you) - def __rdiv__(me, you): return IntRat(you, me) + def __truediv__(me, you): return IntRat(me, you) + def __rtruediv__(me, you): return IntRat(you, me) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ _repr_pretty_ = _pp_str _augment(MP, _tmp) @@ -393,8 +415,10 @@ class _tmp: def halftrace(x, y): return x.reduce().halftrace(y) def modsqrt(x, y): return x.reduce().sqrt(y) def quadsolve(x, y): return x.reduce().quadsolve(y) - def __div__(me, you): return GFRat(me, you) - def __rdiv__(me, you): return GFRat(you, me) + def __truediv__(me, you): return GFRat(me, you) + def __rtruediv__(me, you): return GFRat(you, me) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ _repr_pretty_ = _pp_str _augment(GF, _tmp) @@ -586,7 +610,7 @@ class _tmp: def pad(me, sz): if sz > me.max: raise ValueError, 'key too large' elif sz < me.min: return me.min - else: sz += me.mod; return sz - sz%me.mod + else: sz += me.mod - 1; return sz - sz%me.mod _augment(KeySZRange, _tmp) class _tmp: @@ -978,14 +1002,9 @@ class Ed448Priv (_EdDSAPriv, Ed448Pub): return ed448_sign(me.priv, msg, pub = me.pub, **kw) ###-------------------------------------------------------------------------- -### Built-in named curves and prime groups. - -class _groupmap (object): - def __init__(me, map, nth): - me.map = map - me.nth = nth - me._n = max(map.values()) + 1 - me.i = me._n*[None] +### Built-in algorithm and group tables. + +class _tmp: def __repr__(me): return '{%s}' % ', '.join(['%r: %r' % kv for kv in me.iteritems()]) def _repr_pretty_(me, pp, cyclep): @@ -993,36 +1012,7 @@ class _groupmap (object): if cyclep: pp.text('...') else: _pp_dict(pp, me.iteritems()) pp.end_group(ind, ' }') - def __len__(me): - return me._n - def __contains__(me, k): - return k in me.map - def __getitem__(me, k): - i = me.map[k] - if me.i[i] is None: - me.i[i] = me.nth(i) - return me.i[i] - def __setitem__(me, k, v): - raise TypeError, "immutable object" - def __iter__(me): - return iter(me.map) - def iterkeys(me): - return iter(me.map) - def itervalues(me): - for k in me: - yield me[k] - def iteritems(me): - for k in me: - yield k, me[k] - def keys(me): - return [k for k in me] - def values(me): - return [me[k] for k in me] - def items(me): - return [(k, me[k]) for k in me] -eccurves = _groupmap(_base._eccurves, ECInfo._curven) -primegroups = _groupmap(_base._pgroups, DHInfo._groupn) -bingroups = _groupmap(_base._bingroups, BinDHInfo._groupn) +_augment(_base._MiscTable, _tmp) ###-------------------------------------------------------------------------- ### Prime number generation.