143def print_parameters(a: int, c: int, l: int):
144
145 p = (2**a) * c - 1
146 assert p % 4 == 3
147
148
149 pbits = p.bit_length()
150 pbytes = (pbits + 7) // 8
151 pwords = (pbits + 63) // 64
152 pmask = pbits % 64
153 if pmask == 0:
154 pmask = hex((1 << 64) - 1);
155 else:
156 pmask = hex((1 << pmask) - 1)
157
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')
161
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')
169
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')
173
174 print("// Field characteristic p")
175 word_extractor(p, pwords, "FIELD_64BITS_WORDS", "FIELD_CHARACTERISTIC")
176
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")
182
183 print("// Exponent constant required for field inversion: p - 2")
184 word_extractor(p - 2, pwords, "FIELD_64BITS_WORDS", "FIELD_INVERSION_EXPONENT")
185
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")
188 q = p**2
189
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")
192
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")
195
196 if (p % 3 == 2):
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")
200
201 if (q % 16 == 9):
202 def l2r(a, exponent):
203
204 temporal = 1 * exponent
205 power = a * 1
206 result = 1
207 while temporal > 0:
208 if (temporal % 2) == 1:
209 result = result * power;
210 power = power**2
211
212 temporal = temporal // 2
213 return result
214
215 def is_quadratic_residue(a):
216 p = a.parent().characteristic()
217 q = a.parent().cardinality()
218 m = int(log(q, p))
219 b = 1 * a
220 c = 1
221 for index in range(0, m, 1):
222 c *= b
223 b = l2r(b, p)
224 return not (l2r(c, (p - 1) // 2) - 1)
225
226
227 Fp = GF(p)
228 Rx = PolynomialRing(Fp, name="x")
229 X = Rx.gens()[0]
230
231
232 Fq = Fp.extension(X**2 + 1, 'i')
233 rootq = Fq.gen()
235 Rx = PolynomialRing(Fq, name="x")
236
237
238 rootq2_squared = rootq
239 while is_quadratic_residue(-rootq2_squared):
240 rootq2_squared += 1
241
242 exponent1 = (q - 9) // 16
243 exponent2 = (q - 9) // 8
244
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")
255
256
257 n3, zeta3 = cube_root(p)
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")
263 word_extractor_twice(zeta3, pwords, "FIELD_64BITS_WORDS", "CUBE_ROOT_OF_UNITY")
264
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")
274
275 print(f'#endif // SSEC_PARAMETERS_P{pbits}_H')
276
277