1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
/*
* ecgen, tool for generating Elliptic curve domain parameters
* Copyright (C) 2017 J08nY
*/
#include "field.h"
#include "io/input.h"
#include "io/output.h"
#include "math/poly.h"
static GEN field_primer(unsigned long bits) { return random_prime(bits); }
static GEN field_binaryr(unsigned long bits) {
if (poly_exists(bits)) {
return poly_find_gen(bits);
} else {
fprintf(err,
"Unable to find a suitable binary field. Use an explicit one.");
exit(1);
}
}
GENERATOR(field_gen_random) {
switch (cfg->field) {
case FIELD_PRIME:
curve->field = field_primer(cfg->bits);
return 1;
case FIELD_BINARY:
curve->field = field_binaryr(cfg->bits);
return 1;
default:
return INT_MIN; /* NOT REACHABLE */
}
}
GENERATOR(field_gen_input) {
pari_sp ltop = avma;
switch (cfg->field) {
case FIELD_PRIME: {
GEN p = input_prime("p:", cfg->bits);
if (equalii(p, gen_m1)) {
avma = ltop;
return 0;
}
curve->field = p;
return 1;
}
case FIELD_BINARY: {
GEN m = input_short("m:");
if (!equalis(m, cfg->bits)) {
avma = ltop;
return 0;
}
GEN e1 = input_short("e1:");
if (equalii(e1, gen_m1)) {
avma = ltop;
return 0;
}
GEN e2 = input_short("e2:");
if (equalii(e2, gen_m1)) {
avma = ltop;
return 0;
}
GEN e3 = input_short("e3:");
if (equalii(e3, gen_m1)) {
avma = ltop;
return 0;
}
if (isintzero(e1) && isintzero(e2) && isintzero(e3)) {
fprintf(err, "At least one exponent must be nonzero.\n");
avma = ltop;
return 0;
}
GEN v = gtovec0(gen_0, cfg->bits + 1);
gel(v, itos(m) + 1) = gen_1;
if (gsigne(e1) == 1) gel(v, itos(e1) + 1) = gen_1;
if (gsigne(e2) == 1) gel(v, itos(e2) + 1) = gen_1;
if (gsigne(e3) == 1) gel(v, itos(e3) + 1) = gen_1;
gel(v, 1) = gen_1;
GEN poly = gmul(gtopolyrev(v, -1), gmodulss(1, 2));
if (!isirreducible(poly)) {
fprintf(err, "Polynomial is reducible.\n");
avma = ltop;
return 0;
}
curve->field = gerepilecopy(ltop, ffgen(poly, -1));
return 1;
}
default:
return INT_MIN; /* NOT REACHABLE */
}
}
static GEN field = NULL;
static curve_t *curve_field = NULL;
GENERATOR(field_gen_once) {
if (field && curve_field == curve) {
curve->field = gcopy(field);
return 1;
}
int inp = field_gen_input(curve, args, state);
if (inp > 0) {
field = gclone(curve->field);
curve_field = curve;
return 1;
} else {
return 0;
}
}
GEN field_params(GEN field) {
pari_sp ltop = avma;
if (typ(field) == t_INT) {
return gtovec(field);
}
GEN out = gtovec0(gen_0, 4);
long j = 1;
long l2 = glength(member_mod(field)) - 1;
{
pari_sp btop = avma;
for (long i = l2; i > 0; --i) {
GEN c = polcoeff0(member_mod(field), i, -1);
if (cmpis(c, 0) != 0) {
gel(out, j) = stoi(i);
j++;
}
gerepileall(btop, 2, &out, &c);
}
}
return gerepilecopy(ltop, out);
}
GEN field_elementi(GEN element) {
switch (typ(element)) {
case t_INT:
return element;
case t_INTMOD:
return lift(element);
case t_FFELT: {
pari_sp ltop = avma;
GEN coeffs = FF_to_FpXQ(element);
GEN vec = gtovec(coeffs);
GEN n = fromdigits(vec, stoi(2));
return gerepilecopy(ltop, n);
}
default:
pari_err_TYPE("field_elementi", element);
return NULL; /* NOT REACHABLE */
}
}
GEN field_ielement(GEN field, GEN in) {
switch (typ(field)) {
case t_INT:
return Fp_to_mod(in, field);
case t_FFELT: {
pari_sp ltop = avma;
GEN coeffs = digits(in, gen_2);
GEN poly = gtopoly(coeffs, -1);
return gerepilecopy(ltop, Fq_to_FF(poly, field));
}
default:
pari_err_TYPE("field_ielement, field is unknown type. ", field);
return gen_m1; /* NOT REACHABLE */
}
}
|