39 content_str =
"static const uint64_t " + var + f
"[{length}] = {{\n"
41 for i
in range(1, p_words + 1):
42 if ((i - 1) % 4) == 0:
43 content_str = content_str +
"\t"
44 p_word.append(pp % 2 ** k)
45 if (i % 4) != 0
and (i != p_words):
46 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
", "
49 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
",\n"
51 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
"\n"
54 content_str = content_str +
"};\n"
55 print(f
'{content_str}')
62 content_str =
"static const uint64_t " + var + f
"[2 * {length}] = {{\n"
64 for i
in range(1, p_words + 1):
65 if ((i - 1) % 4) == 0:
66 content_str = content_str +
"\t"
67 p_word.append(pp % 2 ** k)
68 if (i % 4) != 0
and (i != p_words):
69 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
", "
71 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
",\n"
75 for i
in range(1, p_words + 1):
76 if ((i - 1) % 4) == 0:
77 content_str = content_str +
"\t"
78 p_word.append(pp % 2 ** k)
79 if (i % 4) != 0
and (i != p_words):
80 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
", "
83 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
",\n"
85 content_str = content_str +
"0x{:X}".format(p_word[i - 1]) +
"\n"
88 content_str = content_str +
"};\n"
89 print(f
'{content_str}')
93 pbits = p.bit_length()
94 pwords = (pbits + 63) // 64
95 montgomery_one = 2 ** (64 * pwords) % p
97 p_minus_one_halves = (p - 1) // 2
98 p_minus_3_quarters = (p - 3) // 4
102 Rx = PolynomialRing(fp, name=
"x")
104 fp2 = fp.extension(x**2 + 1,
'i')
109 a1 = a ** p_minus_3_quarters
113 alpha_conjugated = alpha.conjugate()
115 a0 = alpha * alpha_conjugated
127 b = alpha ** p_minus_one_halves
132 r3 = ZZ(3).inverse_mod(N3)
135 correct, square_root_of_three = fp2_issquare(
fp2(-3))
137 assert(square_root_of_three**2 == -3)
138 zeta3 = (-1 + square_root_of_three) /
fp2(2)
140 return r3, (zeta3 * montgomery_one).list()
149 pbits = p.bit_length()
150 pbytes = (pbits + 7) // 8
151 pwords = (pbits + 63) // 64
154 pmask = hex((1 << 64) - 1);
156 pmask = hex((1 << pmask) - 1)
158 print(f
'// Parameters concerning P{pbits}\n')
159 print(f
'#ifndef SSEC_PARAMETERS_P{pbits}_H')
160 print(f
'#define SSEC_PARAMETERS_P{pbits}_H\n')
162 print(f
'#define FIELD_NAME\t\t\t"p{pbits}"')
163 print(f
'#define FIELD_BITS\t\t\t{pbits}')
164 print(f
'#define FIELD_BYTES\t\t\t{pbytes}')
165 print(f
'#define FIELD_64BITS_WORDS\t{pwords}')
166 print(f
'#define QFIELD_BYTES\t\t{2 * pbytes}')
167 print(f
'#define MASK_FIELD_ELEMENT\t{pmask}')
168 print(f
'#define SECURITY_BITS\t\t{l}\n')
170 trits = int(ceil((2.0 * l) / log(3.0, 2)))
171 print(f
'#define BIT_LENGTH_PATH\t\t{2 * l}')
172 print(f
'#define TRITLENGTH_PATH\t\t{trits}\n')
174 print(
"// Field characteristic p")
175 word_extractor(p, pwords,
"FIELD_64BITS_WORDS",
"FIELD_CHARACTERISTIC")
177 montgomery_one = 2 ** (64 * pwords) % p
178 print(
"// Neutral multiplicative in Montgomery domain: R = 2ᵉ mod p")
179 word_extractor(montgomery_one, pwords,
"FIELD_64BITS_WORDS",
"MONTGOMERY_CONSTANT_ONE")
180 print(
"// Montgomery constant R² = (2ᵉ)² mod p where e = 0 mod 64 s.t. 2ᵉ⁻⁶⁴ < p < 2ᵉ")
181 word_extractor((montgomery_one ** 2) % p, pwords,
"FIELD_64BITS_WORDS",
"MONTGOMERY_CONSTANT_R_SQUARED")
183 print(
"// Exponent constant required for field inversion: p - 2")
184 word_extractor(p - 2, pwords,
"FIELD_64BITS_WORDS",
"FIELD_INVERSION_EXPONENT")
186 print(
"// Exponent constant required for computing square-roots in GF(p): (p - 1) / 2")
187 word_extractor((p - 1) // 2, pwords,
"FIELD_64BITS_WORDS",
"SQUARE_ROOT_EXPONENT_12")
190 print(
"// Exponent constant required for computing square-roots in GF(p²): (p - 3) / 4")
191 word_extractor((p - 3) // 4, pwords,
"FIELD_64BITS_WORDS",
"SQUARE_ROOT_EXPONENT_34")
193 print(
"// Exponent constant required for computing square-roots in GF(p²): (p + 1) / 4")
194 word_extractor((p + 1) // 4, pwords,
"FIELD_64BITS_WORDS",
"SQUARE_ROOT_EXPONENT_14")
197 print(
"#define SSEC_CUBE_ROOT_OVER_FP")
198 print(
"// Exponent constant required for computing square-roots in GF(p): (2p - 1) / 3")
199 word_extractor((2*p - 1) // 3, pwords,
"FIELD_64BITS_WORDS",
"CUBE_ROOT_EXPONENT_213")
202 def l2r(a, exponent):
204 temporal = 1 * exponent
208 if (temporal % 2) == 1:
209 result = result * power;
212 temporal = temporal // 2
215 def is_quadratic_residue(a):
216 p = a.parent().characteristic()
217 q = a.parent().cardinality()
221 for index
in range(0, m, 1):
224 return not (l2r(c, (p - 1) // 2) - 1)
228 Rx = PolynomialRing(Fp, name=
"x")
232 Fq = Fp.extension(X**2 + 1,
'i')
235 Rx = PolynomialRing(Fq, name=
"x")
238 rootq2_squared = rootq
239 while is_quadratic_residue(-rootq2_squared):
242 exponent1 = (q - 9) // 16
243 exponent2 = (q - 9) // 8
245 constant3 = l2r(rootq2_squared, exponent2)
246 print(
"#define SSEC_KONG_ET_AL_S_ALGORITHM")
247 print(
"// Constant required in Kong et al.'s algorithm, d: quadratic non-residue")
248 word_extractor_twice((rootq2_squared * montgomery_one).list(), pwords,
"FIELD_64BITS_WORDS",
"SQUARE_ROOT_CONSTANT_D")
249 print(
"// Constant required in Kong et al.'s algorithm, t: d raised at the power (p² - 9) / 8")
250 word_extractor_twice((constant3 * montgomery_one).list(), pwords,
"FIELD_64BITS_WORDS",
"SQUARE_ROOT_CONSTANT_T")
251 print(
"// Exponent constant required for computing square-roots in GF(p²): (p² - 9) / 16")
252 e1words = (exponent1.bit_length() + 63) // 64
253 print(f
'#define SQUARE_ROOT_EXPONENT_BITS\t\t\t{exponent1.bit_length()}')
254 word_extractor(exponent1, e1words,
"2 * FIELD_64BITS_WORDS",
"SQUARE_ROOT_EXPONENT_916")
258 n3words = (n3.bit_length() + 63) // 64
259 print(
"// Exponent constant required for computing cube-roots")
260 print(f
'#define CUBE_ROOT_EXPONENT_BITS\t\t\t{n3.bit_length()}')
261 word_extractor(n3, n3words,
"2 * FIELD_64BITS_WORDS",
"CUBE_ROOT_EXPONENT")
262 print(
"// Cube root of unity in Montgomery domain")
265 montgomery_one = 2 ** (64 * pwords) % p
266 one_half = ZZ(2).inverse_mod(p)
267 word_extractor((one_half * montgomery_one) % p, pwords,
"FIELD_64BITS_WORDS",
"ONE_HALF")
268 one_third = ZZ(3).inverse_mod(p)
269 word_extractor((one_third * montgomery_one) % p, pwords,
"FIELD_64BITS_WORDS",
"ONE_THIRD")
270 one_ninth = (one_third**2) % p
271 word_extractor((one_ninth * montgomery_one) % p, pwords,
"FIELD_64BITS_WORDS",
"ONE_NINTH")
272 one_by_27 = (one_third * one_ninth) % p
273 word_extractor((one_by_27 * montgomery_one) % p, pwords,
"FIELD_64BITS_WORDS",
"ONE_BY_27")
275 print(f
'#endif // SSEC_PARAMETERS_P{pbits}_H')