| 1 | #! /usr/bin/python |
| 2 | |
| 3 | from sys import argv |
| 4 | import catacomb as C |
| 5 | |
| 6 | TESTS = {} |
| 7 | NTEST = 20 |
| 8 | |
| 9 | def test(arg): |
| 10 | def reg(fn, name): |
| 11 | TESTS[name] = fn |
| 12 | return fn |
| 13 | if isinstance(arg, str): return lambda fn: reg(fn, arg) |
| 14 | else: return reg(arg, arg.__name__.replace('_', '-')) |
| 15 | |
| 16 | FIELDS = {} |
| 17 | |
| 18 | class FieldElt (object): |
| 19 | def __init__(me, k, n): |
| 20 | me.k = k |
| 21 | me.v = (C.MP(n)%k.p).storel(k.len) |
| 22 | def __str__(me): return hex(me.v) |
| 23 | @property |
| 24 | def n(me): return C.MP.loadl(me.v) |
| 25 | def __pos__(me): return FieldElt(me.k, me.n) |
| 26 | def __neg__(me): return FieldElt(me.k, -me.n) |
| 27 | def __nonzero__(me): return me.n != 0 |
| 28 | def __add__(me, you): return FieldElt(me.k, me.n + me.k(you).n) |
| 29 | def __radd__(me, you): return FieldElt(me.k, me.k(you).n + me.n) |
| 30 | def __sub__(me, you): return FieldElt(me.k, me.n - me.k(you).n) |
| 31 | def __rsub__(me, you): return FieldElt(me.k, me.k(you).n - me.n) |
| 32 | def __mul__(me, you): return FieldElt(me.k, me.n*me.k(you).n) |
| 33 | def __rmul__(me, you): return FieldElt(me.k, me.k(you).n*me.n) |
| 34 | def __div__(me, you): return FieldElt(me.k, me.n*me.k(you).inv().n) |
| 35 | def __rdiv__(me, you): return FieldElt(me.k, me.k(you).n*me.inv().n) |
| 36 | def inv(me): return FieldElt(me.k, me.k.p.modinv(me.n)) |
| 37 | def sqrt(me): return FieldElt(me.k, me.k.p.modsqrt(me.n)) |
| 38 | @classmethod |
| 39 | def rand(cls, k): |
| 40 | me = cls(k, 0) |
| 41 | me.v = C.rand.block(k. len) |
| 42 | return me |
| 43 | |
| 44 | class Field (object): |
| 45 | def __init__(me, p, len = None): |
| 46 | me.p = C.MP(p) |
| 47 | me.len = len is None and me.p.noctets or len |
| 48 | @classmethod |
| 49 | def register(cls, name, *args, **kw): |
| 50 | FIELDS[name] = cls(*args, **kw) |
| 51 | def rand(me): return FieldElt.rand(me) |
| 52 | def __call__(me, n): |
| 53 | if isinstance(n, FieldElt): |
| 54 | assert n.k is me |
| 55 | return n |
| 56 | else: |
| 57 | return FieldElt(me, n) |
| 58 | |
| 59 | Field.register('f25519', C.MP(0).setbit(255) - 19) |
| 60 | Field.register('fgoldi', C.MP(0).setbit(448) - C.MP(0).setbit(224) - 1) |
| 61 | |
| 62 | def binop(k, op): |
| 63 | x = k.rand(); y = k.rand() |
| 64 | print ' %s\n %s\n %s;' % (x, y, op(x, y)) |
| 65 | |
| 66 | def unop(k, op): |
| 67 | x = k.rand() |
| 68 | print ' %s\n %s;' % (x, op(x)) |
| 69 | |
| 70 | @test |
| 71 | def add(k): binop(k, lambda x, y: x + y) |
| 72 | |
| 73 | @test |
| 74 | def sub(k): binop(k, lambda x, y: x - y) |
| 75 | |
| 76 | @test |
| 77 | def neg(k): unop(k, lambda x: -x) |
| 78 | |
| 79 | @test |
| 80 | def mul(k): binop(k, lambda x, y: x*y) |
| 81 | |
| 82 | @test |
| 83 | def sqr(k): unop(k, lambda x: x*x) |
| 84 | |
| 85 | @test |
| 86 | def inv(k): unop(k, lambda x: x and x.inv() or k(0)) |
| 87 | |
| 88 | @test |
| 89 | def quosqrt(k): |
| 90 | x = k.rand(); y = k.rand() |
| 91 | yy = +y |
| 92 | u = yy and x/y or k(0) |
| 93 | try: zz = u.sqrt() |
| 94 | except ValueError: print ' %s\n %s\n "" "";' % (x, y) |
| 95 | else: print ' %s\n %s\n %s\n %s;' % (x, y, zz, -zz) |
| 96 | |
| 97 | @test |
| 98 | def mulconst(k): |
| 99 | x = k.rand() |
| 100 | a = C.rand.range(1 << 20) - (1 << 19) |
| 101 | print ' %s %d\n %s;' % (x, a, a*x) |
| 102 | |
| 103 | def mask(): return C.rand.range(2)*0xffffffff |
| 104 | |
| 105 | @test |
| 106 | def pick2(k): |
| 107 | x = k.rand(); y = k.rand(); m = mask() |
| 108 | print ' %s\n %s\n 0x%08x\n %s;' % (x, y, m, +(m and x or y)) |
| 109 | |
| 110 | @test |
| 111 | def condneg(k): |
| 112 | x = k.rand(); m = mask() |
| 113 | print ' %s\n 0x%08x\n %s;' % (x, m, x*(m and -1 or +1)) |
| 114 | |
| 115 | @test |
| 116 | def pickn(k): |
| 117 | n = C.rand.range(31) + 1 |
| 118 | v = [k.rand() for i in xrange(n)] |
| 119 | i = C.rand.range(n) |
| 120 | print ' "%s"\n %d\n %s;' % ('\n '.join(map(str, v)), i, +v[i]) |
| 121 | |
| 122 | @test |
| 123 | def condswap(k): |
| 124 | x = k.rand(); y = k.rand(); m = mask() |
| 125 | xx, yy = m and (+y, +x) or (+x, +y) |
| 126 | print ' %s\n %s\n 0x%08x\n %s\n %s;' % (x, y, m, xx, yy) |
| 127 | |
| 128 | @test |
| 129 | def sub_mulc_add_sub_mul(k): |
| 130 | u = k.rand(); v = k.rand(); w = k.rand(); x = k.rand(); y = k.rand(); |
| 131 | a = C.rand.range(1 << 20) - (1 << 19) |
| 132 | print ' %s\n %s %d\n %s\n %s\n %s\n %s;' % \ |
| 133 | (u, v, a, w, x, y, ((u - v)*a + w)*(x - y)) |
| 134 | |
| 135 | k = FIELDS[argv[1]] |
| 136 | for t in argv[2:]: |
| 137 | print '%s {' % t |
| 138 | for i in xrange(NTEST): TESTS[t](k) |
| 139 | print '}' |