= k[]
56 | l = Integer(readfile('l'))
57 | x0 = Integer(readfile('x0'))
58 | y0 = Integer(readfile('y0'))
59 | x1 = Integer(readfile('x1'))
60 | y1 = Integer(readfile('y1'))
61 | shape = readfile('shape').strip()
62 | s = readfile('primes')
63 | rigid = readfile('rigid').strip()
64 |
65 | safefield = True
66 | safeeq = True
67 | safebase = True
68 | saferho = True
69 | safetransfer = True
70 | safedisc = True
71 | saferigid = True
72 | safeladder = True
73 | safetwist = True
74 | safecomplete = True
75 | safeind = True
76 |
77 | V = [] # distinct verified primes
78 | for line in s.split():
79 | n = Integer(line)
80 | if not n.is_prime(): continue
81 | if n == 2:
82 | if not n in V: V += [n]
83 | continue
84 | for trybase in primes(2,10000):
85 | base = Integers(n)(trybase)
86 | if base^(n-1) != 1: continue
87 | proof = 'Primality proof for n = %s:\n' % n
88 | proof += 'Take b = %s.\n' % base
89 | proof += '
b^(n-1) mod n = 1.\n'
90 | f = factor(1)
91 | for v in reversed(V):
92 | if f.prod()^2 <= n:
93 | if n % v == 1:
94 | u = base^((n-1)/v)-1
95 | if u.is_unit():
96 | proof += '
%s is prime.\n' % (v,v)
97 | proof += '
b^((n-1)/%s)-1 mod n = %s, which is a unit, inverse %s.\n' % (v,u,1/u)
98 | f *= factor(v)^(n-1).valuation(v)
99 | if f.prod()^2 <= n: continue
100 | if n % f.prod() != 1: continue
101 | proof += '
(%s) divides n-1.\n' % f
102 | proof += '
(%s)^2 > n.\n' % f
103 | proof += "
n is prime by Pocklington's theorem.\n"
104 | proof += '\n'
105 | writefile('../../../proof/%s.html' % n,proof)
106 | if not n in V: V += [n]
107 | break
108 |
109 | writefile('verify-primes',''.join('%s\n' % (v,v) for v in V))
110 |
111 | pstatus = 'Unverified'
112 | if not p.is_prime(): pstatus = 'False'
113 | if p in V: pstatus = 'True'
114 | if pstatus != 'True': safefield = False
115 | writefile('verify-pisprime',pstatus + '\n')
116 |
117 | pstatus = 'Unverified'
118 | if not l.is_prime(): pstatus = 'False'
119 | if l in V: pstatus = 'True'
120 | if pstatus != 'True': safebase = False
121 | writefile('verify-lisprime',pstatus + '\n')
122 |
123 | writefile('expand2-p','= %s\n' % expand2(p))
124 | writefile('expand2-l','
= %s\n' % expand2(l))
125 |
126 | writefile('hex-p',hex(p) + '\n')
127 | writefile('hex-l',hex(l) + '\n')
128 | writefile('hex-x0',hex(x0) + '\n')
129 | writefile('hex-x1',hex(x1) + '\n')
130 | writefile('hex-y0',hex(y0) + '\n')
131 | writefile('hex-y1',hex(y1) + '\n')
132 |
133 | gcdlpis1 = gcd(l,p) == 1
134 | safetransfer &= requirement('verify-gcdlp1',gcdlpis1)
135 |
136 | writefile('verify-movsafe','Unverified\n')
137 | writefile('verify-embeddingdegree','Unverified\n')
138 | if gcdlpis1 and l.is_prime():
139 | u = Integers(l)(p)
140 | d = l-1
141 | for v in V:
142 | while d % v == 0: d /= v
143 | if d == 1:
144 | d = l-1
145 | for v in V:
146 | while d % v == 0:
147 | if u^(d/v) != 1: break
148 | d /= v
149 | safetransfer &= requirement('verify-movsafe',(l-1)/d <= 100)
150 | writefile('verify-embeddingdegree','%s
= (l-1)/%s\n' % (d,(l-1)/d))
151 |
152 | t = p+1-l*round((p+1)/l)
153 | if l^2 > 16*p:
154 | writefile('verify-trace','%s\n' % t)
155 | f = factor(1)
156 | d = (p+1-t)/l
157 | for v in V:
158 | while d % v == 0:
159 | d //= v
160 | f *= factor(v)
161 | writefile('verify-cofactor','%s\n' % f)
162 | else:
163 | writefile('verify-trace','Unverified\n')
164 | writefile('verify-cofactor','Unverified\n')
165 |
166 | D = t^2-4*p
167 | for v in V:
168 | while D % v^2 == 0: D /= v^2
169 | if prod([v for v in V if D % v == 0]) != -D:
170 | writefile('verify-disc','Unverified\n')
171 | writefile('verify-discisbig','Unverified\n')
172 | safedisc = False
173 | else:
174 | f = -prod([factor(v) for v in V if D % v == 0])
175 | if D % 4 != 1:
176 | D *= 4
177 | f = factor(4) * f
178 | Dbits = (log(-D)/log(2)).numerical_approx()
179 | writefile('verify-disc','%s
= %s
≈ -2^%.1f\n' % (D,f,Dbits))
180 | safedisc &= requirement('verify-discisbig',D < -2^100)
181 |
182 | pi4 = 0.78539816339744830961566084581987572105
183 | rho = log(pi4*l)/log(4)
184 | writefile('verify-rho','%.1f\n' % rho)
185 | saferho &= requirement('verify-rhoabove100',rho.numerical_approx() >= 100)
186 |
187 | twistl = 'Unverified'
188 | d = p+1+t
189 | for v in V:
190 | while d % v == 0: d /= v
191 | if d == 1:
192 | d = p+1+t
193 | for v in V:
194 | if d % v == 0:
195 | if twistl == 'Unverified' or v > twistl: twistl = v
196 |
197 | writefile('verify-twistl','%s\n' % twistl)
198 | writefile('verify-twistembeddingdegree','Unverified\n')
199 | writefile('verify-twistmovsafe','Unverified\n')
200 | if twistl == 'Unverified':
201 | writefile('hex-twistl','Unverified\n')
202 | writefile('expand2-twistl','Unverified\n')
203 | writefile('verify-twistcofactor','Unverified\n')
204 | writefile('verify-gcdtwistlp1','Unverified\n')
205 | writefile('verify-twistrho','Unverified\n')
206 | safetwist = False
207 | else:
208 | writefile('hex-twistl',hex(twistl) + '\n')
209 | writefile('expand2-twistl','
= %s\n' % expand2(twistl))
210 | f = factor(1)
211 | d = (p+1+t)/twistl
212 | for v in V:
213 | while d % v == 0:
214 | d //= v
215 | f *= factor(v)
216 | writefile('verify-twistcofactor','%s\n' % f)
217 | gcdtwistlpis1 = gcd(twistl,p) == 1
218 | safetwist &= requirement('verify-gcdtwistlp1',gcdtwistlpis1)
219 |
220 | movsafe = 'Unverified'
221 | embeddingdegree = 'Unverified'
222 | if gcdtwistlpis1 and twistl.is_prime():
223 | u = Integers(twistl)(p)
224 | d = twistl-1
225 | for v in V:
226 | while d % v == 0: d /= v
227 | if d == 1:
228 | d = twistl-1
229 | for v in V:
230 | while d % v == 0:
231 | if u^(d/v) != 1: break
232 | d /= v
233 | safetwist &= requirement('verify-twistmovsafe',(twistl-1)/d <= 100)
234 | writefile('verify-twistembeddingdegree',"%s
= (l'-1)/%s\n" % (d,(twistl-1)/d))
235 |
236 | rho = log(pi4*twistl)/log(4)
237 | writefile('verify-twistrho','%.1f\n' % rho)
238 | safetwist &= requirement('verify-twistrhoabove100',rho.numerical_approx() >= 100)
239 |
240 | precomp = 0
241 | joint = l
242 | for v in V:
243 | d1 = p+1-t
244 | d2 = p+1+t
245 | while d1 % v == 0 or d2 % v == 0:
246 | if d1 % v == 0: d1 //= v
247 | if d2 % v == 0: d2 //= v
248 | # best case for attack: cyclic; each power is usable
249 | # also assume that kangaroo is as efficient as rho
250 | if v + sqrt(pi4*joint/v) < sqrt(pi4*joint):
251 | precomp += v
252 | joint /= v
253 |
254 | rho = log(precomp + sqrt(pi4 * joint))/log(2)
255 | writefile('verify-jointrho','%.1f\n' % rho)
256 | safetwist &= requirement('verify-jointrhoabove100',rho.numerical_approx() >= 100)
257 |
258 |
259 | x0 = k(x0)
260 | y0 = k(y0)
261 | x1 = k(x1)
262 | y1 = k(y1)
263 |
264 | if shape == 'edwards':
265 | d = Integer(readfile('d'))
266 | writefile('verify-shape','Edwards\n')
267 | writefile('verify-equation','x^2+y^2 = 1%+dx^2y^2\n' % d)
268 |
269 | d = k(d)
270 | elliptic = d*(1-d)
271 | level0 = x0^2+y0^2-1-d*x0^2*y0^2
272 | level1 = x1^2+y1^2-1-d*x1^2*y1^2
273 |
274 | if shape == 'montgomery':
275 | writefile('verify-shape','Montgomery\n')
276 | A = Integer(readfile('A'))
277 | B = Integer(readfile('B'))
278 | equation = '%sy^2 = x^3%+dx^2+x' % (B,A)
279 | if B == 1:
280 | equation = 'y^2 = x^3%+dx^2+x' % A
281 | writefile('verify-equation',equation + '\n')
282 |
283 | A = k(A)
284 | B = k(B)
285 | elliptic = B*(A^2-4)
286 | level0 = B*y0^2-x0^3-A*x0^2-x0
287 | level1 = B*y1^2-x1^3-A*x1^2-x1
288 |
289 | if shape == 'shortw':
290 | writefile('verify-shape','short Weierstrass\n')
291 | a = Integer(readfile('a'))
292 | b = Integer(readfile('b'))
293 | writefile('verify-equation','y^2 = x^3%+dx%+d\n' % (a,b))
294 |
295 | a = k(a)
296 | b = k(b)
297 | elliptic = 4*a^3+27*b^2
298 | level0 = y0^2-x0^3-a*x0-b
299 | level1 = y1^2-x1^3-a*x1-b
300 |
301 | writefile('verify-elliptic',str(elliptic) + '\n')
302 | safeeq &= requirement('verify-iselliptic',elliptic != 0)
303 | safebase &= requirement('verify-isoncurve0',level0 == 0)
304 | safebase &= requirement('verify-isoncurve1',level1 == 0)
305 |
306 | if shape == 'edwards':
307 | A = 2*(1+d)/(1-d)
308 | B = 4/(1-d)
309 | x0,y0 = (1+y0)/(1-y0),((1+y0)/(1-y0))/x0
310 | x1,y1 = (1+y1)/(1-y1),((1+y1)/(1-y1))/x1
311 | shape = 'montgomery'
312 |
313 | if shape == 'montgomery':
314 | a = (3-A^2)/(3*B^2)
315 | b = (2*A^3-9*A)/(27*B^3)
316 | x0,y0 = (x0+A/3)/B,y0/B
317 | x1,y1 = (x1+A/3)/B,y1/B
318 | shape = 'shortw'
319 |
320 | try:
321 | E = EllipticCurve([a,b])
322 | numorder2 = 0
323 | numorder4 = 0
324 | for P in E(0).division_points(4):
325 | if P != 0 and 2*P == 0:
326 | numorder2 += 1
327 | if 2*P != 0 and 4*P == 0:
328 | numorder4 += 1
329 | writefile('verify-numorder2',str(numorder2) + '\n')
330 | writefile('verify-numorder4',str(numorder4) + '\n')
331 | completesingle = False
332 | completemulti = False
333 | if numorder4 == 2 and numorder2 == 1:
334 | # complete edwards form, and montgomery with unique point of order 2
335 | completesingle = True
336 | completemulti = True
337 | # should extend this to allow complete twisted hessian
338 | safecomplete &= requirement('verify-completesingle',completesingle)
339 | safecomplete &= requirement('verify-completemulti',completemulti)
340 | safecomplete &= requirement('verify-ltimesbase1is0',l * E([x1,y1]) == 0)
341 | writefile('verify-ltimesbase1',str(l * E([x1,y1])) + '\n')
342 | writefile('verify-cofactorbase01',str(((p+1-t)//l) * E([x0,y0]) == E([x1,y1])) + '\n')
343 | except:
344 | writefile('verify-numorder2','Unverified\n')
345 | writefile('verify-numorder4','Unverified\n')
346 | writefile('verify-ltimesbase1','Unverified\n')
347 | writefile('verify-cofactorbase01','Unverified\n')
348 | safecomplete = False
349 |
350 | montladder = False
351 | for r,e in (z^3+a*z+b).roots():
352 | if (3*r^2+a).is_square():
353 | montladder = True
354 | safeladder &= requirement('verify-montladder',montladder)
355 |
356 | indistinguishability = False
357 | elligator2 = False
358 | if (p+1-t) % 2 == 0:
359 | if b != 0:
360 | indistinguishability = True
361 | elligator2 = True
362 | safeind &= requirement('verify-indistinguishability',indistinguishability)
363 | writefile('verify-ind-notes','Elligator 2: %s.\n' % ['No','Yes'][elligator2])
364 |
365 | saferigid &= (rigid == 'fully rigid' or rigid == 'somewhat rigid')
366 |
367 | safecurve = True
368 | safecurve &= requirement('verify-safefield',safefield)
369 | safecurve &= requirement('verify-safeeq',safeeq)
370 | safecurve &= requirement('verify-safebase',safebase)
371 | safecurve &= requirement('verify-saferho',saferho)
372 | safecurve &= requirement('verify-safetransfer',safetransfer)
373 | safecurve &= requirement('verify-safedisc',safedisc)
374 | safecurve &= requirement('verify-saferigid',saferigid)
375 | safecurve &= requirement('verify-safeladder',safeladder)
376 | safecurve &= requirement('verify-safetwist',safetwist)
377 | safecurve &= requirement('verify-safecomplete',safecomplete)
378 | safecurve &= requirement('verify-safeind',safeind)
379 | requirement('verify-safecurve',safecurve)
380 |
381 | originaldir = os.open('.',os.O_RDONLY)
382 | for i in range(1,len(sys.argv)):
383 | /// implement for different operating systems
384 | os.fchdir(originaldir)
385 | /// as well as
386 | os.chdir(sys.argv[i])
387 | verify()
388 |
389 | ## Curve Paramaters section.
390 | /// The size of the prime field when Sonny is
391 | /// a curve defined as E where #E(Fp), and p
392 | /// is the prime of the field, defined as:
393 | sage: p
394 | 7237005577332262213973186563042994240857116359379907606001950938285454250989
395 | /// also written as
396 | sage: p
397 | 2^252 + 27742317777372353535851937790883648493
398 |
399 | /// A montgomery form of the curve
400 | /// Y^2 = X^3 + A*X^2 + B*X,
401 | /// A = 505186, B = 1
402 |
403 | /// Basepoint calculation
404 | sage: prime = 2^252 + 27742317777372353535851937790883648493
405 |
406 | sage: A = 505186
407 |
408 | sage: def findBasepoint(prime, A):
409 | F = GF(prime)
410 | E = EllipticCurve(F, [0, A, 0, 1, 0])
411 | for uInt in range(1, 1e3):
412 | u = F(uInt)
413 | v2 = u^3 + A*u^2 + u
414 | if not v2.is_square():
415 | v = v2.sqrt()
416 | point = E(u, v)
417 | pointOrder = point.order()
418 | if pointOrder > 8 and pointOrder.is_prime():
419 | Q=u^3 + A*u^2 + u
420 | return u, Q, sqrt(Q), point
421 |
422 | sage: res = findBasepoint(prime, A)
423 |
424 | sage: res
425 |
426 | (4,
427 | 8083044,
428 | 2387694734969974503585694617203302024142786955946516383730480941479078023877,
429 |
430 | (4 : 5476327F819F419674D6ECE6CD9CC73DD90461A0D99B2A65D27C9881ABA52C5 : 1)
431 |
432 | /// Hexidecimal representation
433 | (4 : 23E4A96ED9E13AF0600EA21DB1007D9FB6E47BDD233BBBD82EB8E634305E0B1 : 1)
434 |
435 | /// Prime order of curve, l
436 | sage: E
437 | Elliptic Curve defined by y^2 = x^3 + 505186*x^2 + x over Finite Field of size 7237005577332262213973186563042994240857116359379907606001950938285454250989
438 | sage: q = E.cardinality()
439 | sage: print q
440 | 7237005577332262213973186563042994240945298446207996762370788566739812500248
441 | sage: l = q/8;
442 | sage: print l
443 | 904625697166532776746648320380374280118162305775999595296348570842476562531
444 |
445 |
446 | ///Curve complex multiplicative(CM) discriminant must be > 2^100
447 | ///For this to hold true a calculation of varying values must be
448 | ///obtained.
449 | /// The first step is to obtain the trace of frobenius.
450 | /// Then check if the prime field satisfies Hasses theorem and is bound by:
451 | /// -2*sqrt(q) < t < 2*sqrt(q)
452 | /// Then compute D using
453 |
454 | sage: E.frobenius_order()
455 | Order in Number Field in phi with defining polynomial x^2 + 88182086828089156368837628454358249258*x + 7237005577332262213973186563042994240857116359379907606001950938285454250989
456 | sage: E.trace_of_frobenius()
457 | 88182086828089156368837628454358249258
458 |
459 | /// Alternatively, the trace of frobenius
460 | /// can be computed using #E(Fp) = q + 1 - t,
461 | /// where #E(Fp) is P, the prime of the field.
462 | /// As shown below.
463 |
464 | sage: P
465 | 7237005577332262213973186563042994240857116359379907606001950938285454250989
466 | sage: q
467 | 7237005577332262213973186563042994240945298446207996762370788566739812500248
468 | sage: t = q+1-P
469 | sage: t
470 | 88182086828089156368837628454358249260
471 |
472 |
--------------------------------------------------------------------------------
/sage_codes/curve_derivation:
--------------------------------------------------------------------------------
1 | sage: q = 2^252 + 27742317777372353535851937790883648493
2 | ....: Fq = GF(q)
3 | ....:
4 | ....: # We wish to find a Montgomery curve with B = 1 and A the smallest such
5 | ....: # that (A - 2) / 4 is a small integer. As well as fitting the isogeny
6 | ....: # needed for the cofactor compression algorithms. Therefore creating
7 | ....: # A+2 as square in q..
8 | ....: def get_A(n):
9 | ....: return (n * 4) + 2
10 | ....:
11 | ....: # A = 2 is invalid (singular curve), so we start at i = 1 (A = 6)
12 | ....: i = 1
13 | ....:
14 | ....: while True:
15 | ....: A = Fq(get_A(i))
16 | ....: i = i + 1
17 | ....:
18 | ....: # We also want that A^2 - 4 is nonsquare.
19 | ....: if ((A^2) - 4).is_square() && legendre_symbol(A+2, q) == 1:
20 | ....: continue
21 | ....:
22 | ....: ec = EllipticCurve(Fq, [0, A, 0, 1, 0])
23 | ....: o = ec.order()
24 | ....:
25 | ....: if (o % 8 == 0):
26 | ....: o = o // 8
27 | ....: if is_prime(o):
28 | ....: twist = ec.quadratic_twist()
29 | ....: otwist = twist.order()
30 | ....: if (otwist % 4 == 0):
31 | ....: otwist = otwist // 4
32 | ....: if is_prime(otwist):
33 | ....: print "A = %s" % A
34 | ....: exit(0)
35 | sage: A
36 | sage: 505186
37 |
38 |
--------------------------------------------------------------------------------
/sage_codes/sage_weierstrass_code:
--------------------------------------------------------------------------------
1 | sage: def egcd(a, b):
2 | ....: ^Iif a == 0:
3 | ....: ^I^Ireturn (b, 0, 1)
4 | ....: ^Ielse:
5 | ....: ^I^Ig, y, x = egcd(b % a, a)
6 | ....: ^I^Ireturn (g, x - (b // a) * y, y)
7 | ....:
8 | sage: def modinv(a, m):
9 | ....: ^Ig, x, y = egcd(a, m)
10 | ....: ^Iif g != 1:
11 | ....: ^I^Iraise Exception('modular inverse does not exist')
12 | ....: ^Ielse:
13 | ....: ^I^Ireturn x % m
14 | ....:
15 | sage: ^I^Ireturn pow(a, (p + 1) / 4, p)
16 | ....:
17 | ....: ^I# Partition p-1 to s * 2^e for an odd s (i.e.
18 | ....: ^I# reduce all the powers of 2 from p-1)
19 | ....: ^I#
20 | ....: ^Is = p - 1
21 | ....: ^Ie = 0
22 | ....: ^Iwhile s % 2 == 0:
23 | ....: ^I^Is /= 2
24 | ....: ^I^Ie += 1
25 | ....:
26 | ....: ^I# Find some 'n' with a legendre symbol n|p = -1.
27 | ....: ^I# Shouldn't take long.
28 | ....: ^I#
29 | ....: ^In = 2
30 | ....: ^Iwhile legendre_symbol(n, p) != -1:
31 | ....: ^I^In += 1
32 | ....:
33 | ....: ^I# Here be dragons!
34 | ....: ^I# Read the paper "Square roots from 1; 24, 51,
35 | ....: ^I# 10 to Dan Shanks" by Ezra Brown for more
36 | ....: ^I# information
37 | ....: ^I#
38 | ....:
39 | ....: ^I# x is a guess of the square root that gets better
40 | ....: ^I# with each iteration.
41 | ....: ^I# b is the "fudge factor" - by how much we're off
42 | ....: ^I# with the guess. The invariant x^2 = ab (mod p)gx_w = (9 + a_m/3)%p
43 | ....: ^I# is maintained throughout the loop.
44 | ....: ^I# g is used for successive powers of n to update
45 | ....: ^I# both a and b
46 | ....: ^I# r is the exponent - decreases with each update
47 | ....: ^I#
48 | ....: ^Ix = pow(a, (s + 1) / 2, p)
49 | ....: ^Ib = pow(a, s, p)
50 | ....: ^Ig = pow(n, s, p)
51 | ....: ^Ir = e
52 | ....:
53 | ....: ^Iwhile True:
54 | ....: ^I^It = b
55 | ....: ^I^Im = 0
56 | ....: ^I^Ifor m in xrange(r):
57 | ....: ^I^I^Iif t == 1:
58 | ....: ^I^I^I^Ibreak
59 | ....: ^I^I^It = pow(t, 2, p)
60 | ....:
61 | ....: ^I^Iif m == 0:
62 | ....: ^I^I^Ireturn x
63 | ....:
64 | ....: ^I^Igs = pow(g, 2 ** (r - m - 1), p)
65 | ....: ^I^Ig = (gs * gs) % p
66 | ....: ^I^Ix = (x * gs) % p
67 | ....: ^I^Ib = (b * g) % p
68 | ....: ^I^Ir = m
69 | ....:
70 | sage:
71 | sage: def legendre_symbol(a, p):
72 | ....: ^I""" Compute the Legendre symbol a|p using
73 | ....: ^I^IEuler's criterion. p is a prime, a is
74 | ....: ^I^Irelatively prime to p (if p divides
75 | ....: ^I^Ia, then a|p = 0)
76 | ....:
77 | ....: ^I^IReturns 1 if a has a square root modulo
78 | ....: ^I^Ip, -1 otherwise.
79 | ....: ^I"""
80 | ....: ^Ils = pow(a, (p - 1) / 2, p)
81 | ....: ^Ireturn -1 if ls == p - 1 else ls
82 | ....:
83 | sage: p = pow(2,255)-19
84 | sage: a_m = 486662
85 | sage: b_m = 1
86 | sage: interim_a_numerator = 3-pow(a_m,2)
87 | sage: interim_a_denominator = 3*pow(b_m,2)
88 | sage: interim_a_denominator = modinv(interim_a_denominator,p)
89 | sage: a_w = interim_a_numerator * interim_a_denominator
90 | sage: a_w = a_w % p
91 | sage: interim_b_numerator = 2*pow(a_m,3)-9*a_m
92 | sage: interim_b_denominator = 27 * pow(b_m,3)
93 | sage: interim_b_denominator = modinv(interim_b_denominator, p)
94 | sage: b_w = interim_b_numerator * interim_b_denominator
95 | sage: b_w = b_w % p
96 | sage: x = 9
97 | sage: x = (x + a_m * modinv(3,p))%p
98 | sage: y2 = pow(x,3) + a_w*x + b_w
99 | sage: y2 = y2 % p
100 | sage: y = modular_sqrt(y2,p)
101 | sage: P
102 | ---------------------------------------------------------------------------
103 | NameError Traceback (most recent call last)
104 | in ()
105 | ----> 1 P
106 |
107 | NameError: name 'P' is not defined
108 | sage:
109 | sage: p
110 | 57896044618658097711785492504343953926634992332820282019728792003956564819949
111 | sage: a_w
112 | 19298681539552699237261830834781317975544997444273427339909597334573241639236
113 | sage: b_w
114 | 55751746669818908907645289078257140818241103727901012315294400837956729358436
115 | sage: x
116 | 19298681539552699237261830834781317975544997444273427339909597334652188435546
117 | sage: y
118 | 14781619447589544791020593568409986887264606134616475288964881837755586237401
119 | sage: p = pow(2,252) + 27742317777372353535851937790883648493
120 | sage: a_m = 346598
121 | sage: b_m = 1
122 | sage: interim_a_numerator = 3-pow(a_m,2)
123 | sage: interim_a_denominator = 3*pow(b_m,2)
124 | sage: interim_a_denominator = modinv(interim_a_denominator,p)
125 | sage: a_w = interim_a_numerator * interim_a_denominator
126 | sage: a_w = a_w % p
127 | sage: interim_b_numerator = 2*pow(a_m,3)-9*a_m
128 | ....:
129 | sage: interim_b_denominator = 27 * pow(b_m,3)
130 | sage: interim_b_denominator = modinv(interim_b_denominator, p)
131 | sage: b_w = interim_b_numerator * interim_b_denominator
132 | sage: b_w = b_w % p
133 | ....:
134 | sage: x = 17
135 | sage: x = (x + a_m * modinv(3,p))%p
136 | sage: y2 = pow(x,3) + a_w*x + b_w
137 | sage: y2 = y2 % p
138 | sage: y = modular_sqrt(y2,p)
139 | sage: p
140 | 7237005577332262213973186563042994240857116359379907606001950938285454250989
141 | sage: a_w
142 | 2412335192444087404657728854347664746952372119793302535333983646055108025796
143 | sage: b_w
144 | 1340186218024493002587627141304258192751317844329612519629993998710484804961
145 | sage: x
146 | 2412335192444087404657728854347664746952372119793302535333983646095151532546
147 | sage: y
148 | 6222320563903764848551041754877036140234555813488015858364752483591799173948
149 |
--------------------------------------------------------------------------------
/src/backend/mod.rs:
--------------------------------------------------------------------------------
1 | //! This contains the different backend implementations: `u64` and further comming ones. .
2 | //!
3 | //! On this module you can find the different implementations
4 | //! done for Finite Fields mathematical-backends.
5 |
6 | /// The u64 backend contains the implementation of all of the
7 | /// mathematical base eg. Arithmetics over Finite Fields with
8 | /// a design specially thought out 64-bit architectures.
9 | pub mod u64;
10 | #[cfg(not(any(feature = "u64_backend")))]
11 |
12 | // A backend feature must fair be chosen.
13 | compile_error!(
14 | "no zerocaf backend cargo feature enabled! \
15 | please enable u64_backend"
16 | );
17 |
--------------------------------------------------------------------------------
/src/backend/u64/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod constants;
2 | pub mod field;
3 | pub mod scalar;
4 |
--------------------------------------------------------------------------------
/src/backend/u64/scalar.rs:
--------------------------------------------------------------------------------
1 | //! Arithmetic mod `2^249 + 14490550575682688738086195780655237219`
2 | //! with five 52-bit unsigned limbs
3 | //! represented in radix `2^52`.
4 | //!
5 | //! //! The basic modular operations have been taken from the
6 | //! [curve25519-dalek repository](https://github.com/dalek-cryptography/curve25519-dalek) and refactored to work
7 | //! for the Sonny sub-group field.
8 |
9 | use core::fmt::Debug;
10 | use core::ops::{Add, Mul, Neg, Sub};
11 | use core::ops::{Index, IndexMut};
12 |
13 | use std::cmp::{Ord, Ordering, PartialOrd};
14 | use std::ops::Shr;
15 |
16 | use num::Integer;
17 |
18 | use crate::backend::u64::constants;
19 | use crate::traits::ops::*;
20 | use crate::traits::Identity;
21 |
22 |
23 | /// The `Scalar` struct represents an Scalar over the modulo
24 | /// `2^249 + 14490550575682688738086195780655237219` as 5 52-bit limbs
25 | /// represented in radix `2^52`.
26 | #[derive(Copy, Clone)]
27 | pub struct Scalar(pub [u64; 5]);
28 |
29 | impl Debug for Scalar {
30 | fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
31 | write!(f, "Scalar: {:?}", &self.0[..])
32 | }
33 | }
34 |
35 | impl Index for Scalar {
36 | type Output = u64;
37 | fn index(&self, _index: usize) -> &u64 {
38 | &(self.0[_index])
39 | }
40 | }
41 |
42 | impl IndexMut for Scalar {
43 | fn index_mut(&mut self, _index: usize) -> &mut u64 {
44 | &mut (self.0[_index])
45 | }
46 | }
47 |
48 | impl PartialOrd for Scalar {
49 | fn partial_cmp(&self, other: &Scalar) -> Option {
50 | Some(self.cmp(&other))
51 | }
52 | }
53 |
54 | impl Ord for Scalar {
55 | fn cmp(&self, other: &Self) -> Ordering {
56 | for i in (0..5).rev() {
57 | if self[i] > other[i] {
58 | return Ordering::Greater;
59 | } else if self[i] < other[i] {
60 | return Ordering::Less;
61 | }
62 | }
63 | Ordering::Equal
64 | }
65 | }
66 |
67 | //-------------- From Implementations -----------------//
68 | impl From for Scalar {
69 | /// Performs the conversion.
70 | fn from(_inp: i8) -> Scalar {
71 | let mut res = Scalar::zero();
72 |
73 | match _inp >= 0 {
74 | true => {
75 | res[0] = _inp as u64;
76 | return res
77 | },
78 | false => {
79 | res[0] = _inp.abs() as u64;
80 | return -res
81 | }
82 | }
83 | }
84 | }
85 | impl From for Scalar {
86 | /// Performs the conversion.
87 | fn from(_inp: u8) -> Scalar {
88 | let mut res = Scalar::zero();
89 | res[0] = _inp as u64;
90 | res
91 | }
92 | }
93 |
94 | impl From for Scalar {
95 | /// Performs the conversion.
96 | fn from(_inp: u16) -> Scalar {
97 | let mut res = Scalar::zero();
98 | res[0] = _inp as u64;
99 | res
100 | }
101 | }
102 |
103 | impl From for Scalar {
104 | /// Performs the conversion.
105 | fn from(_inp: u32) -> Scalar {
106 | let mut res = Scalar::zero();
107 | res[0] = _inp as u64;
108 | res
109 | }
110 | }
111 |
112 | impl From for Scalar {
113 | /// Performs the conversion.
114 | fn from(_inp: u64) -> Scalar {
115 | let mut res = Scalar::zero();
116 | let mask = (1u64 << 52) - 1;
117 | res[0] = _inp & mask;
118 | res[1] = _inp >> 52;
119 | res
120 | }
121 | }
122 |
123 | impl From for Scalar {
124 | /// Performs the conversion.
125 | fn from(_inp: u128) -> Scalar {
126 | let mut res = Scalar::zero();
127 | let mask = (1u128 << 52) - 1;
128 |
129 | // Since 128 / 52 < 4 , we only need to care
130 | // about the first three limbs.
131 | res[0] = (_inp & mask) as u64;
132 | res[1] = ((_inp >> 52) & mask) as u64;
133 | res[2] = (_inp >> 104) as u64;
134 |
135 | res
136 | }
137 | }
138 |
139 | impl<'a> Neg for &'a Scalar {
140 | type Output = Scalar;
141 | /// Performs the negate operation over the
142 | /// sub-group modulo l.
143 | fn neg(self) -> Scalar {
144 | &Scalar::zero() - &self
145 | }
146 | }
147 |
148 | impl Neg for Scalar {
149 | type Output = Scalar;
150 | /// Performs the negate operation over the
151 | /// sub-group modulo l.
152 | fn neg(self) -> Scalar {
153 | -&self
154 | }
155 | }
156 |
157 | impl Identity for Scalar {
158 | /// Returns the `Identity` element for `Scalar`
159 | /// which equals `1 (mod l)`.
160 | fn identity() -> Scalar {
161 | Scalar::one()
162 | }
163 | }
164 |
165 | impl Shr for Scalar {
166 | type Output = Scalar;
167 |
168 | fn shr(self, _rhs: u8) -> Scalar {
169 | let mut res = self;
170 |
171 | for _ in 0.._rhs {
172 | let mut carry = 0u64;
173 | for i in (0..5).rev() {
174 | res[i] = res[i] | carry;
175 |
176 | carry = (res[i] & 1) << 52;
177 | res[i] >>= 1;
178 | }
179 | }
180 | res
181 | }
182 | }
183 |
184 | impl<'a, 'b> Add<&'b Scalar> for &'a Scalar {
185 | type Output = Scalar;
186 | /// Compute `a + b (mod l)`.
187 | fn add(self, b: &'b Scalar) -> Scalar {
188 | let mut sum = Scalar::zero();
189 | let mask = (1u64 << 52) - 1;
190 |
191 | // a + b
192 | let mut carry: u64 = 0;
193 | for i in 0..5 {
194 | carry = self.0[i] + b[i] + (carry >> 52);
195 | sum[i] = carry & mask;
196 | }
197 | // subtract l if the sum is >= l
198 | sum - constants::L
199 | }
200 | }
201 |
202 | impl Add for Scalar {
203 | type Output = Scalar;
204 | /// Compute `a + b (mod l)`.
205 | fn add(self, b: Scalar) -> Scalar {
206 | &self + &b
207 | }
208 | }
209 |
210 | impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar {
211 | type Output = Scalar;
212 | /// Compute `a - b (mod l)`.
213 | fn sub(self, b: &'b Scalar) -> Scalar {
214 | let mut difference = Scalar::zero();
215 | let mask = (1u64 << 52) - 1;
216 |
217 | // a - b
218 | let mut borrow: u64 = 0;
219 | // Save the wrapping_sub in borrow and add the remainder to the next limb.
220 | for i in 0..5 {
221 | // Borrow >> 63 so the Most Significant Bit of the remainder (2^64) can be carried to the next limb.
222 | borrow = self.0[i].wrapping_sub(b[i] + (borrow >> 63));
223 | difference[i] = borrow & mask;
224 | }
225 |
226 | // conditionally add `l` if the difference is negative.
227 | // Note that here borrow tells us the Most Signif Bit of the last limb so then we know if it's greater than `l`.
228 | let underflow_mask = ((borrow >> 63) ^ 1).wrapping_sub(1); // If isn't greater, we will not add it as XOR = 0.
229 | let mut carry: u64 = 0;
230 | for i in 0..5 {
231 | carry = (carry >> 52) + difference[i] + (constants::L[i] & underflow_mask);
232 | difference[i] = carry & mask;
233 | }
234 |
235 | difference
236 | }
237 | }
238 |
239 | impl Sub for Scalar {
240 | type Output = Scalar;
241 | /// Compute `a - b (mod l)`.
242 | fn sub(self, b: Scalar) -> Scalar {
243 | &self - &b
244 | }
245 | }
246 |
247 | impl<'a, 'b> Mul<&'a Scalar> for &'b Scalar {
248 | type Output = Scalar;
249 | /// This `Mul` implementation returns a double precision result.
250 | /// The result of the standard mul is stored on a [u128; 9].
251 | ///
252 | /// Then, we apply the Montgomery Reduction function to perform
253 | /// the modulo and the reduction to the `Scalar` format: [u64; 5].
254 | fn mul(self, b: &'a Scalar) -> Scalar {
255 | let ab = Scalar::montgomery_reduce(&Scalar::mul_internal(self, b));
256 | Scalar::montgomery_reduce(&Scalar::mul_internal(&ab, &constants::RR))
257 | }
258 | }
259 |
260 | impl Mul for Scalar {
261 | type Output = Scalar;
262 | /// This `Mul` implementation returns a double precision result.
263 | /// The result of the standard mul is stored on a [u128; 9].
264 | ///
265 | /// Then, we apply the Montgomery Reduction function to perform
266 | /// the modulo and the reduction to the `Scalar` format: [u64; 5].
267 | fn mul(self, b: Scalar) -> Scalar {
268 | &self * &b
269 | }
270 | }
271 |
272 | impl<'a> Square for &'a Scalar {
273 | type Output = Scalar;
274 | /// This `Square` implementation returns a double precision result.
275 | /// The result of the standard mul is stored on a [u128; 9].
276 | ///
277 | /// Then, we apply the Montgomery Reduction function to perform
278 | /// the modulo and the reduction to the `Scalar` format: [u64; 5].
279 | fn square(self) -> Scalar {
280 | let aa = Scalar::montgomery_reduce(&Scalar::square_internal(self));
281 | Scalar::montgomery_reduce(&Scalar::mul_internal(&aa, &constants::RR))
282 | }
283 | }
284 |
285 | impl<'a> Half for &'a Scalar {
286 | type Output = Scalar;
287 | /// Give the half of the Scalar value (mod l).
288 | fn half(self) -> Scalar {
289 | self * &constants::SCALAR_INVERSE_MOD_TWO
290 | }
291 | }
292 |
293 | /// Performs the op: `a^b (mod l)`.
294 | ///
295 | /// Exponentiation by squaring classical algorithm
296 | /// implementation for `Scalar`.
297 | ///
298 | /// Schneier, Bruce (1996). Applied Cryptography: Protocols,
299 | /// Algorithms, and Source Code in C, Second Edition (2nd ed.).
300 | impl<'a, 'b> Pow<&'b Scalar> for &'a Scalar {
301 | type Output = Scalar;
302 |
303 | fn pow(self, exp: &'b Scalar) -> Scalar {
304 | let mut base = *self;
305 | let mut res = Scalar::one();
306 | let mut expon = *exp;
307 |
308 | while expon > Scalar::zero() {
309 | if expon.is_even() {
310 | expon = expon.half_without_mod();
311 | base = base.square();
312 | } else {
313 | expon = expon - Scalar::one();
314 | res = res * base;
315 |
316 | expon = expon.half();
317 | base = base.square();
318 | }
319 | }
320 | res
321 | }
322 | }
323 |
324 | /// u64 * u64 = u128 inline func multiply helper
325 | fn m(x: u64, y: u64) -> u128 {
326 | (x as u128) * (y as u128)
327 | }
328 |
329 | impl Scalar {
330 | /// Return a Scalar with value = `0`.
331 | pub const fn zero() -> Scalar {
332 | Scalar([0, 0, 0, 0, 0])
333 | }
334 |
335 | /// Return a Scalar with value = `1`.
336 | pub const fn one() -> Scalar {
337 | Scalar([1, 0, 0, 0, 0])
338 | }
339 |
340 | /// Return a Scalar with value = `-1 (mod l)`.
341 | pub const fn minus_one() -> Scalar {
342 | Scalar([1129677152307298, 1363544697812651, 714439, 0, 2199023255552])
343 | }
344 |
345 | /// Evaluate if a `Scalar` is even or not.
346 | pub fn is_even(self) -> bool {
347 | self.0[0].is_even()
348 | }
349 |
350 | /// Returns the bit representation of the given `Scalar` as
351 | /// an array of 256 bits represented as `u8`.
352 | pub fn into_bits(&self) -> [u8; 256] {
353 | let bytes = self.to_bytes();
354 | let mut res = [0u8; 256];
355 |
356 | let mut j = 0;
357 |
358 | for byte in &bytes {
359 | for i in 0..8 {
360 | let bit = byte >> i as u8;
361 | res[j] = !bit.is_even() as u8;
362 | j+=1;
363 | };
364 | };
365 | res
366 | }
367 |
368 | #[allow(non_snake_case)]
369 | /// Compute the Non-Adjacent Form of a given `Scalar`.
370 | pub fn compute_NAF(&self) -> [i8; 256] {
371 | let mut k = *self;
372 | let mut i = 0;
373 | let one = Scalar::one();
374 | let mut res = [0i8; 256];
375 |
376 | while k >= one {
377 | if !k.is_even() {
378 | let ki = 2i8 - k.mod_2_pow_k(2u8) as i8;
379 | res[i] = ki;
380 | k = k - Scalar::from(ki);
381 | } else {
382 | res[i] = 0i8;
383 | };
384 |
385 | k = k.half_without_mod();
386 | i +=1;
387 | }
388 | res
389 | }
390 |
391 | #[allow(non_snake_case)]
392 | /// Compute the Windowed-Non-Adjacent Form of a given `Scalar`.
393 | ///
394 | /// ## Inputs
395 | /// - `width` => Represents the window-width i.e. `width = 2^width`.
396 | pub fn compute_window_NAF(&self, width: u8) -> [i8; 256] {
397 | let mut k = *self;
398 | let mut i = 0;
399 | let one = Scalar::one();
400 | let mut res = [0i8; 256];
401 |
402 | while k >= one {
403 | if !k.is_even() {
404 | let ki = k.mods_2_pow_k(width);
405 | res[i] = ki;
406 | k = k - Scalar::from(ki);
407 | } else {
408 | res[i] = 0i8;
409 | };
410 |
411 | k = k.half_without_mod();
412 | i+=1;
413 | }
414 | res
415 | }
416 |
417 | /// Compute the result from `Scalar (mod 2^k)`.
418 | ///
419 | /// # Panics
420 | ///
421 | /// If the given k is > 32 (5 bits) as the value gets
422 | /// greater than the limb.
423 | pub fn mod_2_pow_k(&self, k: u8) -> u8 {
424 | (self.0[0] & ((1 << k) -1)) as u8
425 | }
426 |
427 | /// Compute the result from `Scalar (mods k)`.
428 | ///
429 | /// # Panics
430 | ///
431 | /// If the given `k > 32 (5 bits)` || `k == 0` as the value gets
432 | /// greater than the limb.
433 | pub fn mods_2_pow_k(&self, w: u8) -> i8 {
434 | assert!(w < 32u8);
435 | let modulus = self.mod_2_pow_k(w) as i8;
436 | let two_pow_w_minus_one = 1i8 << (w - 1);
437 |
438 | match modulus >= two_pow_w_minus_one {
439 | false => return modulus,
440 | true => return modulus - ((1u8 << w) as i8),
441 | }
442 | }
443 |
444 | /// Unpack a 32 byte / 256 bit Scalar into 5 52-bit limbs.
445 | pub fn from_bytes(bytes: &[u8; 32]) -> Scalar {
446 | let mut words = [0u64; 4];
447 | for i in 0..4 {
448 | for j in 0..8 {
449 | words[i] |= (bytes[(i * 8) + j] as u64) << (j * 8);
450 | }
451 | }
452 |
453 | let mask = (1u64 << 52) - 1;
454 | let top_mask = (1u64 << 48) - 1;
455 | let mut s = Scalar::zero();
456 |
457 | s[0] = words[0] & mask;
458 | // Get the 64-52 = 12 bits and add words[1] (shifting 12 to the left) on the front with `|` then apply mask.
459 | s[1] = ((words[0] >> 52) | (words[1] << 12)) & mask;
460 | s[2] = ((words[1] >> 40) | (words[2] << 24)) & mask;
461 | s[3] = ((words[2] >> 28) | (words[3] << 36)) & mask;
462 | // Shift 16 to the right to get the 52 bits of the scalar on that limb. Then apply top_mask.
463 | s[4] = (words[3] >> 16) & top_mask;
464 |
465 | assert!(s <= Scalar::minus_one());
466 | s
467 | }
468 |
469 | /// Reduce a 64 byte / 512 bit scalar mod l
470 | pub fn from_bytes_wide(_bytes: &[u8; 64]) -> Scalar {
471 | // We could provide 512 bit scalar support using Montgomery Reduction.
472 | // But first we need to finnish the 256-bit implementation.
473 | unimplemented!()
474 | }
475 |
476 | /// Pack the limbs of this `Scalar` into 32 bytes
477 | pub fn to_bytes(&self) -> [u8; 32] {
478 | let mut res = [0u8; 32];
479 |
480 | res[0] = (self.0[0] >> 0) as u8;
481 | res[1] = (self.0[0] >> 8) as u8;
482 | res[2] = (self.0[0] >> 16) as u8;
483 | res[3] = (self.0[0] >> 24) as u8;
484 | res[4] = (self.0[0] >> 32) as u8;
485 | res[5] = (self.0[0] >> 40) as u8;
486 | res[6] = ((self.0[0] >> 48) | (self.0[1] << 4)) as u8;
487 | res[7] = (self.0[1] >> 4) as u8;
488 | res[8] = (self.0[1] >> 12) as u8;
489 | res[9] = (self.0[1] >> 20) as u8;
490 | res[10] = (self.0[1] >> 28) as u8;
491 | res[11] = (self.0[1] >> 36) as u8;
492 | res[12] = (self.0[1] >> 44) as u8;
493 | res[13] = (self.0[2] >> 0) as u8;
494 | res[14] = (self.0[2] >> 8) as u8;
495 | res[15] = (self.0[2] >> 16) as u8;
496 | res[16] = (self.0[2] >> 24) as u8;
497 | res[17] = (self.0[2] >> 32) as u8;
498 | res[18] = (self.0[2] >> 40) as u8;
499 | res[19] = ((self.0[2] >> 48) | (self.0[3] << 4)) as u8;
500 | res[20] = (self.0[3] >> 4) as u8;
501 | res[21] = (self.0[3] >> 12) as u8;
502 | res[22] = (self.0[3] >> 20) as u8;
503 | res[23] = (self.0[3] >> 28) as u8;
504 | res[24] = (self.0[3] >> 36) as u8;
505 | res[25] = (self.0[3] >> 44) as u8;
506 | res[26] = (self.0[4] >> 0) as u8;
507 | res[27] = (self.0[4] >> 8) as u8;
508 | res[28] = (self.0[4] >> 16) as u8;
509 | res[29] = (self.0[4] >> 24) as u8;
510 | res[30] = (self.0[4] >> 32) as u8;
511 | res[31] = (self.0[4] >> 40) as u8;
512 |
513 | // High bit should be zero.
514 | //debug_assert!((res[31] & 0b1000_0000u8) == 0u8);
515 | res
516 | }
517 |
518 | /// Given a `k`: u64, compute `2^k` giving the resulting result
519 | /// as a `Scalar`.
520 | ///
521 | /// See that the input must be between the range => 0..250.
522 | ///
523 | /// # Panics
524 | /// If the input is greater than the Sub-group order.
525 | pub fn two_pow_k(exp: u64) -> Scalar {
526 | // Check that exp has to be less than 260.
527 | // Note that a Scalar can be as much
528 | // `2^249 - 15145038707218910765482344729778085401` so we pick
529 | // 250 knowing that 249 will be lower than the prime of the
530 | // sub group.
531 | assert!(exp < 250u64, "Exponent can't be greater than the sub-group order");
532 |
533 | let mut res = Scalar::zero();
534 | match exp {
535 | 0..=51 => {
536 | res[0] = 1u64 << exp;
537 | }
538 | 52..=103 => {
539 | res[1] = 1u64 << (exp - 52);
540 | }
541 | 104..=155 => {
542 | res[2] = 1u64 << (exp - 104);
543 | }
544 | 156..=207 => {
545 | res[3] = 1u64 << (exp - 156);
546 | }
547 | _ => {
548 | res[4] = 1u64 << (exp - 208);
549 | }
550 | }
551 | res
552 | }
553 |
554 | /// Returns the half of an **EVEN** `Scalar`.
555 | ///
556 | /// This function performs almost 4x faster than the
557 | /// `Half` implementation but SHOULD be used carefully.
558 | ///
559 | /// # Panics
560 | ///
561 | /// When the `Scalar` provided is not even.
562 | pub fn half_without_mod(self) -> Scalar {
563 | //assert!(self.is_even());
564 | let mut carry = 0u64;
565 | let mut res = self;
566 |
567 | for i in (0..5).rev() {
568 | res[i] = res[i] | carry;
569 |
570 | carry = (res[i] & 1) << 52;
571 | res[i] >>= 1;
572 | }
573 | res
574 | }
575 |
576 | /// Compute `a * b`.
577 | /// Note that this is just the normal way of performing a product.
578 | /// This operation returns back a double precision result stored
579 | /// on a `[u128; 9] in order to avoid overflowings.
580 | pub(self) fn mul_internal(a: &Scalar, b: &Scalar) -> [u128; 9] {
581 | let mut res = [0u128; 9];
582 |
583 | res[0] = m(a[0], b[0]);
584 | res[1] = m(a[0], b[1]) + m(a[1], b[0]);
585 | res[2] = m(a[0], b[2]) + m(a[1], b[1]) + m(a[2], b[0]);
586 | res[3] = m(a[0], b[3]) + m(a[1], b[2]) + m(a[2], b[1]) + m(a[3], b[0]);
587 | res[4] = m(a[0], b[4]) + m(a[1], b[3]) + m(a[2], b[2]) + m(a[3], b[1]) + m(a[4], b[0]);
588 | res[5] = m(a[1], b[4]) + m(a[2], b[3]) + m(a[3], b[2]) + m(a[4], b[1]);
589 | res[6] = m(a[2], b[4]) + m(a[3], b[3]) + m(a[4], b[2]);
590 | res[7] = m(a[3], b[4]) + m(a[4], b[3]);
591 | res[8] = m(a[4], b[4]);
592 |
593 | res
594 | }
595 |
596 | /// Compute `a^2`.
597 | ///
598 | /// This operation returns a double precision result.
599 | /// So it gives back a `[u128; 9]` with the result of the squaring.
600 | pub(self) fn square_internal(a: &Scalar) -> [u128; 9] {
601 | let a_sqrt = [a[0] * 2, a[1] * 2, a[2] * 2, a[3] * 2];
602 |
603 | [
604 | m(a[0], a[0]),
605 | m(a_sqrt[0], a[1]),
606 | m(a_sqrt[0], a[2]) + m(a[1], a[1]),
607 | m(a_sqrt[0], a[3]) + m(a_sqrt[1], a[2]),
608 | m(a_sqrt[0], a[4]) + m(a_sqrt[1], a[3]) + m(a[2], a[2]),
609 | m(a_sqrt[1], a[4]) + m(a_sqrt[2], a[3]),
610 | m(a_sqrt[2], a[4]) + m(a[3], a[3]),
611 | m(a_sqrt[3], a[4]),
612 | m(a[4], a[4]),
613 | ]
614 | }
615 |
616 | /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^260
617 | pub(self) fn montgomery_reduce(limbs: &[u128; 9]) -> Scalar {
618 |
619 | fn adjustment_fact(sum: u128) -> (u128, u64) {
620 | let p = (sum as u64).wrapping_mul(constants::LFACTOR) & ((1u64 << 52) - 1);
621 | ((sum + m(p, constants::L[0])) >> 52, p)
622 | }
623 |
624 |
625 | fn montg_red_res(sum: u128) -> (u128, u64) {
626 | let w = (sum as u64) & ((1u64 << 52) - 1);
627 | (sum >> 52, w)
628 | }
629 |
630 | let l = &constants::L;
631 |
632 | // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R
633 | let (carry, n0) = adjustment_fact(limbs[0]);
634 | let (carry, n1) = adjustment_fact(carry + limbs[1] + m(n0, l[1]));
635 | let (carry, n2) = adjustment_fact(carry + limbs[2] + m(n0, l[2]) + m(n1, l[1]));
636 | let (carry, n3) =
637 | adjustment_fact(carry + limbs[3] + m(n0, l[3]) + m(n1, l[2]) + m(n2, l[1]));
638 | let (carry, n4) = adjustment_fact(
639 | carry + limbs[4] + m(n0, l[4]) + m(n1, l[3]) + m(n2, l[2]) + m(n3, l[1]),
640 | );
641 |
642 | // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result
643 | let (carry, r0) =
644 | montg_red_res(carry + limbs[5] + m(n1, l[4]) + m(n2, l[3]) + m(n3, l[2]) + m(n4, l[1]));
645 | let (carry, r1) = montg_red_res(carry + limbs[6] + m(n2, l[4]) + m(n3, l[3]) + m(n4, l[2]));
646 | let (carry, r2) = montg_red_res(carry + limbs[7] + m(n3, l[4]) + m(n4, l[3]));
647 | let (carry, r3) = montg_red_res(carry + limbs[8] + m(n4, l[4]));
648 | let r4 = carry as u64;
649 |
650 | // result may be >= r, so attempt to subtract l
651 | &Scalar([r0, r1, r2, r3, r4]) - l
652 | }
653 |
654 | /// Compute `(a * b) / R` (mod l), where R is the Montgomery modulus 2^260
655 | #[allow(dead_code)]
656 | pub(self) fn montgomery_mul(a: &Scalar, b: &Scalar) -> Scalar {
657 | Scalar::montgomery_reduce(&Scalar::mul_internal(a, b))
658 | }
659 |
660 | /// Puts a Scalar into Montgomery form, i.e. computes `a*R (mod l)`
661 | #[allow(dead_code)]
662 | pub(self) fn to_montgomery(&self) -> Scalar {
663 | Scalar::montgomery_mul(self, &constants::RR)
664 | }
665 |
666 | /// Takes a Scalar out of Montgomery form, i.e. computes `a/R (mod l)`
667 | #[allow(dead_code)]
668 | pub(self) fn from_montgomery(&self) -> Scalar {
669 | let mut limbs = [0u128; 9];
670 | for i in 0..5 {
671 | limbs[i] = self[i] as u128;
672 | }
673 | Scalar::montgomery_reduce(&limbs)
674 | }
675 | }
676 |
677 | #[cfg(test)]
678 | mod tests {
679 | use super::*;
680 |
681 | /// `A = 182687704666362864775460604089535377456991567872`.
682 | pub static A: Scalar = Scalar([0, 0, 0, 2, 0]);
683 |
684 | /// `B = 904625697166532776746648320197686575422163851717637391703244652875051672039`
685 | pub static B: Scalar = Scalar([
686 | 2766226127823335,
687 | 4237835465749098,
688 | 4503599626623787,
689 | 4503599627370493,
690 | 2199023255551,
691 | ]);
692 |
693 | /// `AB = A - B (mod l) = `365375409332725729550921208179070754913983135744`.
694 | pub static AB: Scalar = Scalar([2867050651854460, 1629308859434048, 1461147, 4, 0]);
695 |
696 | /// `BA = B - A = 904625697166532776746648320014998870755800986942176787613709275418060104167`.
697 | pub static BA: Scalar = Scalar([
698 | 2766226127823335,
699 | 4237835465749098,
700 | 4503599626623787,
701 | 4503599627370491,
702 | 2199023255551,
703 | ]);
704 |
705 | /// `A ^ B (mod l) = 722079218299359393463304261975695272152587797512052686822897975048879125727`.
706 | pub static A_POW_B: Scalar = Scalar([
707 | 2191545792217572,
708 | 448661815025744,
709 | 1377760471467833,
710 | 2830870192895755,
711 | 435342682203,
712 | ]);
713 |
714 | /// A in Montgomery domain; `A_MONT = (A * R) (mod l) = 74956990360519859676823980567085929151483724995760953292439364863916993608`.
715 | pub static A_MONT: Scalar = Scalar([
716 | 690508070349896,
717 | 1499135165000273,
718 | 3323154938341339,
719 | 2542801086174134,
720 | 182210350076,
721 | ]);
722 |
723 | /// `X = 1809251394333065553493296640760748560207343510400633813116524750123642650623`
724 | pub static X: Scalar = Scalar([
725 | 4503599627370495,
726 | 4503599627370495,
727 | 4503599627370495,
728 | 4503599627370495,
729 | 4398046511103,
730 | ]);
731 |
732 | /// `Y = 717350576871794411262215878514291949349241575907629849852603275827191647632`.
733 | pub static Y: Scalar = Scalar([
734 | 138340288859536,
735 | 461913478537005,
736 | 1182880083788836,
737 | 1688835920473363,
738 | 1743782656037,
739 | ]);
740 |
741 | /// `Y^2 (mod l) = 480582312179500987438513229347407841000328373586967991836637456597269397662`.
742 | pub static Y_SQ: Scalar = Scalar([
743 | 3511508334592158,
744 | 913859277470939,
745 | 3383393792942685,
746 | 3918279098243301,
747 | 1168230887094,
748 | ]);
749 |
750 | /// `Y/2 = 358675288435897205631107939257145974674620787953814924926301637913595823816`.
751 | pub static Y_HALF: Scalar = Scalar([
752 | 2320969958115016,
753 | 230956739268502,
754 | 2843239855579666,
755 | 3096217773921929,
756 | 871891328018,
757 | ]);
758 |
759 | /// Y in Montgomery domain; `Y_MONT = (Y * R) (mod l) = 181593701473289124342215660240169352515908506664531442677698834953613087302`.
760 | pub static Y_MONT: Scalar = Scalar([
761 | 2880674519323206,
762 | 1234984943133080,
763 | 2849728124521957,
764 | 4421863362992372,
765 | 441429835402,
766 | ]);
767 |
768 | /// `(X * Y)/R (mod l) = 394801755993377774325488732071130802534479695819740243486564413323892352807`.
769 | pub static X_TIMES_Y_MONT: Scalar = Scalar([
770 | 228255815821095,
771 | 3571367814561020,
772 | 2885104738833919,
773 | 415982367220597,
774 | 959709905966,
775 | ]);
776 |
777 | /// `X * Y (mod l) = 72607398683238392972008549298495917621610972793940628309128483126058020327`
778 | pub static X_TIMES_Y: Scalar = Scalar([
779 | 3955754814270951,
780 | 1675310998682037,
781 | 4396625830536378,
782 | 1174212537684658,
783 | 176498809098,
784 | ]);
785 |
786 | //------------------ Tests ------------------//
787 |
788 | #[test]
789 | fn partial_ord_and_eq() {
790 | assert!(Y.is_even());
791 | assert!(!X.is_even());
792 |
793 | assert!(A_MONT < Y);
794 | assert!(Y < X);
795 |
796 | assert!(Y >= Y);
797 | assert!(X == X);
798 | }
799 |
800 | #[test]
801 | fn add_with_modulo() {
802 | let res = AB + BA;
803 | let zero = Scalar::zero();
804 |
805 | for i in 0..5 {
806 | assert!(res[i] == zero[i]);
807 | }
808 | }
809 |
810 | #[test]
811 | fn add_without_modulo() {
812 | let res = BA + A;
813 |
814 | for i in 0..5 {
815 | assert!(res[i] == B[i]);
816 | }
817 | }
818 |
819 | #[test]
820 | fn sub_with_modulo() {
821 | let res = A - B;
822 | for i in 0..5 {
823 | assert!(res[i] == AB[i]);
824 | }
825 | }
826 |
827 | #[test]
828 | fn sub_without_modulo() {
829 | let res = B - A;
830 | for i in 0..5 {
831 | assert!(res[i] == BA[i]);
832 | }
833 | }
834 |
835 | #[test]
836 | fn square_internal() {
837 | let easy_res = Scalar::square_internal(&A);
838 | let res_correct: [u128; 9] = [0, 0, 0, 0, 0, 0, 4, 0, 0];
839 | for i in 0..5 {
840 | assert!(easy_res[i] == res_correct[i]);
841 | }
842 | }
843 |
844 | #[test]
845 | fn to_montgomery_conversion() {
846 | let a = Scalar::to_montgomery(&A);
847 | for i in 0..5 {
848 | assert!(a[i] == A_MONT[i]);
849 | }
850 | }
851 |
852 | #[test]
853 | fn from_montgomery_conversion() {
854 | let y = Scalar::from_montgomery(&Y_MONT);
855 | for i in 0..5 {
856 | assert!(y[i] == Y[i]);
857 | }
858 | }
859 |
860 | #[test]
861 | fn scalar_mul() {
862 | let res = &X * &Y;
863 | for i in 0..5 {
864 | assert!(res[i] == X_TIMES_Y[i]);
865 | }
866 | }
867 |
868 | #[test]
869 | fn mul_by_identity() {
870 | let res = &Y * &Scalar::identity();
871 |
872 | for i in 0..5 {
873 | assert!(res[i] == Y[i]);
874 | }
875 | }
876 |
877 | #[test]
878 | fn mul_by_zero() {
879 | let res = &Y * &Scalar::zero();
880 | for i in 0..5 {
881 | assert!(res[i] == Scalar::zero()[i]);
882 | }
883 | }
884 |
885 | #[test]
886 | fn montgomery_mul() {
887 | let res = Scalar::montgomery_mul(&X, &Y);
888 | for i in 0..5 {
889 | assert!(res[i] == X_TIMES_Y_MONT[i]);
890 | }
891 | }
892 |
893 | #[test]
894 | fn square() {
895 | let res = &Y.square();
896 |
897 | for i in 0..5 {
898 | assert!(res[i] == Y_SQ[i]);
899 | }
900 | }
901 |
902 | #[test]
903 | fn square_zero_and_identity() {
904 | let zero = &Scalar::zero().square();
905 | let one = &Scalar::identity().square();
906 |
907 | for i in 0..5 {
908 | assert!(zero[i] == Scalar::zero()[i]);
909 | assert!(one[i] == Scalar::one()[i]);
910 | }
911 | }
912 |
913 | #[test]
914 | fn half() {
915 | let res = &Y.half();
916 | for i in 0..5 {
917 | assert!(res[i] == Y_HALF[i]);
918 | }
919 |
920 | let a_half = Scalar([0, 0, 0, 1, 0]);
921 | let a_half_half = Scalar([0, 0, 2251799813685248, 0, 0]);
922 |
923 | for i in 0..5 {
924 | assert!(a_half[i] == A.half()[i]);
925 | assert!(a_half_half[i] == A.half().half()[i]);
926 | }
927 | }
928 |
929 | #[test]
930 | fn mod_pow() {
931 | let res = A.pow(&B);
932 |
933 | assert!(res == A_POW_B);
934 | }
935 |
936 | #[test]
937 | fn even_scalar() {
938 | assert!(Y.is_even());
939 | assert!(!X.is_even());
940 | assert!(Scalar::zero().is_even());
941 | }
942 |
943 | #[test]
944 | fn ct_eq() {
945 | use subtle::ConstantTimeEq;
946 | assert!(A.ct_eq(&A).unwrap_u8() == 1u8);
947 | assert!(A.ct_eq(&B).unwrap_u8() == 0u8);
948 | }
949 |
950 |
951 | #[test]
952 | fn two_pow_k() {
953 | // 0 case.
954 | assert!(Scalar::two_pow_k(0) == Scalar::one());
955 | // 1 case.
956 | assert!(Scalar::two_pow_k(1) == Scalar::from(2u8));
957 | // Normal case.
958 | assert!(Scalar::two_pow_k(249) == Scalar([0, 0, 0, 0, 2199023255552]));
959 | assert!(Scalar::two_pow_k(248) == Scalar([0, 0, 0, 0, 1099511627776]));
960 | }
961 |
962 | #[test]
963 | fn shr() {
964 | // Normal case.
965 | assert!(A >>1 == Scalar([0, 0, 0, 1, 0]));
966 | // Limb reduction case.
967 | assert!(Scalar([0, 0, 0, 1, 0]) >>1 == Scalar([0, 0, 2251799813685248, 0, 0]));
968 | // Last limb with 1 case.
969 | assert!(Scalar::one() >>1 == Scalar([0, 0, 0, 0, 0]));
970 | // Zero case.
971 | assert!(Scalar::zero() >>1 == Scalar::zero());
972 | // Max case.
973 | assert!(Scalar::minus_one() >>250 == Scalar::zero());
974 | assert!(Scalar::two_pow_k(249)>>248 == Scalar::from(2u8));
975 | // Reduction
976 | assert!(Scalar::two_pow_k(249)>>249 == Scalar::one());
977 | }
978 |
979 | #[test]
980 | fn into_bits() {
981 | // Define following results as bit-arrays.
982 | let zero = [0u8; 256];
983 | let one = {
984 | let mut res = zero.clone();
985 | res[0] = 1;
986 | res
987 | };
988 | let nine = {
989 | let mut res = one.clone();
990 | res[3] = 1;
991 | res
992 | };
993 | let two_pow_249 = {
994 | let mut res = zero.clone();
995 | res[249] = 1;
996 | res
997 | };
998 | let minus_one = [0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
999 |
1000 | // 0 case.
1001 | assert!(&Scalar::zero().into_bits()[..] == &zero[..]);
1002 | // 1 case.
1003 | assert!(&Scalar::one().into_bits()[..] == &one[..]);
1004 | // Odd case.
1005 | assert!(&Scalar::from(9u8).into_bits()[..] == &nine[..]);
1006 | // Even case.
1007 | assert!(&Scalar::two_pow_k(249).into_bits()[..] == &two_pow_249[..]);
1008 | // MAX case.
1009 | assert!(&Scalar::minus_one().into_bits()[..] == &minus_one[..]);
1010 | }
1011 |
1012 | #[test]
1013 | fn mod_four() {
1014 | // Modulo case.
1015 | assert!(Scalar::from(4u8).mod_2_pow_k(2u8) == 0u8);
1016 | // Low case.
1017 | assert!(Scalar::from(3u8).mod_2_pow_k(2u8) == 3u8);
1018 | // Bignum case.
1019 | assert!(Scalar::from(557u16).mod_2_pow_k(2u8) == 1u8);
1020 | assert!(Scalar::from(42535295865117307932887201356513780707u128).mod_2_pow_k(2u8) == 3u8);
1021 | }
1022 |
1023 | #[test]
1024 | fn naf() {
1025 | let seven_in_naf = [-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1026 | assert!(&Scalar::from(7u8).compute_NAF()[..4] == &seven_in_naf[..4]);
1027 | }
1028 |
1029 | #[test]
1030 | fn window_naf() {
1031 | let scalar = Scalar::from(1122334455u64);
1032 | // Case NAF2
1033 | let naf2_scalar = [-1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, -1, 0, 1, 0, -1, 0, 0 ,-1, 0,1,0,0,0,1];
1034 | assert!(&naf2_scalar[..] == &scalar.compute_window_NAF(2)[..31]);
1035 |
1036 | // Case NAF3
1037 | let naf3_scalar = [-1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 3,0,0,1,0,0,-1,0,0,3,0,0,0,0,0,1];
1038 | assert!(&naf3_scalar[..] == &scalar.compute_window_NAF(3)[..31]);
1039 |
1040 | // Case NAF4
1041 | let naf4_scalar = [7,0,0,0,-1,0,0,0,7,0,0,0,7,0,0,0,5,0,0,0,0,7,0,0,0,1,0,0,0,0,1];
1042 | assert!(&naf4_scalar[..] == &scalar.compute_window_NAF(4)[..31]);
1043 |
1044 | // Case NAF5
1045 | let naf5_scalar = [-9,0,0,0,0,0,0,0,-9,0,0,0,0,0,0,11,0,0,0,0,0,-9,0,0,0,0,-15,0,0,0,0,1];
1046 | assert!(&naf5_scalar[..] == &scalar.compute_window_NAF(5)[..32]);
1047 |
1048 | //Case NAF6
1049 | let naf6_scalar = [-9,0,0,0,0,0,0,0,-9,0,0,0,0,0,0,11,0,0,0,0,0,23,0,0,0,0,0,0,0,0,1];
1050 | assert!(&naf6_scalar[..] == &scalar.compute_window_NAF(6)[..31]);
1051 |
1052 | }
1053 | }
1054 |
--------------------------------------------------------------------------------
/src/constants.rs:
--------------------------------------------------------------------------------
1 | //! Contains the curve-constants needed by different algorithm implementations.
2 |
3 | use crate::edwards::CompressedEdwardsY;
4 | use crate::ristretto::CompressedRistretto;
5 |
6 | #[cfg(feature = "u64_backend")]
7 | pub use crate::backend::u64::constants::*;
8 |
9 | /// Holds the value of the Curve basepoint, which has been constructed
10 | /// from taking `y-coodrinate = 3/5 (mod l)`.
11 | /// The positive sign is choosen for it, so we leave it on it's cannonical bytes
12 | /// encoding.
13 | pub const BASEPOINT_COMPRESSED: CompressedEdwardsY = CompressedEdwardsY([
14 | 194, 24, 45, 158, 220, 161, 164, 1, 231, 42, 46, 200, 184, 98, 31, 166, 153, 153, 153, 153,
15 | 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 9,
16 | ]);
17 |
18 | /// Ristretto Basepoint on compressed format.
19 | pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto = CompressedRistretto([
20 | 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 | ]);
22 |
--------------------------------------------------------------------------------
/src/field.rs:
--------------------------------------------------------------------------------
1 | //! A `FieldElement` represents an element of the finite field
2 | //! modulo `2^252 + 27742317777372353535851937790883648493`.
3 | //!
4 | //! The `FieldElement` type is an alias for one of the backend
5 | //! implementations.
6 | //!
7 | //! `ConstantTimeEq` and `PartialEq` traits have been implemented
8 | //! here since they will be the samme across all of the different backends.
9 | //!
10 | //! # Examples
11 | //! ```rust
12 | //! use zerocaf::field::FieldElement;
13 | //! use zerocaf::traits::ops::*;
14 | //! use zerocaf::constants::EDWARDS_D;
15 | //!
16 | //! use subtle::Choice;
17 | //! use rand::rngs::OsRng;
18 | //!
19 | //! // You can create a FieldElement from a byte-array as follows:
20 | //! let a = FieldElement::from_bytes(&[0u8;32]);
21 | //!
22 | //! // You ca also create a FieldElement from an uint type as follows:
23 | //! let b = FieldElement::from(126296u128);
24 | //! let c = FieldElement::from(126297u64);
25 | //!
26 | //! // You can create random FieldElements by calling:
27 | //! let rand = FieldElement::random(&mut OsRng);
28 | //!
29 | //! // The last way of creating a FieldElement it by calling the
30 | //! // constructor. THIS IS NOT RECOMMENDED since NO checks about
31 | //! // the correctness of the input will be done at all.
32 | //! // It can be done as follows:
33 | //! let d: FieldElement = FieldElement([0, 1, 0, 0, 0]); // d = 2^52.
34 | //! assert!(d == FieldElement::two_pow_k(52u64));
35 | //!
36 | //! // All of the basuc modular operations are implemented
37 | //! // for FieldElement type:
38 | //! let mut res = &a + &b; // Performs a + b (mod l).
39 | //! res = a - b; // Performs a - b (mod l).
40 | //! res = a * b; // Performs a * b (mod l).
41 | //! res = a.square(); // Performs a^2 (mod l).
42 | //! res = -&a; // Performs Negation over the modulo l.
43 | //! res = a.pow(&b); // Performs Modular exponentiation.
44 | //! res = a.mod_sqrt(Choice::from(1u8)).unwrap(); //Performs
45 | //! // modular sqrt.
46 | //! // Returs `None` if the input is not a QR on the field.
47 | //! // Returns Some(result) if everything is correct.
48 | //!
49 | //! // Division has been also implemented. Remember that when we write
50 | //! // a/b (mod l), we are indeed performing a * inverse_mod(b, l) (mod l).
51 | //! assert!((-b / c) == EDWARDS_D);
52 | //!
53 | //! // Dividing by two even FieldElements is recommended through the `Half`
54 | //! // trait implmementation since it's much faster.
55 | //! if a.is_even() {
56 | //! let half_a = &a.half(); // This will panic if a isn't even.
57 | //! };
58 | //!
59 | //! // We can finally perform inversion modulo l for a FieldElement:
60 | //! let inv_a = &c.inverse(); // Performs a^-1 (mod l).
61 | //!
62 | //! // You can export your `FieldElement` as an slice of 32 bytes in Little
63 | //! // Endian encoding by:
64 | //! let c_bytes: [u8; 32] = c.to_bytes();
65 | //! ```
66 | //!
67 | //! `PartialOrd`, `Ord`, `PartialEq` and `Eq` are also implemented for
68 | //! `FieldElement` type.
69 | //!
70 | //! All `std::core::ops traits -> (Add, Sub, Mul, Div)` are implemented
71 | //! for both, `&FieldElement` and `FieldElement`.
72 |
73 | use core::cmp::PartialEq;
74 |
75 | use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
76 |
77 | use rand::{CryptoRng, Rng};
78 |
79 | use curve25519_dalek::scalar::Scalar;
80 |
81 | use crate::backend;
82 |
83 | #[cfg(feature = "u64_backend")]
84 | pub use backend::u64::field::*;
85 | /// A `FieldElement` represents an element of the field
86 | /// `2^252 + 27742317777372353535851937790883648493`
87 | ///
88 | /// The `FieldElement` type is an alias for one of the platform-specific
89 | /// implementations.
90 | #[cfg(feature = "u64_backend")]
91 | pub type FieldElement = backend::u64::field::FieldElement;
92 |
93 | impl PartialEq for FieldElement {
94 | fn eq(&self, other: &FieldElement) -> bool {
95 | self.ct_eq(other).unwrap_u8() == 1u8
96 | }
97 | }
98 |
99 | impl ConstantTimeEq for FieldElement {
100 | /// Test equality between two `FieldElement`s. Since the
101 | /// internal representation is not canonical, the field elements
102 | /// are normalized to wire format before comparison.
103 | fn ct_eq(&self, other: &FieldElement) -> Choice {
104 | self.to_bytes().ct_eq(&other.to_bytes())
105 | }
106 | }
107 |
108 | impl ConditionallySelectable for FieldElement {
109 | fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
110 | FieldElement([
111 | u64::conditional_select(&a.0[0], &b.0[0], choice),
112 | u64::conditional_select(&a.0[1], &b.0[1], choice),
113 | u64::conditional_select(&a.0[2], &b.0[2], choice),
114 | u64::conditional_select(&a.0[3], &b.0[3], choice),
115 | u64::conditional_select(&a.0[4], &b.0[4], choice),
116 | ])
117 | }
118 | }
119 |
120 | impl Into for &FieldElement {
121 | fn into(self) -> Scalar {
122 | Scalar::from_bytes_mod_order(self.to_bytes())
123 | }
124 | }
125 |
126 | impl FieldElement {
127 | /// Generate a valid FieldElement choosen uniformly using user-
128 | /// provided rng.
129 | ///
130 | /// By `rng` we mean any Rng that implements: `Rng` + `CryptoRng`.
131 | pub fn random(rand: &mut T) -> FieldElement
132 | where
133 | T: Rng + CryptoRng,
134 | {
135 | let mut bytes = [0u8; 32];
136 | rand.fill_bytes(&mut bytes);
137 | // Ensure that the value is lower than `FIELD_L`.
138 | bytes[31] &= 0b0000_0111;
139 | FieldElement::from_bytes(&bytes)
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![doc(
2 | html_logo_url = "https://lh3.googleusercontent.com/SmwswGxtgIANTbDrCOn5EKcRBnVdHjmYsHYxLq2HZNXWCQ9-fZyaea-bNgdX9eR0XGSqiMFi=w128-h128-e365"
3 | )]
4 | #![doc(html_favicon_url = "https://dusk.network/lib/img/favicon-16x16.png")]
5 | //!
6 | //!
7 | //!
8 | //!
9 | //!
10 | //!
11 | //!
12 | //!
13 | //!
14 | //!
15 | //!
16 | //!
17 | //!
18 | //!
19 | //!
20 | //!

21 | //!
22 | //!
23 | //!
24 | //! # What is Zerocaf?
25 | //! Zerocaf is a pure Rust cryptographic library constructed to define operations for an elliptic curve embedded
26 | //! into the Ristretto scalar field, which allows the construction of prime order groups
27 | //! from an otherwise non prime order curve.
28 | //!
29 | //! The ultimate purpose of defining operations is for set inclusion proofs - where it is shown, in zero-knowledge,
30 | //! that a private key exists in a set of many public keys.
31 | //!
32 | //! Additionally, the zero-knowledge proofs use Bulletproofs as the argument for arithmetic circuits
33 | //! that are used to form arbitrary constraint systems.
34 | //!
35 | //! # What can it be used for?
36 | //! The main goal of the library, as said before, is to be the base of operations over set inclusion proofs
37 | //! and other Zero-Knowledge protocols.
38 | //!
39 | //! But since Zerocaf is build upon the SonnyCurve using the Ristretto protocol, it allows other devs to build
40 | //! cryptographic protocols over it without needing to take care about the co-factor of the curve.
41 | //!
42 | //! This, brings to developers, a good mathematical backend library which can be used as a `mid-level` API
43 | //! for building all kinds of cryptographic protocols over it such as key agreement, signatures,
44 | //! anonymous credentials, rangeproofs...
45 | //!
46 | //! # Usage
47 | //! To import the library as a dependency of your project, just add on your `Cargo.toml`s project file:
48 | //! ```toml
49 | //! zerocaf = "0.1.1"
50 | //! ```
51 | //!
52 | //! Then import the crate as:
53 | //! ```rust
54 | //! extern crate zerocaf;
55 | //! ```
56 | //!
57 | //! # Backends.
58 | //! Zerocaf has been built following the [Curve25519-dalek](https://docs.rs/curve25519-dalek/1.2.1/curve25519_dalek/) library structure, which allows for multiple
59 | //! backend implementations. All of the works are built to enable modularity.
60 | //!
61 | //! Currently, `Zerocaf` has implemented the u64 backend.
62 | //! By default, the `u64` backend is the one which is used to perform all of
63 | //! the operations.
64 | //! Additionly, for future works, we would like to implement a `u32` backend aswell.
65 | //!
66 | //! To select a backend type, the following method can be used:
67 | //! ```sh
68 | //! // For unoptimized builds:
69 | //! cargo build --features "u64_backend"
70 | //!
71 | //! // For optimized/release builds:
72 | //! cargo build --release --features "u64_backend"
73 | //! ```
74 | //!
75 | //!
76 | //! NOTE: If no backend is selected, the compilation will fail!
77 | //!
78 | //! # Security and features of Zerocaf
79 | //!
80 | //! As is previously mentioned, zerocaf is designed to host the fastest possible curve operations whilst
81 | //! simultaneously avoiding all of the drawbacks associated with having a cofactor such that h > 1.
82 | //!
83 | //! To achieve this we make use of Ristretto, which is a technique to construct prime order elliptic curve groups.
84 | //! The Ristretto protocol compresses the cofactor by adding a thin abstraction layer to allow small changes
85 | //! in code to ultimately omit the cofactor issues.
86 | //!
87 | //! This is achieved by having defining the twisted edwards curve over the ristretto scalar field,
88 | //! which means to perform every operation on the curve in modulo L,
89 | //! where L is the order of the ristretto scalar field.
90 | //!
91 | //! `L = 2^252 + 27742317777372353535851937790883648493`.
92 | //!
93 | //! By expounding the operations in this manner, we can benefit from the speed of a non-prime order twisted
94 | //! edwards curve whilst not suffering the pitfalls of a cofactor greater than one.
95 | //!
96 | //!
97 | //! # Performance & Benchmarks
98 | //! Benchmarks have been implemented using [Criterion.rs](https://docs.rs/criterion/0.2.11/criterion/).
99 | //! To run them just execute `cargo bench` on the repository root.
100 | //!
101 | //! All of the operatons have been implemented using bit-shifting techniques to allow better performance
102 | //! and a significant reduction in execution time.
103 | //!
104 | //! # Examples
105 | //! We are planning to add some examples about tha basics of the `Zerocaf` library usage.
106 | //! They will be uploaded to the [examples](https://github.com/dusk-network/dusk-zerocaf/tree/master/docs) folder.
107 | //!
108 | //! This is a very basic usage example of the Zerocaf lib:
109 | //! ```rust
110 | //! extern crate zerocaf;
111 | //! extern crate rand;
112 | //!
113 | //! use zerocaf::field::FieldElement;
114 | //! use zerocaf::scalar::Scalar;
115 | //! use zerocaf::edwards::EdwardsPoint;
116 | //!
117 | //! use rand::{Rng, thread_rng};
118 | //!
119 | //! fn main() -> () {
120 | //!
121 | //! // Let G be an `EdwardsPoint` which is a point over the Twisted Eds Extended Coordinates.
122 | //! let G: EdwardsPoint = EdwardsPoint {
123 | //! X: FieldElement([23, 0, 0, 0, 0]),
124 | //! Y: FieldElement([1664892896009688, 132583819244870, 812547420185263, 637811013879057, 13284180325998]),
125 | //! Z: FieldElement([1, 0, 0, 0, 0]),
126 | //! T: FieldElement([4351986304670635, 4020128726404030, 674192131526433, 1158854437106827, 6468984742885])
127 | //! };
128 | //!
129 | //! let scalar: Scalar = rand_scalar_generation();
130 | //! println!("{:?}", scalar);
131 | //!
132 | //! // Perform G*k, Point mul uses the `add_and_double` standard algorithm.
133 | //! let P = &G * &scalar;
134 | //! println!("{:?}", P);
135 | //! }
136 | //!
137 | //! /// Generate a random `Scalar` defined over the sub-group field
138 | //! /// modulo: `2^249 - 15145038707218910765482344729778085401`
139 | //! pub fn rand_scalar_generation() -> Scalar {
140 | //! // Gen random 32-byte array.
141 | //! let mut bytes = [0u8;32];
142 | //!
143 | //! // Fill the bytes varible with random bytes. We can use the 32 bytes co give
144 | //! // total randomness but then we will need to be aware because we can generate
145 | //! // values greater than `L = 2^252 + 27742317777372353535851937790883648493` and
146 | //! // the program will panic if we don't catch the error correctly on the
147 | //! // `from_bytes()` Scalar method call.
148 | //! thread_rng().try_fill(&mut bytes[..31]).expect("Error getting the random bytes");
149 | //!
150 | //! Scalar::from_bytes(&bytes)
151 | //! }
152 | //! ```
153 | //!
154 | //! We will also publish some videos talking about how is the library built and
155 | //! the maths that are happening behind the scenes.
156 | //! Videos can also include programming examples using `Zerocaf` as a dependency.
157 | //! You can check them on the [Dusk Network Youtube Channel](https://www.youtube.com/channel/UCAfY3VcuaxAelPp44B253Rw).
158 | //!
159 |
160 | // Used for traits related to constant-time code.
161 | extern crate subtle;
162 | // Used for Ristretto255Scalar trait.
163 | extern crate curve25519_dalek;
164 | extern crate num;
165 |
166 | pub mod backend;
167 | pub mod constants;
168 | pub mod edwards;
169 | pub mod field;
170 | pub mod montgomery;
171 | pub mod ristretto;
172 | pub mod scalar;
173 | pub mod traits;
174 |
--------------------------------------------------------------------------------
/src/montgomery.rs:
--------------------------------------------------------------------------------
1 | //! Implementation that provides support for Montgomery Points
2 | //! over the Sonnycurve.
3 | //!
4 | //! A `MontgomeryPoint` is represented as the `u-coordinate`
5 | //! of itself in LE bytes-format.
6 |
7 | use crate::edwards::EdwardsPoint;
8 | use crate::field::FieldElement;
9 |
10 | use subtle::Choice;
11 | use subtle::ConstantTimeEq;
12 |
13 | /// Holds the u-coordinate of a point on the Montgomery form of
14 | /// Doppio-curve or its twist.
15 | #[derive(Copy, Clone, Debug)]
16 | pub struct MontgomeryPoint(pub [u8; 32]);
17 |
18 | /// Equality of `MontgomeryPoint`s is defined mod p.
19 | impl ConstantTimeEq for MontgomeryPoint {
20 | fn ct_eq(&self, other: &MontgomeryPoint) -> Choice {
21 | let self_fe = FieldElement::from_bytes(&self.0);
22 | let other_fe = FieldElement::from_bytes(&other.0);
23 |
24 | self_fe.ct_eq(&other_fe)
25 | }
26 | }
27 |
28 | impl Default for MontgomeryPoint {
29 | fn default() -> MontgomeryPoint {
30 | MontgomeryPoint([0u8; 32])
31 | }
32 | }
33 |
34 | impl PartialEq for MontgomeryPoint {
35 | fn eq(&self, other: &MontgomeryPoint) -> bool {
36 | self.ct_eq(other).unwrap_u8() == 1u8
37 | }
38 | }
39 |
40 | impl Eq for MontgomeryPoint {}
41 |
42 | impl MontgomeryPoint {
43 | /// View this `MontgomeryPoint` as an array of bytes.
44 | pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] {
45 | &self.0
46 | }
47 |
48 | /// Convert this `MontgomeryPoint` to an array of bytes.
49 | pub fn to_bytes(&self) -> [u8; 32] {
50 | self.0
51 | }
52 |
53 | /// Attempt to convert to an `EdwardsPoint`, using the supplied
54 | /// choice of sign for the `EdwardsPoint`.
55 | pub fn to_edwards(&self, _sign: u8) -> Option {
56 | unimplemented!()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/ristretto.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 | #![allow(non_snake_case)]
3 | //! Implementation of the Ristretto Protocol over the
4 | //! Sonnycurve.
5 | //!
6 | //! Notes extracted from: https://ristretto.group/ristretto.html.
7 | //! Go there for the full lecture or check the paper here:
8 | //! https://tools.ietf.org/pdf/draft-hdevalence-cfrg-ristretto-00.pdf
9 | //!
10 | //! The code wa originaly created by Isis Agora Lovecruft and
11 | //! Henry de Valence [here](https://github.com/dalek-cryptography/curve25519-dalek/blob/master/src/ristretto.rs)
12 | //!
13 | //! # What's Ristretto?
14 | //! Ristretto is a construction of a prime-order group using a non-prime-order Edwards curve.
15 | //! The Decaf paper suggests using a non-prime-order curve E\mathcal EE to implement a prime-order
16 | //! group by constructing a quotient group. Ristretto uses the same idea, but with different formulas,
17 | //! in order to allow the use of cofactor 8 curves such as Curve25519.
18 | //!
19 | //! Internally, a Ristretto point is represented by an Edwards point.
20 | //! Two Edwards points `P, Q` may represent the same Ristretto point, in the same way that
21 | //! different projective (X,Y,Z) coordinates may represent the same Edwards point.
22 | //!
23 | //! Group operations on Ristretto points are carried out with no overhead by performing the
24 | //! operations on the representative Edwards points.
25 | //!
26 | //! Reference: https://tools.ietf.org/html/draft-hdevalence-cfrg-ristretto-00
27 | use crate::constants;
28 | use crate::edwards::{double_and_add, EdwardsPoint};
29 | use crate::field::FieldElement;
30 | use crate::scalar::Scalar;
31 | use crate::traits::ops::*;
32 | use crate::traits::{Identity, ValidityCheck};
33 |
34 | use core::ops::{Add, Sub, Index, Mul, Neg};
35 |
36 | use std::fmt::Debug;
37 |
38 | use rand::{CryptoRng, Rng};
39 | use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq};
40 |
41 | /// Ristretto Point expressed in wire format.
42 | /// Since the Ristretto bytes encoding is canonical,
43 | /// two points are equal if their encodin form is equal.
44 | #[derive(Debug, Clone, Copy)]
45 | pub struct CompressedRistretto(pub [u8; 32]);
46 |
47 | impl Index for CompressedRistretto {
48 | type Output = u8;
49 | fn index(&self, _index: usize) -> &u8 {
50 | &(self.0[_index])
51 | }
52 | }
53 |
54 | impl ConstantTimeEq for CompressedRistretto {
55 | fn ct_eq(&self, other: &Self) -> Choice {
56 | self.as_bytes().ct_eq(&other.as_bytes())
57 | }
58 | }
59 |
60 | impl PartialEq for CompressedRistretto {
61 | fn eq(&self, other: &CompressedRistretto) -> bool {
62 | self.ct_eq(other).unwrap_u8() == 1u8
63 | }
64 | }
65 |
66 | impl Eq for CompressedRistretto {}
67 |
68 | impl Identity for CompressedRistretto {
69 | /// Returns the Identity point on `CompressedRistretto`
70 | /// format.
71 | fn identity() -> CompressedRistretto {
72 | CompressedRistretto([0u8; 32])
73 | }
74 | }
75 |
76 | impl CompressedRistretto {
77 | /// Get the bytes of the `CompressedRistretto` point.
78 | pub fn as_bytes(&self) -> [u8; 32] {
79 | self.0
80 | }
81 |
82 | pub fn copy_from_slice(bytes: &[u8]) -> CompressedRistretto {
83 | let mut inp = [0u8; 32];
84 | inp.copy_from_slice(bytes);
85 | CompressedRistretto(inp)
86 | }
87 |
88 | #[allow(non_snake_case)]
89 | /// Attempt to decompress a `CompressedRistretto` point.
90 | /// This proces is done following the formulas derived from the
91 | /// isogenies that suit for our curve selection.
92 | ///
93 | /// # Returns
94 | /// - If the decompression/decoding succeeds -> `Some(RistrettoPoint)`.
95 | /// - If the decompression/decoding fails -> `None`.
96 | pub fn decompress(&self) -> Option {
97 | // Step 1: Check that the byte-string is a valid FieldElement.
98 |
99 | // As Ristretto paper says: "If the implementation's field element
100 | // encoding function produces canonical outputs, one way to check
101 | // that s_bytes is a canonical encoding (in step 1) is to decode
102 | // s_bytes into sss, then re-encode sss into s_bytes_check, and ensure
103 | // that s_bytes == s_bytes_check.
104 | let s: FieldElement = FieldElement::from_bytes(&self.as_bytes());
105 | let s_check = s.to_bytes();
106 | let s_correct_enc = s_check.ct_eq(&self.as_bytes());
107 | let s_is_positive = s.is_positive();
108 |
109 | // If the byte-encoding was incorrect or the representation is
110 | // a negative `FieldElement` (according to the definition of
111 | // positive found on Decaf paper), return `None`.
112 | if s_is_positive.unwrap_u8() == 0u8 || s_correct_enc.unwrap_u8() == 0u8 {
113 | return None;
114 | };
115 | // Step 2: Attempt to decompress the CompressedRistretto.
116 | let one = FieldElement::one();
117 |
118 | // u1 = 1 + as² with a = -1.
119 | let u1 = one - s.square();
120 | // u2 = 1 - as² with a = -1.
121 | let u2 = one + s.square();
122 | let u2_sq = u2.square();
123 |
124 | // v = a*d*u1² - u2²
125 | let v = -(constants::EDWARDS_D * u1.square()) - u2_sq;
126 | // I = 1/sqrt(v*u2²), returns `None` if the sqrt does not exist.
127 | let (ok, I) = (v * u2_sq).inv_sqrt();
128 | if ok.unwrap_u8() == 0 {
129 | return None;
130 | };
131 |
132 | // Compute the Extended Point Coordinates Y & T
133 | let Dx = I * u2;
134 | let Dy = I * Dx * v;
135 |
136 | // Compute ABS(2*s*Dx) and negate if it is negative.
137 | let mut x = (s + s) * Dx;
138 | let x_is_pos = x.is_positive();
139 | x.conditional_negate(!x_is_pos);
140 | // Compute Y and T coordinates.
141 | let y = u1 * Dy;
142 | let t = x * y;
143 |
144 | if t.is_positive().unwrap_u8() == 0u8 || y == FieldElement::zero() {
145 | return None;
146 | };
147 |
148 | Some(RistrettoPoint(EdwardsPoint {
149 | X: x,
150 | Y: y,
151 | Z: one,
152 | T: t,
153 | }))
154 | }
155 | }
156 |
157 | #[derive(Clone, Copy)]
158 | pub struct RistrettoPoint(pub EdwardsPoint);
159 |
160 | impl Debug for RistrettoPoint {
161 | fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
162 | write!(f, "{:?}", &self.0)
163 | }
164 | }
165 |
166 | impl ConstantTimeEq for RistrettoPoint {
167 | /// As specified on the Ristretto protocol docs:
168 | /// https://ristretto.group/formulas/equality.html
169 | /// and we are on the twisted case, we compare
170 | /// `X1*Y2 == Y1*X2 | X1*X2 == Y1*Y2`.
171 | fn ct_eq(&self, other: &RistrettoPoint) -> Choice {
172 | let a = (self.0.X * other.0.Y).ct_eq(&(self.0.Y * other.0.X));
173 | let b = (self.0.X * other.0.X).ct_eq(&(self.0.Y * other.0.Y));
174 | a | b
175 | }
176 | }
177 |
178 | impl PartialEq for RistrettoPoint {
179 | fn eq(&self, other: &RistrettoPoint) -> bool {
180 | self.ct_eq(&other).unwrap_u8() == 1u8
181 | }
182 | }
183 |
184 | impl Eq for RistrettoPoint {}
185 |
186 | impl Identity for RistrettoPoint {
187 | /// Gives back the Identity point for the Extended Edwards Coordinates
188 | /// which is endoded as a `RistrettoPoint` with coordinates:
189 | /// `(X, Y, Z, T)` = `(0, 1, 1, 0)`.
190 | fn identity() -> RistrettoPoint {
191 | RistrettoPoint(EdwardsPoint::identity())
192 | }
193 | }
194 |
195 | impl Default for RistrettoPoint {
196 | /// Gives back the Identity point for the Extended Edwards Coordinates
197 | /// which is endoded as a `RistrettoPoint` with coordinates:
198 | /// `(X, Y, Z, T)` = `(0, 1, 1, 0)`.
199 | fn default() -> RistrettoPoint {
200 | RistrettoPoint::identity()
201 | }
202 | }
203 |
204 | //TODO: Review RistrettoPoint original implementation correctness: #83.
205 | impl ValidityCheck for RistrettoPoint {
206 | /// A valid `RistrettoPoint` should have exactly
207 | /// order `L` (Scalar Field Order) and also
208 | /// verify the curve equation.
209 | ///
210 | /// This trait is mostly implemented for debugging purposes.
211 | ///
212 | /// # Returns
213 | /// - `Choice(1) if the point has order L (not 2L, 4L or 8L) &
214 | /// satisfies the curve equation.
215 | /// - `Choice(0) if the point does not satisfy one of the conditions
216 | /// mentioned avobe.
217 | fn is_valid(&self) -> Choice {
218 | // Verify that the point has order `L` (Sub group order).
219 | let has_order_l = (self.0 * constants::L).ct_eq(&EdwardsPoint::identity());
220 | has_order_l & self.0.is_valid()
221 | }
222 | }
223 |
224 | impl<'a> Neg for &'a RistrettoPoint {
225 | type Output = RistrettoPoint;
226 | /// Negates a `RistrettoPoint` giving it's negated representation
227 | /// as a result.
228 | ///
229 | /// Since the negative of a point is (-X:Y:Z:-T), it
230 | /// gives as a result: `(-X:Y:Z:-T)`.
231 | fn neg(self) -> RistrettoPoint {
232 | RistrettoPoint(-self.0)
233 | }
234 | }
235 |
236 | impl Neg for RistrettoPoint {
237 | type Output = RistrettoPoint;
238 | /// Negates a `RistrettoPoint` giving it's negated representation
239 | /// as a result.
240 | ///
241 | /// Since the negative of a point is (-X:Y:Z:-T), it
242 | /// gives as a result: `(-X:Y:Z:-T)`.
243 | fn neg(self) -> RistrettoPoint {
244 | RistrettoPoint(-&self.0)
245 | }
246 | }
247 |
248 | impl<'a, 'b> Add<&'a RistrettoPoint> for &'b RistrettoPoint {
249 | type Output = RistrettoPoint;
250 | /// Performs the addition of two RistrettoPoints following the
251 | /// Twisted Edwards Extended Coordinates formulae.
252 | ///
253 | /// This implementation is specific for curves with `a = -1` as
254 | /// the isomorphic twist is for Doppio.
255 | ///
256 | /// [Source: 2008 Hisil–Wong–Carter–Dawson],
257 | /// (http://eprint.iacr.org/2008/522), Section 3.1.
258 | fn add(self, other: &'a RistrettoPoint) -> RistrettoPoint {
259 | RistrettoPoint(&self.0 + &other.0)
260 | }
261 | }
262 |
263 | impl Add for RistrettoPoint {
264 | type Output = RistrettoPoint;
265 | /// Performs the addition of two RistrettoPoints following the
266 | /// Twisted Edwards Extended Coordinates formulae.
267 | ///
268 | /// This implementation is specific for curves with `a = -1` as
269 | /// the isomorphic twist is for Doppio.
270 | ///
271 | /// [Source: 2008 Hisil–Wong–Carter–Dawson],
272 | /// (http://eprint.iacr.org/2008/522), Section 3.1.
273 | fn add(self, other: RistrettoPoint) -> RistrettoPoint {
274 | &self + &other
275 | }
276 | }
277 |
278 | impl<'a, 'b> Sub<&'a RistrettoPoint> for &'b RistrettoPoint {
279 | type Output = RistrettoPoint;
280 | /// Performs the subtraction of two RistrettoPoints following the
281 | /// Twisted Edwards Extended Coordinates formulae.
282 | ///
283 | /// Note that Subtraction is basically the addition of the first
284 | /// point by the second negated.
285 | ///
286 | /// This implementation is specific for curves with `a = -1` as
287 | /// the isomorphic twist is for Doppio.
288 | ///
289 | /// [Source: 2008 Hisil–Wong–Carter–Dawson],
290 | /// (http://eprint.iacr.org/2008/522), Section 3.1.
291 | fn sub(self, other: &'a RistrettoPoint) -> RistrettoPoint {
292 | self + &-other
293 | }
294 | }
295 |
296 | impl Sub for RistrettoPoint {
297 | type Output = RistrettoPoint;
298 | /// Performs the subtraction of two RistrettoPoints following the
299 | /// Twisted Edwards Extended Coordinates formulae.
300 | ///
301 | /// Note that Subtraction is basically the addition of the first
302 | /// point by the second negated.
303 | ///
304 | /// This implementation is specific for curves with `a = -1` as
305 | /// the isomorphic twist is for Doppio.
306 | ///
307 | /// [Source: 2008 Hisil–Wong–Carter–Dawson],
308 | /// (http://eprint.iacr.org/2008/522), Section 3.1.
309 | fn sub(self, other: RistrettoPoint) -> RistrettoPoint {
310 | &self - &other
311 | }
312 | }
313 |
314 | impl<'a> Double for &'a RistrettoPoint {
315 | type Output = RistrettoPoint;
316 | /// Performs the point doubling operation
317 | /// ie. `2*P` over the Twisted Edwards Extended
318 | /// Coordinates.
319 | ///
320 | /// This implementation is specific for curves with `a = -1` as
321 | /// the isomorphic twist is.
322 | /// Source: 2008 Hisil–Wong–Carter–Dawson,
323 | /// http://eprint.iacr.org/2008/522, Section 3.1.
324 | /// Cost: 4M+ 4S+ 1D
325 | fn double(self) -> RistrettoPoint {
326 | RistrettoPoint(self.0.double())
327 | }
328 | }
329 |
330 | impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoPoint {
331 | type Output = RistrettoPoint;
332 | /// Scalar multiplication: compute `self * Scalar`.
333 | /// This implementation uses the algorithm:
334 | /// `add_and_doubling` which is the standard one for
335 | /// this operations and also adds less constraints on
336 | /// R1CS.
337 | ///
338 | /// Hankerson, Darrel; Vanstone, Scott; Menezes, Alfred (2004).
339 | /// Guide to Elliptic Curve Cryptography.
340 | /// Springer Professional Computing. New York: Springer-Verlag.
341 | fn mul(self, scalar: &'b Scalar) -> RistrettoPoint {
342 | double_and_add(self, scalar)
343 | }
344 | }
345 |
346 | impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar {
347 | type Output = RistrettoPoint;
348 | /// Scalar multiplication: compute `self * Scalar`.
349 | /// This implementation uses the algorithm:
350 | /// `add_and_doubling` which is the standard one for
351 | /// this operations and also adds less constraints on
352 | /// R1CS.
353 | ///
354 | /// Hankerson, Darrel; Vanstone, Scott; Menezes, Alfred (2004).
355 | /// Guide to Elliptic Curve Cryptography.
356 | /// Springer Professional Computing. New York: Springer-Verlag.
357 | fn mul(self, point: &'b RistrettoPoint) -> RistrettoPoint {
358 | double_and_add(point, &self)
359 | }
360 | }
361 |
362 | impl Mul for RistrettoPoint {
363 | type Output = RistrettoPoint;
364 | /// Scalar multiplication: compute `self * Scalar`.
365 | /// This implementation uses the algorithm:
366 | /// `add_and_doubling` which is the standard one for
367 | /// this operations and also adds less constraints on
368 | /// R1CS.
369 | ///
370 | /// Hankerson, Darrel; Vanstone, Scott; Menezes, Alfred (2004).
371 | /// Guide to Elliptic Curve Cryptography.
372 | /// Springer Professional Computing. New York: Springer-Verlag.
373 | fn mul(self, scalar: Scalar) -> RistrettoPoint {
374 | &self * &scalar
375 | }
376 | }
377 |
378 | impl Mul for Scalar {
379 | type Output = RistrettoPoint;
380 | /// Scalar multiplication: compute `self * Scalar`.
381 | /// This implementation uses the algorithm:
382 | /// `add_and_doubling` which is the standard one for
383 | /// this operations and also adds less constraints on
384 | /// R1CS.
385 | ///
386 | /// Hankerson, Darrel; Vanstone, Scott; Menezes, Alfred (2004).
387 | /// Guide to Elliptic Curve Cryptography.
388 | /// Springer Professional Computing. New York: Springer-Verlag.
389 | fn mul(self, point: RistrettoPoint) -> RistrettoPoint {
390 | &self * &point
391 | }
392 | }
393 |
394 | impl RistrettoPoint {
395 | /// Encode a Ristretto point represented by the point `(X:Y:Z:T)`
396 | /// in extended coordinates.
397 | #[allow(non_snake_case)]
398 | pub fn compress(&self) -> CompressedRistretto {
399 | let u1 = (self.0.Z + self.0.Y) * (self.0.Z - self.0.Y);
400 | let u2 = self.0.X * self.0.Y;
401 | let (_, I) = (u1 * u2.square()).inv_sqrt();
402 | let D1 = u1 * I;
403 | let D2 = u2 * I;
404 | let Zinv = D1 * D2 * self.0.T;
405 | let mut xy;
406 | let D;
407 | if (self.0.T * Zinv).is_positive().unwrap_u8() == 0u8 {
408 | xy = (
409 | constants::SQRT_MINUS_ONE * self.0.Y,
410 | constants::SQRT_MINUS_ONE * self.0.X,
411 | );
412 | D = D1 * constants::INV_SQRT_A_MINUS_D;
413 | } else {
414 | xy = (self.0.X, self.0.Y);
415 | D = D2;
416 | };
417 |
418 | xy.1.conditional_negate(!(xy.0 * Zinv).is_positive());
419 | // We are on the Twisted case, so a = -1.
420 | // Then s = ABS((Z-Y) * D)
421 | let mut s = (self.0.Z - xy.1) * D;
422 | s.conditional_negate(!s.is_positive());
423 |
424 | CompressedRistretto(s.to_bytes())
425 | }
426 |
427 | /// Computes the Ristretto Elligator map.
428 | /// This gets a `RistrettoPoint` from a given
429 | /// `FieldElement´.
430 | pub fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint {
431 | let d = constants::EDWARDS_D;
432 | let one = FieldElement::one();
433 | let mut c = -one;
434 | // 1 - d^2
435 | let one_minus_d_sq = one - d.square();
436 |
437 | // r = i*r0^2
438 | let r = constants::SQRT_MINUS_ONE * r_0.square();
439 | // Ns = a(r+1)*(a+d)*(a-d)
440 | let N_s = (r + one) * one_minus_d_sq;
441 | // D = (d*r -a)*(a*r -d)
442 | let D = (c - (d * r)) * (r + d);
443 | // s = sqrt(Ns/D)
444 | let (Ns_D_is_sq, mut s) = N_s.sqrt_ratio_i(&D);
445 |
446 | //s' = -ABS(s*r0)
447 | let mut s_prim = &s * r_0;
448 | s_prim.conditional_negate(s_prim.is_positive());
449 |
450 | s.conditional_assign(&s_prim, !Ns_D_is_sq);
451 | c.conditional_assign(&r, !Ns_D_is_sq);
452 | // Nt = c(r-1)*(d-1)^2 - D
453 | let N_t = ((c * (r - one)) * (d - one).square()) - D;
454 | let s_square = s.square();
455 |
456 | // Get the `CompletePoint` coordinates.
457 | let W0 = (s + s) * D;
458 | let W1 = N_t * constants::SQRT_AD_MINUS_ONE;
459 | let W2 = one - s_square;
460 | let W3 = one + s_square;
461 |
462 | // Get the `EdwardsPoint` that comes from the
463 | // `CompletePoint` obtained by the original
464 | // algorithm.
465 | RistrettoPoint(EdwardsPoint {
466 | X: W0 * W3,
467 | Y: W2 * W1,
468 | Z: W1 * W3,
469 | T: W0 * W2,
470 | })
471 | }
472 |
473 | /// Debugging function used to get the 4coset where a point
474 | /// lives.
475 | pub(self) fn coset4(&self) -> [EdwardsPoint; 4] {
476 | self.0.coset4()
477 | }
478 |
479 | /// Construct a `RistrettoPoint` from 64 bytes of data.
480 | ///
481 | /// If the input bytes are uniformly distributed, the resulting
482 | /// point will be uniformly distributed over the group, and its
483 | /// discrete log with respect to other points should be unknown.
484 | ///
485 | /// # Implementation
486 | ///
487 | /// This function splits the input array into two 32-byte halves,
488 | /// takes the low 255 bits of each half mod p, applies the
489 | /// Ristretto-flavored Elligator map to each, and adds the results.
490 | ///
491 | /// This function is taken from the Ristretto255 implementation found
492 | /// in [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek/blob/cf03d39f0fc3e1c625b9f1e9be0473758b324526/src/ristretto.rs#L713)
493 | pub fn from_uniform_bytes(bytes: &[u8; 64]) -> RistrettoPoint {
494 | let mut r_1_bytes = [0u8; 32];
495 | r_1_bytes.copy_from_slice(&bytes[0..32]);
496 | let r_1 = FieldElement::from_bytes(&r_1_bytes);
497 | let R_1 = RistrettoPoint::elligator_ristretto_flavor(&r_1);
498 |
499 | let mut r_2_bytes = [0u8; 32];
500 | r_2_bytes.copy_from_slice(&bytes[32..64]);
501 | let r_2 = FieldElement::from_bytes(&r_2_bytes);
502 | let R_2 = RistrettoPoint::elligator_ristretto_flavor(&r_2);
503 |
504 | // Applying Elligator twice and adding the results ensures a
505 | // uniform distribution.
506 | R_1 + R_2
507 | }
508 |
509 | /// Generate a random `RistrettoPoint` from a 64-byte array generated
510 | /// with user-provided rng.
511 | ///
512 | /// The provided `rng` has to implement: `Rng` + `CryptoRng`.
513 | ///
514 | /// This function uses the elligator hash map twice, once for [0..31] &
515 | /// another for [32..64] giving a uniformly distributed random value.
516 | ///
517 | /// This implementation follows the idea pointed on the
518 | /// random point generation used in [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek).
519 | pub fn new_random_point(rand: &mut T) -> RistrettoPoint {
520 | let mut bytes = [0u8; 64];
521 | rand.try_fill(&mut bytes).unwrap();
522 | RistrettoPoint::from_uniform_bytes(&bytes)
523 | }
524 | }
525 |
526 | #[cfg(test)]
527 | mod tests {
528 | use super::*;
529 |
530 | #[cfg(feature = "rand")]
531 | use rand::rngs::OsRng;
532 |
533 | #[test]
534 | fn basepoint_compr_decompr() {
535 | let compress = RistrettoPoint(constants::BASEPOINT).compress();
536 |
537 | let decompress = compress.decompress().unwrap();
538 | assert!(decompress == RistrettoPoint(constants::BASEPOINT));
539 | }
540 |
541 | #[test]
542 | fn valid_encoding_test_vectors() {
543 | // The following are the byte encodings of small multiples
544 | // [0]B, [1]B, ..., [15]B
545 | // of the basepoint, represented as hex strings.
546 | let encodings_of_small_multiples = [
547 | // This is the identity point
548 | "0000000000000000000000000000000000000000000000000000000000000000",
549 | // This is the basepoint
550 | "0200000000000000000000000000000000000000000000000000000000000000",
551 | // These are small multiples of the basepoint
552 | "abe4ea98eaaeda5a9c63879cb3c4d9b4a01ed31ac383acefd7ed49861e1a8002",
553 | "1064fe35b16525f90f1d2f7d3dc448ba31a118f136c53eed88c2e951f1832907",
554 | "a826cf66461dea21e51187dddd8753299b726a7d4217cb75758aefbf5a2d4f01",
555 | "4d2e0705a9b47d122f98bd74808d386cf1691bc5407af703dd0c4808038b7f07",
556 | "f3a3592fde5fa05a881b80b4e732b37c32c7f684a5be33cdb8b7bdaf53db6f04",
557 | "51626c7960da63010efc5e064e62962f158f59928914fc108257ec2653745e01",
558 | "d5f8144c1b04954291785be578633a79131752e82afb990bd4a25b41cbd49001",
559 | "1372ed81add54633970746cd4b38ceb8a3e538b916288ac3d7c0dfbd54a42b06",
560 | "a83d7a262a80926724a0beb75a5f26e9a622205e6a64730e14ce64c4b2acf704",
561 | "a6b2712a6e586ab552f7bcf438168304b8b8a3f3b2852a06ae183e6303406503",
562 | "7876266b939b889c1da827a76da5c220eb1ff934472d35de60c9e4c3528fcc06",
563 | "11a0f75ab351572b572c38bf073b076aa964cdff70d53ad7588174dae2729306",
564 | "64f2fb80b45fbf73793e9e8e509f98848ecdb452c98c83c55c5c31fb233d9907",
565 | "1de5afbe9fd279f1651306d8ac0f68f0cb2689609ccfe8db1636f9481a33e205",
566 | ];
567 |
568 | // Test the encodings of small multiples
569 |
570 | let B = constants::RISTRETTO_BASEPOINT;
571 | let mut P = RistrettoPoint::identity();
572 | for i in 0..16 {
573 | assert_eq!(
574 | hex::encode(P.compress().as_bytes()),
575 | encodings_of_small_multiples[i],
576 | );
577 | P = P + B;
578 | }
579 | }
580 |
581 | #[test]
582 | fn decompress_id() {
583 | use crate::edwards::CompressedEdwardsY;
584 |
585 | let compressed_id = CompressedRistretto::identity();
586 | let id = compressed_id.decompress().unwrap();
587 | let mut identity_in_coset = false;
588 | for P in &id.0.coset4() {
589 | if P.compress() == CompressedEdwardsY::identity() {
590 | identity_in_coset = true;
591 | }
592 | }
593 | assert!(identity_in_coset);
594 | }
595 |
596 | #[test]
597 | fn four_torsion_diff() {
598 | use crate::edwards::{mul_by_pow_2, CompressedEdwardsY};
599 |
600 | let bp_compr_decompr = constants::RISTRETTO_BASEPOINT
601 | .compress()
602 | .decompress()
603 | .unwrap()
604 | .0;
605 |
606 | // Check that bp_compr_decompr differs from the
607 | // original RistrettoBasepoint by a point of order 4.
608 | let point_order_4 = &constants::RISTRETTO_BASEPOINT.0 - &bp_compr_decompr;
609 |
610 | let verif = mul_by_pow_2(&point_order_4, 2);
611 | assert_eq!(verif.compress(), CompressedEdwardsY::identity());
612 | }
613 |
614 | #[cfg(feature = "rand")]
615 | #[test]
616 | fn four_torsion_diff_random() {
617 | let mut rng = OsRng::new().unwrap();
618 | let B = &constants::RISTRETTO_BASEPOINT;
619 | let P = B * &Scalar::random(&mut rng);
620 | let P_coset = P.coset4();
621 | for i in 0..4 {
622 | assert_eq!(P, RistrettoPoint(P_coset[i]));
623 | }
624 |
625 | // Check that P_compr_decompr differs from the
626 | // original P by a point of order 4
627 | let P_compr_decompr = P.compress().decompress().unwrap();
628 | let point_order_4 = &P + &-P_compr_decompr;
629 | assert!(mul_by_pow_2(&point_order_4, &2) == RistrettoPoint::identity())
630 | }
631 |
632 | #[test]
633 | fn four_coset_eq_basepoint() {
634 | let basepoint = constants::RISTRETTO_BASEPOINT;
635 | let basep_coset = basepoint.coset4();
636 |
637 | for coset_point in &basep_coset {
638 | assert!(RistrettoPoint(*coset_point) == basepoint);
639 | }
640 | }
641 |
642 | #[test]
643 | fn validity_check() {
644 | // RISTRETTO_BASEPOINT should be valid.
645 | assert!(constants::RISTRETTO_BASEPOINT.is_valid().unwrap_u8() == 1u8);
646 | // The identity and multiples of the basepoint should also be valid.
647 | let mut P = RistrettoPoint::identity();
648 | let basep = constants::RISTRETTO_BASEPOINT;
649 | for _i in 0..16 {
650 | assert!(P.is_valid().unwrap_u8() == 1u8);
651 | P = P + basep;
652 | }
653 |
654 | // This point has order `8L` is a valid `EdwardsPoint`
655 | // but it's not a valid `RistrettoPoint`.
656 | let y_coord_bytes_8L = FieldElement::from_bytes(&[
657 | 177, 118, 250, 81, 30, 181, 58, 122, 224, 214, 112, 52, 50, 60, 95, 199, 213, 167, 143,
658 | 108, 154, 218, 242, 27, 175, 111, 152, 152, 213, 211, 157, 15,
659 | ]);
660 | let point_8L =
661 | EdwardsPoint::new_from_y_coord(&y_coord_bytes_8L, Choice::from(0u8)).unwrap();
662 | assert!(point_8L.is_valid().unwrap_u8() == 1u8);
663 | assert!(RistrettoPoint(point_8L).is_valid().unwrap_u8() == 0u8);
664 | }
665 |
666 | #[cfg(feature = "rand")]
667 | #[test]
668 | fn random_point_validity() {
669 | let mut rng = OsRng::new().unwrap();
670 | for i in 0..100 {
671 | let P = RistrettoPoint::new_random_point(&mut rng);
672 | // Check that the resulting `EdwardsPoint` relies on the curve.
673 | assert!(P.0.is_valid().unwrap_u8() == 1u8);
674 | P.compress().decompress();
675 | }
676 | }
677 |
678 | #[test]
679 | fn elligator_vs_ristretto_sage() {
680 | // This test uses the Sage script `ristretto.sage` located in the
681 | // `curve25519-dalek` repository in order to get test vectors of the
682 | // ristretto_elligator algorithm.
683 | let expected_point = RistrettoPoint(EdwardsPoint {
684 | X: FieldElement([
685 | 520984263488427,
686 | 2866053035698784,
687 | 356812350072736,
688 | 1177086814167286,
689 | 17585355348321,
690 | ]),
691 | Y: FieldElement([
692 | 2224110940152212,
693 | 767723869121786,
694 | 2519083920383090,
695 | 3478258567033985,
696 | 6072297619626,
697 | ]),
698 | Z: FieldElement([1, 0, 0, 0, 0]),
699 | T: FieldElement([
700 | 3761248848988017,
701 | 3474827148739807,
702 | 3137090891116602,
703 | 1521420215868592,
704 | 8052069914602,
705 | ]),
706 | });
707 | assert!(expected_point.is_valid().unwrap_u8() == 1u8);
708 |
709 | let raw_bytes =
710 | hex::decode("2e2d7c6f887c81c1593f32e2fa31a7b65d4fbbf38f8ab3045ead22fc45743219")
711 | .unwrap();
712 | let mut bytes = [0u8; 32];
713 | bytes.copy_from_slice(&raw_bytes);
714 | let point_from_ellig =
715 | RistrettoPoint::elligator_ristretto_flavor(&FieldElement::from_bytes(&bytes));
716 |
717 | assert!(point_from_ellig.0.is_valid().unwrap_u8() == 1u8);
718 | assert!(point_from_ellig == expected_point);
719 | assert!(point_from_ellig.compress() == expected_point.compress())
720 | }
721 | }
722 |
--------------------------------------------------------------------------------
/src/scalar.rs:
--------------------------------------------------------------------------------
1 | //! A `Scalar` represents an element of the finite field
2 | //! modulo `2^249 - 15145038707218910765482344729778085401`.
3 | //!
4 | //! The `Scalar` type is an alias for one of the backend
5 | //! implementations.
6 | //!
7 | //! `ConstantTimeEq` and `PartialEq` traits have been implemented
8 | //! here since they will be the samme across all of the different
9 | //! backends.
10 | //!
11 | //! Here it is also defined the `Ristretto255Scalar` type,
12 | //! which is a type-alias for the curve25519-dalek Scalar Struct.
13 | //!
14 | //! # Examples
15 | //! ```rust
16 | //! use zerocaf::scalar::Scalar;
17 | //! use zerocaf::traits::ops::*;
18 | //!
19 | //! // You can create a Scalar from a byte-array as follows:
20 | //! let a = Scalar::from_bytes(&[0u8;32]);
21 | //!
22 | //! // You ca also create a Scalar from an uint type as follows:
23 | //! let b = Scalar::from(43325u128);
24 | //! let c = Scalar::from(86650u64);
25 | //!
26 | //! // The last way of creating a Scalar it by calling the
27 | //! // constructor. THIS IS NOT RECOMMENDED since ANY checks about
28 | //! // the correctness of the input will be done. It can be done as
29 | //! // follows:
30 | //! let d: Scalar = Scalar([0, 1, 0, 0, 0]); // d = 2^52.
31 | //! assert!(d == Scalar::two_pow_k(52u64));
32 | //!
33 | //! // All of the basuc modular operations are implemented
34 | //! // for Scalar type:
35 | //! let mut res = a + b; // Performs a + b (mod l).
36 | //! res = a - b; // Performs a - b (mod l).
37 | //! res = c * d; // Performs c * d (mod l).
38 | //! res = a.square(); // Performs a^2 (mod l).
39 | //! res = -&a; // Performs Negation over the modulo l.
40 | //!
41 | //! // Dividing even Scalars by two is recommended through the `Half`
42 | //! // trait implmementation since it's much faster.
43 | //! if a.is_even() {
44 | //! let half_c = c.half(); // This will panic if a isn't even.
45 | //! assert!(half_c == b);
46 | //! }
47 | //!
48 | //! // You can export your `Scalar` as an slice of 32 bytes in Little
49 | //! // Endian encoding by:
50 | //! let d_bytes: [u8; 32] = d.to_bytes();
51 | //! ```
52 | //!
53 | //!
54 | //!
55 | //! `PartialOrd`, `Ord`, `PartialEq` and `Eq` are also implemented for
56 | //! `Scalar` type.
57 | //!
58 | //! All `std::core::ops traits -> (Add, Sub, Mul)` are implemented
59 | //! for both, `&Scalar` and `Scalar`.
60 |
61 | use crate::backend;
62 |
63 | use subtle::Choice;
64 | use subtle::ConstantTimeEq;
65 |
66 | use rand::{CryptoRng, Rng};
67 |
68 | #[cfg(feature = "u64_backend")]
69 | pub use backend::u64::scalar::*;
70 | /// A `Scalar` represents an element of the field generated by
71 | /// the prime of the sub-group: `2^249 - 15145038707218910765482344729778085401`.
72 | ///
73 | /// This is a type alias for one of the Scalar types in the `backend`
74 | /// module.
75 | #[cfg(feature = "u64_backend")]
76 | pub type Scalar = backend::u64::scalar::Scalar;
77 |
78 | impl PartialEq for Scalar {
79 | fn eq(&self, other: &Scalar) -> bool {
80 | self.ct_eq(other).unwrap_u8() == 1u8
81 | }
82 | }
83 |
84 | impl ConstantTimeEq for Scalar {
85 | /// Test equality between two `Scalar`s. Since the
86 | /// internal representation is not canonical, the field elements
87 | /// are normalized to wire format before comparison.
88 | fn ct_eq(&self, other: &Scalar) -> Choice {
89 | self.to_bytes().ct_eq(&other.to_bytes())
90 | }
91 | }
92 |
93 | impl Eq for Scalar {}
94 |
95 | impl Scalar {
96 | /// Generate a valid Scalar choosen uniformly using user-
97 | /// provided rng.
98 | ///
99 | /// By `rng` we mean any Rng that implements: `Rng` + `CryptoRng`.
100 | pub fn random(rand: &mut T) -> Scalar
101 | where
102 | T: Rng + CryptoRng,
103 | {
104 | let mut bytes = [0u8; 32];
105 | rand.fill_bytes(&mut bytes);
106 | // Ensure that the value is lower than `L`.
107 | bytes[31] &= 0b0000_0001;
108 | Scalar::from_bytes(&bytes)
109 | }
110 | }
111 |
112 | /// This is a type alias for the Scalar type in the `curve25519-dalek` lib.
113 | pub type Ristretto255Scalar = curve25519_dalek::scalar::Scalar;
114 |
--------------------------------------------------------------------------------
/src/traits.rs:
--------------------------------------------------------------------------------
1 | //! Module for Public Trait implementations.
2 |
3 | use subtle::Choice;
4 |
5 | /// Gives the Identity element for the
6 | /// type which it has been implemented on.
7 | ///
8 | /// This trait is implemented following the rules that
9 | /// mandate over the Type that is being implemented.
10 | pub trait Identity {
11 | #[must_use]
12 | /// Returns the identity element for the implemented
13 | /// type, following it's mathematical rules.
14 | fn identity() -> Self;
15 | }
16 |
17 | /// This trait pretends to be a verification in ct_time
18 | /// about a point correctness.
19 | ///
20 | /// This is done through checking that the (X, Y) coordinates
21 | /// of the point are valid and satisfy the curve equation.
22 | pub trait ValidityCheck {
23 | #[must_use]
24 | /// Checks the point coordinates agains the curve equation
25 | /// to validate that the point relies on the curve and its
26 | /// valid.
27 | ///
28 | /// # Returns
29 | /// - `Choice(0)` if the point isn't a valid point.
30 | /// - `Choice(1)` if the point is valid.
31 | fn is_valid(&self) -> Choice;
32 | }
33 |
34 | pub mod ops {
35 | use super::*;
36 |
37 | /// Trait that represents the `^2` operation for any
38 | /// kind of element on the library.
39 | ///
40 | /// This trait is implemented following the rules that
41 | /// mandate over the Type that is being implemented.
42 | pub trait Square {
43 | type Output;
44 |
45 | #[must_use]
46 | /// Returns the square of the input: `x^2`.
47 | fn square(self) -> Self::Output;
48 | }
49 |
50 | /// Trait that represents the Point doubling operation
51 | /// for any type of Point that is used on the lib.
52 | ///
53 | /// This trait is implemented following the rules that
54 | /// mandate over the Type that is being implemented.
55 | pub trait Double {
56 | type Output;
57 |
58 | #[must_use]
59 | /// Performs the point-doubling operation over the
60 | /// coordinates which this trait has been implemented
61 | /// for.
62 | fn double(self) -> Self::Output;
63 | }
64 |
65 | /// Trait that represents the `/2` operation for any
66 | /// kind of element on the library.
67 | ///
68 | /// This is a more performant way of performing the
69 | /// division by 2 that dividing by 2 with the `Div`
70 | /// trait implementation.
71 | ///
72 | /// This trait is implemented following the rules that
73 | /// mandate over the Type that is being implemented.
74 | pub trait Half {
75 | type Output;
76 |
77 | #[must_use]
78 | /// Returns the half of the input: `x/2`.
79 | fn half(self) -> Self::Output;
80 | }
81 |
82 | /// Trait that represents the modular exponentiation
83 | /// operation, ie.`a ^ b (mod l)`, for any
84 | /// kind of element on the library (except points).
85 | ///
86 | /// This trait is implemented following the rules that
87 | /// mandate over the Type that is being implemented.
88 | pub trait Pow {
89 | type Output;
90 |
91 | #[must_use]
92 | /// Returns `a^b (mod l)`.
93 | fn pow(self, exp: T) -> Self::Output;
94 | }
95 |
96 | pub trait ModSqrt {
97 | type Output;
98 |
99 | #[must_use]
100 | /// Performs the modular Square Root operation over a finite
101 | /// field ie. `sqrt(x) (mod l)`.
102 | ///
103 | /// With the given `Choice`, the impl is able to provide the
104 | /// result that corresponds to the positive or negative sign choosen.
105 | ///
106 | /// # Returns
107 | ///
108 | /// `Some(symb_choosen_result)` if the input is a QR for the prime modulo.
109 | /// Otherways it returns `None`
110 | fn mod_sqrt(self, choice: Choice) -> Self::Output;
111 | }
112 |
113 | pub trait InvSqrt {
114 | type Output;
115 |
116 | #[must_use]
117 | /// Performs the Inverse Square root of a given value.
118 | ///
119 | /// This operation returns always the positive result of the
120 | /// modular sqrt, understanding positive as the definition that
121 | /// appears on the Decaf paper: 0 < result < (P - 1)/2.
122 | fn inv_sqrt(self) -> Self::Output;
123 | }
124 |
125 | pub trait SqrtRatioI {
126 | type Output;
127 |
128 | #[must_use]
129 | /// Using the same trick as in ed25519 decoding, we merge the
130 | /// inversion, the square root, and the square test.AsMut
131 | ///
132 | /// The first part of the return value signals whether u/v was square,
133 | /// and the second part contains a square root.
134 | /// Specifically, it returns:
135 | ///
136 | ///- (true, +sqrt(u/v)) if v is nonzero and u/v is square;
137 | ///- (true, zero) if u is zero;
138 | ///- (false, zero) if v is zero and uuu is nonzero;
139 | ///- (false, +sqrt(i*u/v)) if u/v is nonsquare (so iu/v is square).
140 | fn sqrt_ratio_i(&self, v: T) -> Self::Output;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/tools/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "param_translator"
3 | version = "0.1.0"
4 | authors = ["CPerez19 "]
5 | edition = "2018"
6 |
7 | [dependencies]
8 | num-bigint = "0.2.2"
9 | num = "0.2.0"
10 | num-traits = "0.2.6"
--------------------------------------------------------------------------------
/tools/kalinski_inv.py:
--------------------------------------------------------------------------------
1 |
2 | import math
3 |
4 | def random_prime(bound):
5 | warnings.simplefilter('ignore')
6 | chck = False
7 | while chck == False:
8 | p = random.randrange(bound>>1, bound)
9 | chck = pyprimes.isprime(p)
10 | warnings.simplefilter('default')
11 | return p
12 |
13 | def fieldElement(a):
14 | f0 = a % pow(2,52)
15 | a = a / pow(2,52)
16 | f1 = a % pow(2,52)
17 | a = a / pow(2,52)
18 | f2 = a % pow(2,52)
19 | a = a / pow(2,52)
20 | f3 = a % pow(2,52)
21 | a = a / pow(2,52)
22 | f4 = a % pow(2,52)
23 | arr = [f0, f1, f2, f3, f4]
24 | return '[' + ', '.join([str(x) for x in arr]) + ']'
25 |
26 |
27 | def AlmostMontInv(x, p):
28 | u = p
29 | v = x
30 | r = 0
31 | s = 1
32 | k = 0
33 | while (v>0):
34 | if (u%2 == 0):
35 | u = u >> 1
36 | s = s << 1
37 | elif (v%2 == 0):
38 | v = v >> 1
39 | r = r << 1
40 | elif u > v:
41 | u = (u-v) >> 1
42 | r = r+s
43 | s = s << 1
44 | else:
45 | v = (v-u) >> 1
46 | s = r+s
47 | r = r << 1
48 | k += 1
49 | #print('Values on iteration: ' + str(k) + ':')
50 | #print('r = ' + str(fieldElement(r)))
51 | #print('s = ' + str(fieldElement(s)))
52 | #print('v = ' + str(fieldElement(v)))
53 | #print('u = ' + str(fieldElement(u)))
54 |
55 | if r>p:
56 | r = r-p
57 |
58 | return p-r, k
59 |
60 |
61 | def phase2(r, k):
62 | for i in range(0, k-253):
63 | if (r % 2 == 0):
64 | r = (r >> 1) % p
65 | else:
66 | r = (r+p) >> 1
67 | #print('r on iter: ' + str(i) + '= ' + str(r))
68 | print('iter: ' + str(i) + ': FieldElement(' + fieldElement(r) + ')')
69 | return r
70 |
71 | # random.seed(11) # for debug
72 |
73 | p = 7237005577332262213973186563042994240857116359379907606001950938285454250989
74 |
75 | # Input to change value to get the AlmostMontInv.
76 | a = 904625697166532776746648320197686575422163851717637391703244652875051672039
77 |
78 | ainv, k = AlmostMontInv(a, p)
79 | print('r:FieldElement' + str(fieldElement(ainv)))
80 | print('r:FieldElement' + str(ainv))
81 | print('k:' + str(k))
82 | print('p:' + str(fieldElement(p)))
83 | ainv = phase2(ainv, k)
84 |
85 | print(ainv, k)
86 | print('ainv:FieldElement' + str(fieldElement(ainv)))
87 |
--------------------------------------------------------------------------------
/tools/src/main.rs:
--------------------------------------------------------------------------------
1 | extern crate num_bigint;
2 | extern crate num;
3 |
4 | use num_bigint::BigUint;
5 | use num::{Zero, One, Integer, Num};
6 | use std::str::FromStr;
7 | use num_traits::cast::ToPrimitive;
8 | use num_traits::pow;
9 | use core::fmt::Debug;
10 |
11 |
12 |
13 | fn main() {
14 | /*Examples of function calls
15 | num_from_bytes_le(&[76, 250, 187, 243, 105, 92, 117, 70, 234, 124, 126, 180, 87, 149, 62, 249, 16, 149, 138, 56, 26, 87, 14, 76, 251, 39, 168, 74, 176, 202, 26, 84]);
16 |
17 | let res = to_field_elem_51(&"1201935917638644956968126114584555454358623906841733991436515590915937358637");
18 | println!("{:?}", res);
19 |
20 | let scalar_res = to_scalar_base_52(&"1201935917638644956968126114584555454358623906841733991436515590915937358637");
21 | println!("{:?}", res);
22 |
23 | hex_bytes_le("120193591763864495696812611458455545435862390684173399143651559091593735863735685683568356835683");
24 | from_radix_to_radix_10("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16u32);
25 |
26 | let m = BigUint::from_str("750791094644726559640638407699").unwrap();
27 | let x1 = BigUint::from_str("540019781128412936473322405310").unwrap();
28 | let x2 = BigUint::from_str("515692107665463680305819378593").unwrap();
29 |
30 | reduction(m, x1, x2).unwrap();
31 |
32 |
33 | let x = to_scalar_base_52("1809251394333065553493296640760748560207343510400633813116524750123642650623");
34 | println!("R: {:?}", x);
35 | let y = to_scalar_base_52("6145104759870991071742105800796537629880401874866217824609283457819451087098");
36 | println!("R: {:?}", y);
37 | let x_y_mont = to_scalar_base_52("532695731852302855127194384594826090862673352940952884676179882511233227548");
38 | println!("R: {:?}", x_y_mont);
39 | let x_y = to_scalar_base_52("890263784947025690345271110799906008759402458672628420828189878638015362081");
40 | println!("R: {:?}", x_y);
41 | let mont_x = to_scalar_base_52("658448296334113745583381664921721413881518248721417041768778176391714104386");
42 | println!("{:?}", mont_x);
43 | */
44 |
45 | let a = to_scalar_base_52("452312848583266388373324160190187140059081152887999797648174285421238281266");
46 | println!("{:?}", a);
47 |
48 | let a = to_scalar_base_52("452312848583266388373324160190187140051835877600158453279131187530910662656");
49 | println!("{:?}", a);
50 | }
51 |
52 | /// The num has to be positive! Otherways it will fail
53 | pub fn hex_bytes_le(num: &str) {
54 | let num: BigUint = BigUint::from_str(num).unwrap();
55 | println!("Encoding result -> {:x?}", num.to_bytes_le());
56 | }
57 |
58 | /// Prints a number in radix 10 given a reference of a slice of Little Endian bytes of it.
59 | pub fn num_from_bytes_le(num: &[u8]){
60 | println!("{}", BigUint::from_bytes_le(num));
61 | }
62 |
63 | /// Changes a number from radix X to radix 10
64 | pub fn from_radix_to_radix_10(num: &str, radix: u32) {
65 | println!("{}",BigUint::from_str_radix(num, radix).unwrap());
66 | }
67 |
68 | /// Gets a number as a &str and encodes it like a FieldElement51 representation of zerocaf repo.
69 | pub fn to_field_elem_51(num: &str) -> [u64; 5] {
70 | let mut resp_as_array = [0u64;5];
71 | let mut response = vec!();
72 | let two_pow_51 = BigUint::from_str("2251799813685248").unwrap();
73 | let mut num = BigUint::from_str(num).unwrap();
74 |
75 | for _i in 0..5 {
76 | response.push(&num % &two_pow_51);
77 | num = &num / &two_pow_51;
78 | }
79 |
80 | let mut res2: Vec = response.iter().map(|x| u64::from_str(&x.to_str_radix(10u32)).unwrap()).collect();
81 | resp_as_array.swap_with_slice(&mut res2);
82 | resp_as_array
83 | }
84 |
85 | /// Gets a number as a &str and encodes it like a Scalar representation of zerocaf repo.
86 | pub fn to_scalar_base_52(num: &str) -> [u64; 5] {
87 | let mut resp_as_array = [0u64;5];
88 | let mut response = vec!();
89 | let two_pow_52 = BigUint::from_str("4503599627370496").unwrap();
90 | let mut num = BigUint::from_str(num).unwrap();
91 |
92 | for _i in 0..5 {
93 | response.push(&num % &two_pow_52);
94 | num = &num / &two_pow_52;
95 | }
96 |
97 | let mut res2: Vec = response.iter().map(|x| u64::from_str(&x.to_str_radix(10u32)).unwrap()).collect();
98 | resp_as_array.swap_with_slice(&mut res2);
99 | resp_as_array
100 | }
101 |
102 | /// Gets a Scalar in base 52 and transforms it into a normal representation
103 | pub fn from_scalar_base_52(limbs: &[u64; 5]) -> () {
104 | let mut res: BigUint = BigUint::zero();
105 | let two_pow_52 = BigUint::from_str("4503599627370496").unwrap();
106 | for i in 0..5 {
107 | res = res + (pow(two_pow_52.clone(), i) * limbs[i]);
108 | }
109 | println!("{}", res)
110 | }
111 |
112 | /// Gets a FieldElement in base 51 and transforms it into a normal representation
113 | pub fn from_field_elem_base_51(limbs: &[u64; 5]) -> () {
114 | let mut res: BigUint = BigUint::zero();
115 | let two_pow_51 = BigUint::from_str("2251799813685248").unwrap();
116 | for i in 0..5 {
117 | res = res + (pow(two_pow_51.clone(), i) * limbs[i]);
118 | }
119 | println!("{}", res)
120 | }
121 |
122 | /// Montgomery struct
123 | #[derive(Debug)]
124 | pub struct Montgomery {
125 | pub BASE: BigUint,
126 | pub m: BigUint,
127 | pub rrm: BigUint,
128 | pub n: i32
129 | }
130 |
131 | impl Montgomery {
132 | pub fn new(m: BigUint) -> Result {
133 | if m < BigUint::zero() || m.is_even() {
134 | Err("Invalid input!")
135 | } else {
136 | let mont = Montgomery {
137 | BASE: BigUint::from(2u32),
138 | m: m.clone(),
139 | n: m.bits() as i32,
140 | rrm: (BigUint::one() << (m.bits() * 2)) % m
141 | };
142 | return Ok(mont)
143 | }
144 | }
145 |
146 | pub fn reduce(&self, prop: BigUint) -> BigUint {
147 | let mut a: BigUint = prop.clone();
148 | for i in 0..self.n {
149 | if !a.is_even() {a+=self.m.clone()}
150 | a = a.clone() >> 1;
151 | }
152 | if a >= self.m {a -= self.m.clone()}
153 | a
154 | }
155 | }
156 |
157 | pub fn reduction(m: BigUint, x1: BigUint, x2: BigUint) -> Result<(), &'static str> {
158 | let mont = Montgomery::new(m.clone()).unwrap();
159 | let t1 = x1.clone() * mont.rrm.clone();
160 | let t2 = x2.clone() * mont.rrm.clone();
161 |
162 | let r1 = mont.reduce(t1.clone());
163 | let r2 = mont.reduce(t2.clone());
164 |
165 | let r = BigUint::one() << mont.n.clone() as usize;
166 | println!("b = {}\n", mont.BASE);
167 | println!("n = {}\n", mont.n);
168 | println!("r = {}\n", r);
169 | println!("m = {}\n", m);
170 | println!("t1 = {}\n", t1);
171 | println!("t2 = {}\n", t2);
172 | println!("r1 = {}\n", r1);
173 | println!("r2 = {}\n", r2);
174 | println!("Original x1: {}\n", x1.clone());
175 | println!("Recovered from r1: {}\n", mont.reduce(r1.clone()));
176 | println!("Original x2: {}\n", x2.clone());
177 | println!("Recovered from r2: {}\n", mont.reduce(r2.clone()));
178 | println!("Montgomery computation of x1 ^ x2 mod m :");
179 | let prod = x1.modpow(&x2, &mont.m);
180 |
181 | println!("{}\n", prod);
182 |
183 | Ok(())
184 | }
185 |
186 | pub fn phase1(input: &BigUint) -> BigUint {
187 | let p = BigUint::from_str("7237005577332262213973186563042994240832148273380272487819684194273658967345").unwrap();
188 | let mut u = p.clone();
189 | let mut v = input.clone();
190 | let mut r = BigUint::zero();
191 | let mut s = BigUint::one();
192 | let two = &s + &s;
193 | let mut k: u64 = 0;
194 | while v > BigUint::zero() {
195 |
196 | match(u.is_even(), v.is_even(), u > v, v >= u) {
197 | // u is even
198 | (true, _, _, _) => {
199 |
200 | u = &u / &two;
201 | s = (&s * &two);
202 | },
203 | // u isn't even but v is even
204 | (false, true, _, _) => {
205 |
206 | v = &v / &two;
207 | r = (&r * &two);
208 | },
209 | // u and v aren't even and u > v
210 | (false, false, true, _) => {
211 |
212 | u = (&u - &v);
213 | u = &u / &two;
214 | r = (&r + &s);
215 | s = (&s * &two);
216 | },
217 | // u and v aren't even and v > u
218 | (false, false, false, true) => {
219 |
220 | v = (&v - &u);
221 | v = &v / &two;
222 | s = (&r + &s);
223 | r = (&r * &two);
224 | },
225 | (false, false, false, false) => panic!("InverseMod does not exist"),
226 | }
227 | k+=1;
228 | println!("Values on iteration: {}: \nr = {:?}\ns = {:?}\nv = {:?}\nu = {:?}", k, to_scalar_base_52(&r.to_str_radix(10)), to_scalar_base_52(&s.to_str_radix(10)),to_scalar_base_52(&v.to_str_radix(10)),to_scalar_base_52(&u.to_str_radix(10)));
229 | }
230 | if r >= p {
231 | println!("Inside if: {:?}", to_scalar_base_52(&(&r - &p).to_str_radix(10)));
232 | r = &r - &p;
233 | }
234 | println!("Outside if: {}", (&p - &r));
235 | &p - &r
236 | }
237 |
238 |
239 | pub struct EdwardsPoint {
240 | pub X: [u64; 5],
241 | pub Y: [u64; 5],
242 | pub Z: [u64; 5],
243 | pub T: [u64; 5]
244 | }
245 |
246 | impl Debug for EdwardsPoint {
247 | fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
248 | write!(f, "
249 | EdwardsPoint {{
250 | X: FieldElement({:?}),
251 | Y: FieldElement({:?}),
252 | Z: FieldElement({:?}),
253 | T: FieldElement({:?})
254 | }};", self.X, self.Y, self.Z, self.T)
255 | }
256 | }
257 |
258 |
259 |
260 | impl EdwardsPoint {
261 |
262 | pub fn new(x: &str, y: &str, z: &str, t: &str) -> EdwardsPoint {
263 |
264 | let mut res: EdwardsPoint = EdwardsPoint{
265 | X: [0u64; 5],
266 | Y: [0u64; 5],
267 | Z: [0u64; 5],
268 | T: [0u64; 5]
269 | };
270 | res.X = to_scalar_base_52(x);
271 | res.Y = to_scalar_base_52(y);
272 | res.Z = to_scalar_base_52(z);
273 | res.T = to_scalar_base_52(t);
274 |
275 | res
276 | }
277 | }
278 |
--------------------------------------------------------------------------------
/tools/tonelli.py:
--------------------------------------------------------------------------------
1 | def legendre_symbol(a, p):
2 | """
3 | Legendre symbol
4 | Define if a is a quadratic residue modulo odd prime
5 | http://en.wikipedia.org/wiki/Legendre_symbol
6 | """
7 | ls = pow(a, (p - 1)/2, p)
8 | if ls == p - 1:
9 | return -1
10 | return ls
11 |
12 |
13 | def prime_mod_sqrt(a, p):
14 | """
15 | Square root modulo prime number
16 | Solve the equation
17 | x^2 = a mod p
18 | and return list of x solution
19 | http://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm
20 | """
21 | a %= p
22 |
23 | # Simple case
24 | if a == 0:
25 | return [0]
26 | if p == 2:
27 | return [a]
28 |
29 | # Check solution existence on odd prime
30 | if legendre_symbol(a, p) != 1:
31 | return []
32 |
33 | # Simple case
34 | if p % 4 == 3:
35 | x = pow(a, (p + 1)/4, p)
36 | return [x, p-x]
37 |
38 | # Factor p-1 on the form q * 2^s (with Q odd)
39 | q, s = p - 1, 0
40 | while q % 2 == 0:
41 | s += 1
42 | q //= 2
43 |
44 | # Select a z which is a quadratic non resudue modulo p
45 | z = 1
46 | while legendre_symbol(z, p) != -1:
47 | z += 1
48 | c = pow(z, q, p)
49 |
50 | # Search for a solution
51 | x = pow(a, (q + 1)/2, p)
52 | t = pow(a, q, p)
53 | m = s
54 | while t != 1:
55 | # Find the lowest i such that t^(2^i) = 1
56 | i, e = 0, 2
57 | for i in xrange(1, m):
58 | if pow(t, e, p) == 1:
59 | break
60 | e *= 2
61 |
62 | # Update next value to iterate
63 | b = pow(c, 2**(m - i - 1), p)
64 | x = (x * b) % p
65 | t = (t * b * b) % p
66 | c = (b * b) % p
67 | m = i
68 |
69 | return [x, p-x]
70 |
71 | y = 39450438318983875225554878125429420291626370862048309987484807859947766635845
72 | l = 7237005577332262213973186563042994240857116359379907606001950938285454250989
73 |
74 | print(prime_mod_sqrt(y,l))
75 |
--------------------------------------------------------------------------------