| @@ -1,4 +1,281 @@ | |||
| from ctypes import * | |||
| from base64 import * | |||
| decaf = CDLL("libdecaf.so") | |||
| 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) | |||
| def from_le(buf): | |||
| return sum([256^i * ord(x) for i,x in enumerate(buf)]) | |||
| 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 __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) | |||
| @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 __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) | |||
| @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 | |||