Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 

336 rindas
9.6 KiB

  1. from ctypes import *
  2. from base64 import *
  3. DECAF = CDLL("build/lib/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. passing = True
  12. # TODO: pathological cases
  13. # TODO: Elligator
  14. # TODO: double scalar mul
  15. # TODO: Curve25519
  16. def random_array(length):
  17. answer = "".join([chr(randint(0,255)) for i in xrange(length)])
  18. return answer
  19. def from_le(buf):
  20. return sum([256^i * ord(x) for i,x in enumerate(buf)])
  21. def youfail(why,n):
  22. print ("Fail on test %d!"%n), why
  23. global passing
  24. passing = False
  25. def run_test(i):
  26. try:
  27. s = DecafScalar.random()
  28. t = DecafScalar.random()
  29. p = DecafPoint.random()
  30. q = DecafPoint.random()
  31. s*p + t*q
  32. if s*(t*p) != (s*t)*p:
  33. raise Exception("Mul doesn't work")
  34. (p+q-p-q).ser() # i guess...
  35. except Exception, e:
  36. youfail(e,i)
  37. def run_all_tests(n = 100):
  38. for testno in xrange(n):
  39. run_test(testno)
  40. if passing:
  41. print "Passed all %d tests." % n
  42. def to_le(x,n):
  43. x = int(x)
  44. if x >= 256^n:
  45. raise Exception("Integer too big in to_le(%d,%d)" % (x,n))
  46. return "".join([chr(x>>(8*i) & 255) for i in xrange(n)])
  47. class DecafScalar():
  48. _UNDER = c_uint64 * int(7)
  49. def __init__(self,cstruct=None,scalar=None):
  50. if cstruct is None:
  51. cstruct = DecafScalar._UNDER()
  52. memmove(addressof(cstruct),
  53. DECAF.decaf_448_scalar_zero,
  54. 8*7
  55. )
  56. if scalar is None:
  57. scalar = E(0)
  58. self.cstruct = cstruct
  59. self.scalar = scalar
  60. self._check()
  61. @staticmethod
  62. def _c_deser(str):
  63. buffer = (c_uint8*int(56)).from_buffer_copy(str)
  64. cstruct = DecafScalar._UNDER()
  65. ret = DECAF.decaf_448_scalar_decode(cstruct,buffer,c_uint64(-1))
  66. if ret != -1:
  67. raise Exception("scalar didn't decode")
  68. return cstruct
  69. @staticmethod
  70. def _sage_deser(str):
  71. s = from_le(str)
  72. if s >= FQ.cardinality(): raise Exception("scalar didn't decode")
  73. return FQ(s)
  74. def __eq__(self,other):
  75. csays = bool(DECAF.decaf_448_scalar_eq(self.cstruct,other.cstruct))
  76. sagesays = any([self.scalar == other.scalar + t for t in Tor])
  77. if csays != sagesays:
  78. raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
  79. return csays
  80. def __ne__(self,other):
  81. return not self==other
  82. def __add__(self,other):
  83. cstruct = DecafScalar._UNDER()
  84. DECAF.decaf_448_scalar_add(cstruct,self.cstruct,other.cstruct)
  85. return DecafScalar(cstruct,self.scalar + other.scalar)
  86. def __sub__(self,other):
  87. cstruct = DecafScalar._UNDER()
  88. DECAF.decaf_448_scalar_sub(cstruct,self.cstruct,other.cstruct)
  89. return DecafScalar(cstruct,self.scalar - other.scalar)
  90. def __mul__(self,other):
  91. if isinstance(other,DecafScalar):
  92. cstruct = DecafScalar._UNDER()
  93. DECAF.decaf_448_scalar_mul(cstruct,self.cstruct,other.cstruct)
  94. return DecafScalar(cstruct,self.scalar * other.scalar)
  95. elif isinstance(other,DecafPoint):
  96. cstruct = DecafPoint._UNDER()
  97. DECAF.decaf_448_point_scalarmul(cstruct,other.cstruct,self.cstruct)
  98. return DecafPoint(cstruct,int(self.scalar) * other.point)
  99. else: raise Exception("Nope")
  100. def __div__(self,other):
  101. return self / other.inverse()
  102. def inverse(self):
  103. cstruct = DecafScalar._UNDER()
  104. z = DECAF.decaf_448_scalar_invert(cstruct,self.cstruct)
  105. if bool(z) != (self.scalar == 0):
  106. raise Exception("C and SAGE don't agree")
  107. return DecafScalar(cstruct,1/self.scalar)
  108. def __neg__(self):
  109. cstruct = DecafScalar._UNDER()
  110. DECAF.decaf_448_scalar_negate(cstruct,self.cstruct)
  111. return DecafScalar(cstruct,-self.scalar)
  112. def __str__(self):
  113. return " ".join(["%02x"%ord(b) for b in self.ser()])
  114. def __repr__(self):
  115. return "DecafScalar.fromInt(%d)" % self.scalar
  116. @classmethod
  117. def fromInt(cls,i):
  118. return cls.deser(to_le(i,56))
  119. def to64(self):
  120. return b64encode(self.ser())
  121. @classmethod
  122. def from64(cls,str):
  123. return cls.deser(b64decode(str))
  124. @classmethod
  125. def deser(cls,str):
  126. good = True
  127. try: cstruct = cls._c_deser(str)
  128. except Exception: good = False
  129. good2 = True
  130. try: scalar = cls._sage_deser(str)
  131. except Exception: good2 = False
  132. if good != good2:
  133. raise Exception("C and SAGE don't agree")
  134. elif not good:
  135. raise Exception("scalar didn't decode")
  136. return cls(cstruct,scalar)
  137. @classmethod
  138. def random(cls):
  139. while True:
  140. try: return cls.deser(random_array(56))
  141. except Exception: pass
  142. @staticmethod
  143. def _c_ser(cstruct):
  144. buffer = (c_uint8*int(56))()
  145. DECAF.decaf_448_scalar_encode(buffer,cstruct)
  146. return str(bytearray(buffer))
  147. def ser(self):
  148. return self._c_ser(self.cstruct)
  149. @staticmethod
  150. def _sage_ser(P):
  151. return to_le(P,56)
  152. def _check(self):
  153. ss = self._sage_ser(self.scalar)
  154. cs = self._c_ser(self.cstruct)
  155. if ss != cs:
  156. print ss
  157. print cs
  158. raise Exception("Check failed!")
  159. return True
  160. class DecafPoint():
  161. _UNDER = c_uint64 * int(8*4)
  162. def __init__(self,cstruct=None,point=None):
  163. if cstruct is None:
  164. cstruct = DecafPoint._UNDER()
  165. memmove(addressof(cstruct),
  166. DECAF.decaf_448_point_identity,
  167. 8*8*4
  168. )
  169. if point is None:
  170. point = E(0)
  171. self.cstruct = cstruct
  172. self.point = point
  173. self._check()
  174. @staticmethod
  175. def _c_deser(str):
  176. buffer = (c_uint8*int(56)).from_buffer_copy(str)
  177. cstruct = DecafPoint._UNDER()
  178. ret = DECAF.decaf_448_point_decode(cstruct,buffer,c_uint64(-1))
  179. if ret != -1:
  180. raise Exception("Point didn't decode")
  181. return cstruct
  182. @staticmethod
  183. def _sage_deser(str):
  184. s = from_le(str)
  185. if s > (F.cardinality()-1)/2: raise Exception("Point didn't decode")
  186. if (s==0): return E(0)
  187. if not E.is_x_coord(s^2): raise Exception("Point didn't decode")
  188. P = E.lift_x(s^2)
  189. t = P.xy()[1] / s
  190. if is_odd(int(2*t/s)): P = -P
  191. return P
  192. def __eq__(self,other):
  193. csays = bool(DECAF.decaf_448_point_eq(self.cstruct,other.cstruct))
  194. sagesays = any([self.point == other.point + t for t in Tor])
  195. if csays != sagesays:
  196. raise Exception("C and SAGE don't agree: %d %d" % (csays, sagesays))
  197. return csays
  198. def __ne__(self,other):
  199. return not self==other
  200. def __add__(self,other):
  201. cstruct = DecafPoint._UNDER()
  202. DECAF.decaf_448_point_add(cstruct,self.cstruct,other.cstruct)
  203. return DecafPoint(cstruct,self.point + other.point)
  204. def __sub__(self,other):
  205. cstruct = DecafPoint._UNDER()
  206. DECAF.decaf_448_point_sub(cstruct,self.cstruct,other.cstruct)
  207. return DecafPoint(cstruct,self.point - other.point)
  208. def __mul__(self,other):
  209. if isinstance(other,DecafScalar):
  210. return other*self
  211. else:
  212. raise Exception("nope")
  213. def __div__(self,other):
  214. if isinstance(other,DecafScalar):
  215. return other.inverse()*self
  216. else:
  217. raise Exception("nope")
  218. def __neg__(self):
  219. cstruct = DecafPoint._UNDER()
  220. DECAF.decaf_448_point_negate(cstruct,self.cstruct)
  221. return DecafPoint(cstruct,-self.point)
  222. def __str__(self):
  223. return " ".join(["%02x"%ord(b) for b in self.ser()])
  224. def __repr__(self):
  225. return "DecafPoint.from64('%s')" % self.to64()
  226. def to64(self):
  227. return b64encode(self.ser())
  228. @classmethod
  229. def from64(cls,str):
  230. return cls.deser(b64decode(str))
  231. @classmethod
  232. def deser(cls,str):
  233. good = True
  234. try: cstruct = cls._c_deser(str)
  235. except Exception: good = False
  236. good2 = True
  237. try: point = cls._sage_deser(str)
  238. except Exception: good2 = False
  239. if good != good2:
  240. raise Exception("C and SAGE don't agree")
  241. elif not good:
  242. raise Exception("Point didn't decode")
  243. return cls(cstruct,point)
  244. @classmethod
  245. def random(cls):
  246. while True:
  247. try: return cls.deser(random_array(56))
  248. except Exception: pass
  249. @staticmethod
  250. def _c_ser(cstruct):
  251. buffer = (c_uint8*int(56))()
  252. DECAF.decaf_448_point_encode(buffer,cstruct)
  253. return str(bytearray(buffer))
  254. def ser(self):
  255. return self._c_ser(self.cstruct)
  256. @staticmethod
  257. def _sage_ser(P):
  258. if P == E(0): return to_le(0,56)
  259. x,y = P.xy()
  260. s = sqrt(x)
  261. if s==0: return to_le(0,56)
  262. if is_odd(int(2*y/s^2)): s = 1/s
  263. if int(s) > (F.cardinality()-1)/2: s = -s
  264. return to_le(s,56)
  265. def _check(self):
  266. ss = self._sage_ser(self.point)
  267. cs = self._c_ser(self.cstruct)
  268. if ss != cs:
  269. print ss
  270. print cs
  271. raise Exception("Check failed!")
  272. return True
  273. run_all_tests()