47 one_ninth = one_third**2
48 one_by_27 = one_third * one_ninth
50 A_times_one_third = A * one_third
52 t = (Fq(3) - A_squared) * one_ninth
53 r = 16 * (A_squared * A) * one_by_27
54 s = 8 * A_times_one_third
59 setup[
'curt'](-2 * A_squared + 8)
64 s0 = setup[
'sqrt'](r - s)
67 s1 = setup[
'sqrt'](v + u * i0)
68 s2 = setup[
'sqrt'](v - u * i0)
71 z.append((-s0 + s1) * one_half)
72 z.append((-s0 - s1) * one_half)
73 z.append((s0 + s2) * one_half)
74 z.append((s0 - s2) * one_half)
76 x = [zk-A_times_one_third
for zk
in z]
82 p = setup[
'Fq'].characteristic()
85 s = hashlib.shake_256()
87 length = int(floor((p.bit_length() / log(3, 2)) + 0.5))
88 digest = s.hexdigest(p.bit_length() // 8)
89 path = base_repr(int(digest, 16), base=3)[:length]
92 print(
'\nCGL Hash function over the 3-isogeny graph (CGLHash3)')
93 print(f
'Symmetric primitive:\t{s.name}')
94 print(f
'Message digest size:\t{len(digest) // 2} bytes')
95 print(f
'Random path of size:\t{len(path)} steps')
99 assert(
not (xP**2 * (3 * xP**2 + 4 * setup[
'A'] * xP + 6) - 1))
105 a1, a3 =
random_walk3(a1, a3, [ int(b)
for b
in path ], setup)
106 return EllipticCurve(setup[
'Fq'], [a1, 0, a3, -5 * a1 * a3, -a1**3 * a3 - 7 * a3**2]).j_invariant()