You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

281 lines
8.3 KiB

  1. from ctypes import *
  2. from base64 import *
  3. DECAF = CDLL("libdecaf.so")
  4. F = GF(2^448-2^224-1)
  5. d = -39081
  6. E = EllipticCurve(F,[0,2-4*d,0,1,0])
  7. p_tor4 = E.lift_x(-1)
  8. Tor = [p_tor4 * i for i in xrange(4)]
  9. q = 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
  10. FQ = GF(q)
  11. def from_le(buf):
  12. return sum([256^i * ord(x) for i,x in enumerate(buf)])
  13. def to_le(x,n):
  14. x = int(x)
  15. if x >= 256^n:
  16. raise Exception("Integer too big in to_le(%d,%d)" % (x,n))
  17. return "".join([chr(x>>(8*i) & 255) for i in xrange(n)])
  18. class DecafScalar():
  19. _UNDER = c_uint64 * int(7)
  20. def __init__(self,cstruct=None,scalar=None):
  21. if cstruct is None:
  22. cstruct = DecafScalar._UNDER()
  23. memmove(addressof(cstruct),
  24. DECAF.decaf_448_scalar_zero,
  25. 8*7
  26. )
  27. if scalar is None:
  28. scalar = E(0)
  29. self.cstruct = cstruct
  30. self.scalar = scalar
  31. self._check()
  32. @staticmethod
  33. def _c_deser(str):
  34. buffer = (c_uint8*int(56)).from_buffer_copy(str)
  35. cstruct = DecafScalar._UNDER()
  36. ret = DECAF.decaf_448_scalar_decode(cstruct,buffer,c_uint64(-1))
  37. if ret != -1:
  38. raise Exception("scalar didn't decode")
  39. return cstruct
  40. @staticmethod
  41. def _sage_deser(str):
  42. s = from_le(str)
  43. if s >= FQ.cardinality(): raise Exception("scalar didn't decode")
  44. return FQ(s)
  45. def __eq__(self,other):
  46. csays = bool(DECAF.decaf_448_scalar_eq(self.cstruct,other.cstruct))
  47. sagesays = any([self.scalar == other.scalar + t for t in Tor])
  48. if csays != sagesays:
  49. raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
  50. return csays
  51. def __add__(self,other):
  52. cstruct = DecafScalar._UNDER()
  53. DECAF.decaf_448_scalar_add(cstruct,self.cstruct,other.cstruct)
  54. return DecafScalar(cstruct,self.scalar + other.scalar)
  55. def __sub__(self,other):
  56. cstruct = DecafScalar._UNDER()
  57. DECAF.decaf_448_scalar_sub(cstruct,self.cstruct,other.cstruct)
  58. return DecafScalar(cstruct,self.scalar - other.scalar)
  59. def __mul__(self,other):
  60. if isinstance(other,DecafScalar):
  61. cstruct = DecafScalar._UNDER()
  62. DECAF.decaf_448_scalar_mul(cstruct,self.cstruct,other.cstruct)
  63. return DecafScalar(cstruct,self.scalar * other.scalar)
  64. elif isinstance(other,DecafPoint):
  65. cstruct = DecafPoint._UNDER()
  66. DECAF.decaf_448_point_scalarmul(cstruct,other.cstruct,self.cstruct)
  67. return DecafPoint(cstruct,int(self.scalar) * other.point)
  68. else: raise Exception("Nope")
  69. def __div__(self,other):
  70. return self / other.inverse()
  71. def inverse(self):
  72. cstruct = DecafScalar._UNDER()
  73. z = DECAF.decaf_448_scalar_invert(cstruct,self.cstruct)
  74. if bool(z) != (self.scalar == 0):
  75. raise Exception("C and SAGE don't agree")
  76. return DecafScalar(cstruct,1/self.scalar)
  77. def __neg__(self):
  78. cstruct = DecafScalar._UNDER()
  79. DECAF.decaf_448_scalar_negate(cstruct,self.cstruct)
  80. return DecafScalar(cstruct,-self.scalar)
  81. def __str__(self):
  82. return " ".join(["%02x"%ord(b) for b in self.ser()])
  83. def __repr__(self):
  84. return "DecafScalar.fromInt(%d)" % self.scalar
  85. @classmethod
  86. def fromInt(cls,i):
  87. return cls.deser(to_le(i,56))
  88. def to64(self):
  89. return b64encode(self.ser())
  90. @classmethod
  91. def from64(cls,str):
  92. return cls.deser(b64decode(str))
  93. @classmethod
  94. def deser(cls,str):
  95. good = True
  96. try: cstruct = cls._c_deser(str)
  97. except Exception: good = False
  98. good2 = True
  99. try: scalar = cls._sage_deser(str)
  100. except Exception: good2 = False
  101. if good != good2:
  102. raise Exception("C and SAGE don't agree")
  103. elif not good:
  104. raise Exception("scalar didn't decode")
  105. return cls(cstruct,scalar)
  106. @staticmethod
  107. def _c_ser(cstruct):
  108. buffer = (c_uint8*int(56))()
  109. DECAF.decaf_448_scalar_encode(buffer,cstruct)
  110. return str(bytearray(buffer))
  111. def ser(self):
  112. return self._c_ser(self.cstruct)
  113. @staticmethod
  114. def _sage_ser(P):
  115. return to_le(P,56)
  116. def _check(self):
  117. ss = self._sage_ser(self.scalar)
  118. cs = self._c_ser(self.cstruct)
  119. if ss != cs:
  120. print ss
  121. print cs
  122. raise Exception("Check failed!")
  123. return True
  124. class DecafPoint():
  125. _UNDER = c_uint64 * int(8*4)
  126. def __init__(self,cstruct=None,point=None):
  127. if cstruct is None:
  128. cstruct = DecafPoint._UNDER()
  129. memmove(addressof(cstruct),
  130. DECAF.decaf_448_point_identity,
  131. 8*8*4
  132. )
  133. if point is None:
  134. point = E(0)
  135. self.cstruct = cstruct
  136. self.point = point
  137. self._check()
  138. @staticmethod
  139. def _c_deser(str):
  140. buffer = (c_uint8*int(56)).from_buffer_copy(str)
  141. cstruct = DecafPoint._UNDER()
  142. ret = DECAF.decaf_448_point_decode(cstruct,buffer,c_uint64(-1))
  143. if ret != -1:
  144. raise Exception("Point didn't decode")
  145. return cstruct
  146. @staticmethod
  147. def _sage_deser(str):
  148. s = from_le(str)
  149. if s > (F.cardinality()-1)/2: raise Exception("Point didn't decode")
  150. if (s==0): return E(0)
  151. if not E.is_x_coord(s^2): raise Exception("Point didn't decode")
  152. P = E.lift_x(s^2)
  153. t = P.xy()[1] / s
  154. if is_odd(int(2*t/s)): P = -P
  155. return P
  156. def __eq__(self,other):
  157. csays = bool(DECAF.decaf_448_point_eq(self.cstruct,other.cstruct))
  158. sagesays = any([self.point == other.point + t for t in Tor])
  159. if csays != sagesays:
  160. raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
  161. return csays
  162. def __add__(self,other):
  163. cstruct = DecafPoint._UNDER()
  164. DECAF.decaf_448_point_add(cstruct,self.cstruct,other.cstruct)
  165. return DecafPoint(cstruct,self.point + other.point)
  166. def __sub__(self,other):
  167. cstruct = DecafPoint._UNDER()
  168. DECAF.decaf_448_point_sub(cstruct,self.cstruct,other.cstruct)
  169. return DecafPoint(cstruct,self.point - other.point)
  170. def __mul__(self,other):
  171. if isinstance(other,DecafScalar):
  172. return other*self
  173. else:
  174. raise Exception("nope")
  175. def __div__(self,other):
  176. if isinstance(other,DecafScalar):
  177. return other.inverse()*self
  178. else:
  179. raise Exception("nope")
  180. def __neg__(self):
  181. cstruct = DecafPoint._UNDER()
  182. DECAF.decaf_448_point_negate(cstruct,self.cstruct)
  183. return DecafPoint(cstruct,-self.point)
  184. def __str__(self):
  185. return " ".join(["%02x"%ord(b) for b in self.ser()])
  186. def __repr__(self):
  187. return "DecafPoint.from64('%s')" % self.to64()
  188. def to64(self):
  189. return b64encode(self.ser())
  190. @classmethod
  191. def from64(cls,str):
  192. return cls.deser(b64decode(str))
  193. @classmethod
  194. def deser(cls,str):
  195. good = True
  196. try: cstruct = cls._c_deser(str)
  197. except Exception: good = False
  198. good2 = True
  199. try: point = cls._sage_deser(str)
  200. except Exception: good2 = False
  201. if good != good2:
  202. raise Exception("C and SAGE don't agree")
  203. elif not good:
  204. raise Exception("Point didn't decode")
  205. return cls(cstruct,point)
  206. @staticmethod
  207. def _c_ser(cstruct):
  208. buffer = (c_uint8*int(56))()
  209. DECAF.decaf_448_point_encode(buffer,cstruct)
  210. return str(bytearray(buffer))
  211. def ser(self):
  212. return self._c_ser(self.cstruct)
  213. @staticmethod
  214. def _sage_ser(P):
  215. if P == E(0): return to_le(0,56)
  216. x,y = P.xy()
  217. s = sqrt(x)
  218. if s==0: return to_le(0,56)
  219. if is_odd(int(2*y/s^2)): s = 1/s
  220. if int(s) > (F.cardinality()-1)/2: s = -s
  221. return to_le(s,56)
  222. def _check(self):
  223. ss = self._sage_ser(self.point)
  224. cs = self._c_ser(self.cstruct)
  225. if ss != cs:
  226. print ss
  227. print cs
  228. raise Exception("Check failed!")
  229. return True