|
- from ctypes import *
- from base64 import *
-
- DECAF = CDLL("libdecaf.so")
-
- F = GF(2^448-2^224-1)
- d = -39081
- E = EllipticCurve(F,[0,2-4*d,0,1,0])
- p_tor4 = E.lift_x(-1)
- Tor = [p_tor4 * i for i in xrange(4)]
- q = 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
- FQ = GF(q)
-
- passing = True
-
- # TODO: pathological cases
- # TODO: Elligator
- # TODO: double scalar mul
-
- def random_array(length):
- answer = "".join([chr(randint(0,255)) for i in xrange(length)])
- return answer
-
- def from_le(buf):
- return sum([256^i * ord(x) for i,x in enumerate(buf)])
-
- def youfail(why,n):
- print ("Fail on test %d!"%n), why
- global passing
- passing = False
-
- def run_test(i):
- try:
- s = DecafScalar.random()
- t = DecafScalar.random()
- p = DecafPoint.random()
- q = DecafPoint.random()
- s*p + t*q
- if s*(t*p) != (s*t)*p:
- raise Exception("Mul doesn't work")
- (p+q-p-q).ser() # i guess...
- except Exception, e:
- youfail(e,i)
-
- def run_all_tests(n = 100):
- for testno in xrange(n):
- run_test(testno)
- if passing:
- print "Passed all %d tests." % n
-
- def to_le(x,n):
- x = int(x)
- if x >= 256^n:
- raise Exception("Integer too big in to_le(%d,%d)" % (x,n))
- return "".join([chr(x>>(8*i) & 255) for i in xrange(n)])
-
- class DecafScalar():
- _UNDER = c_uint64 * int(7)
- def __init__(self,cstruct=None,scalar=None):
- if cstruct is None:
- cstruct = DecafScalar._UNDER()
- memmove(addressof(cstruct),
- DECAF.decaf_448_scalar_zero,
- 8*7
- )
- if scalar is None:
- scalar = E(0)
- self.cstruct = cstruct
- self.scalar = scalar
-
- self._check()
-
- @staticmethod
- def _c_deser(str):
- buffer = (c_uint8*int(56)).from_buffer_copy(str)
- cstruct = DecafScalar._UNDER()
- ret = DECAF.decaf_448_scalar_decode(cstruct,buffer,c_uint64(-1))
- if ret != -1:
- raise Exception("scalar didn't decode")
- return cstruct
-
- @staticmethod
- def _sage_deser(str):
- s = from_le(str)
- if s >= FQ.cardinality(): raise Exception("scalar didn't decode")
- return FQ(s)
-
- def __eq__(self,other):
- csays = bool(DECAF.decaf_448_scalar_eq(self.cstruct,other.cstruct))
- sagesays = any([self.scalar == other.scalar + t for t in Tor])
- if csays != sagesays:
- raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
- return csays
-
- def __ne__(self,other):
- return not self==other
-
- def __add__(self,other):
- cstruct = DecafScalar._UNDER()
- DECAF.decaf_448_scalar_add(cstruct,self.cstruct,other.cstruct)
- return DecafScalar(cstruct,self.scalar + other.scalar)
-
- def __sub__(self,other):
- cstruct = DecafScalar._UNDER()
- DECAF.decaf_448_scalar_sub(cstruct,self.cstruct,other.cstruct)
- return DecafScalar(cstruct,self.scalar - other.scalar)
-
- def __mul__(self,other):
- if isinstance(other,DecafScalar):
- cstruct = DecafScalar._UNDER()
- DECAF.decaf_448_scalar_mul(cstruct,self.cstruct,other.cstruct)
- return DecafScalar(cstruct,self.scalar * other.scalar)
- elif isinstance(other,DecafPoint):
- cstruct = DecafPoint._UNDER()
- DECAF.decaf_448_point_scalarmul(cstruct,other.cstruct,self.cstruct)
- return DecafPoint(cstruct,int(self.scalar) * other.point)
- else: raise Exception("Nope")
-
- def __div__(self,other):
- return self / other.inverse()
-
- def inverse(self):
- cstruct = DecafScalar._UNDER()
- z = DECAF.decaf_448_scalar_invert(cstruct,self.cstruct)
- if bool(z) != (self.scalar == 0):
- raise Exception("C and SAGE don't agree")
- return DecafScalar(cstruct,1/self.scalar)
-
- def __neg__(self):
- cstruct = DecafScalar._UNDER()
- DECAF.decaf_448_scalar_negate(cstruct,self.cstruct)
- return DecafScalar(cstruct,-self.scalar)
-
- def __str__(self):
- return " ".join(["%02x"%ord(b) for b in self.ser()])
-
- def __repr__(self):
- return "DecafScalar.fromInt(%d)" % self.scalar
-
- @classmethod
- def fromInt(cls,i):
- return cls.deser(to_le(i,56))
-
- def to64(self):
- return b64encode(self.ser())
-
- @classmethod
- def from64(cls,str):
- return cls.deser(b64decode(str))
-
- @classmethod
- def deser(cls,str):
- good = True
- try: cstruct = cls._c_deser(str)
- except Exception: good = False
-
- good2 = True
- try: scalar = cls._sage_deser(str)
- except Exception: good2 = False
-
- if good != good2:
- raise Exception("C and SAGE don't agree")
- elif not good:
- raise Exception("scalar didn't decode")
-
- return cls(cstruct,scalar)
-
- @classmethod
- def random(cls):
- while True:
- try: return cls.deser(random_array(56))
- except Exception: pass
-
- @staticmethod
- def _c_ser(cstruct):
- buffer = (c_uint8*int(56))()
- DECAF.decaf_448_scalar_encode(buffer,cstruct)
- return str(bytearray(buffer))
-
- def ser(self):
- return self._c_ser(self.cstruct)
-
- @staticmethod
- def _sage_ser(P):
- return to_le(P,56)
-
- def _check(self):
- ss = self._sage_ser(self.scalar)
- cs = self._c_ser(self.cstruct)
- if ss != cs:
- print ss
- print cs
- raise Exception("Check failed!")
- return True
-
- class DecafPoint():
- _UNDER = c_uint64 * int(8*4)
- def __init__(self,cstruct=None,point=None):
- if cstruct is None:
- cstruct = DecafPoint._UNDER()
- memmove(addressof(cstruct),
- DECAF.decaf_448_point_identity,
- 8*8*4
- )
- if point is None:
- point = E(0)
- self.cstruct = cstruct
- self.point = point
-
- self._check()
-
- @staticmethod
- def _c_deser(str):
- buffer = (c_uint8*int(56)).from_buffer_copy(str)
- cstruct = DecafPoint._UNDER()
- ret = DECAF.decaf_448_point_decode(cstruct,buffer,c_uint64(-1))
- if ret != -1:
- raise Exception("Point didn't decode")
- return cstruct
-
- @staticmethod
- def _sage_deser(str):
- s = from_le(str)
- if s > (F.cardinality()-1)/2: raise Exception("Point didn't decode")
- if (s==0): return E(0)
- if not E.is_x_coord(s^2): raise Exception("Point didn't decode")
- P = E.lift_x(s^2)
- t = P.xy()[1] / s
- if is_odd(int(2*t/s)): P = -P
- return P
-
- def __eq__(self,other):
- csays = bool(DECAF.decaf_448_point_eq(self.cstruct,other.cstruct))
- sagesays = any([self.point == other.point + t for t in Tor])
- if csays != sagesays:
- raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
- return csays
-
- def __ne__(self,other):
- return not self==other
-
- def __add__(self,other):
- cstruct = DecafPoint._UNDER()
- DECAF.decaf_448_point_add(cstruct,self.cstruct,other.cstruct)
- return DecafPoint(cstruct,self.point + other.point)
-
- def __sub__(self,other):
- cstruct = DecafPoint._UNDER()
- DECAF.decaf_448_point_sub(cstruct,self.cstruct,other.cstruct)
- return DecafPoint(cstruct,self.point - other.point)
-
- def __mul__(self,other):
- if isinstance(other,DecafScalar):
- return other*self
- else:
- raise Exception("nope")
-
- def __div__(self,other):
- if isinstance(other,DecafScalar):
- return other.inverse()*self
- else:
- raise Exception("nope")
-
- def __neg__(self):
- cstruct = DecafPoint._UNDER()
- DECAF.decaf_448_point_negate(cstruct,self.cstruct)
- return DecafPoint(cstruct,-self.point)
-
- def __str__(self):
- return " ".join(["%02x"%ord(b) for b in self.ser()])
-
- def __repr__(self):
- return "DecafPoint.from64('%s')" % self.to64()
-
- def to64(self):
- return b64encode(self.ser())
-
- @classmethod
- def from64(cls,str):
- return cls.deser(b64decode(str))
-
- @classmethod
- def deser(cls,str):
- good = True
- try: cstruct = cls._c_deser(str)
- except Exception: good = False
-
- good2 = True
- try: point = cls._sage_deser(str)
- except Exception: good2 = False
-
- if good != good2:
- raise Exception("C and SAGE don't agree")
- elif not good:
- raise Exception("Point didn't decode")
-
- return cls(cstruct,point)
-
- @classmethod
- def random(cls):
- while True:
- try: return cls.deser(random_array(56))
- except Exception: pass
-
- @staticmethod
- def _c_ser(cstruct):
- buffer = (c_uint8*int(56))()
- DECAF.decaf_448_point_encode(buffer,cstruct)
- return str(bytearray(buffer))
-
- def ser(self):
- return self._c_ser(self.cstruct)
-
- @staticmethod
- def _sage_ser(P):
- if P == E(0): return to_le(0,56)
- x,y = P.xy()
- s = sqrt(x)
- if s==0: return to_le(0,56)
- if is_odd(int(2*y/s^2)): s = 1/s
- if int(s) > (F.cardinality()-1)/2: s = -s
- return to_le(s,56)
-
- def _check(self):
- ss = self._sage_ser(self.point)
- cs = self._c_ser(self.cstruct)
- if ss != cs:
- print ss
- print cs
- raise Exception("Check failed!")
- return True
-
- run_all_tests()
-
-
|