Skip to content

Commit 0e9aa69

Browse files
committed
Add KSS curve generation.
1 parent 23c460d commit 0e9aa69

File tree

10 files changed

+114
-60
lines changed

10 files changed

+114
-60
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Tool for generating Elliptic curve domain parameters.
2222
- `-s / --ansi[=SEED]` Generate a curve from `SEED` (ANSI X9.62 verifiable procedure).
2323
- `-b / --brainpool[=SEED]`Generate a curve using the Brainpool verifiably pseudorandom algorithm from the original paper.
2424
- `--brainpool-rfc[=SEED]` Generate a curve using the Brainpool verifiably pseudorandom algorithm as per RFC 5639.
25-
- `-F / --family=FAMILY` Generate a pairing friendly curve from a curve family (e.g. "BN", "BLS12", "BLS24").
25+
- `-F / --family=FAMILY` Generate a pairing friendly curve from a curve family (e.g. "BN", "BLS12", "BLS24", "KSS16", "KSS18", "KSS36", "KSS40").
2626
- `--nums` Generate a curve using the NUMS procedure (as per draft-black-numscurves-02).
2727
- `--twist` Generate a twist of a given curve.
2828

src/exhaustive/exhaustive.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ static void exhaustive_ginit(gen_f *generators) {
148148
}
149149
generators[OFFSET_FIELD] = &family_gen_field;
150150
generators[OFFSET_A] = &gen_skip;
151-
if (cfg->family == FAMILY_KSS16) {
151+
if (cfg->family == FAMILY_KSS16 || cfg->family == FAMILY_KSS40) {
152152
generators[OFFSET_B] = &family_gen_equation_cm;
153153
} else {
154154
generators[OFFSET_B] = &family_gen_equation_iter;

src/exhaustive/family.c

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#include "cm/cm_any.h"
88
#include "gen/seed.h"
99
#include "misc/config.h"
10+
#include "util/bits.h"
1011
#include "util/random.h"
12+
#include "io/output.h"
1113

1214
#define FAMILIES (FAMILY_KSS40 + 1)
1315

@@ -17,49 +19,54 @@ static GEN rz_store[FAMILIES] = {0};
1719
static GEN tz_store[FAMILIES] = {0};
1820
static GEN D_store[FAMILIES] = {0};
1921

22+
// clang-format off
2023
void family_init() {
2124
pari_sp ltop = avma;
2225
nz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> z")));
23-
pz_store[FAMILY_BN] = gclone(closure_evalgen(
24-
compile_str("(z) -> 36*z^4 + 36*z^3 + 24*z^2 + 6*z + 1")));
25-
rz_store[FAMILY_BN] = gclone(closure_evalgen(
26-
compile_str("(z) -> 36*z^4 + 36*z^3 + 18*z^2 + 6*z + 1")));
27-
tz_store[FAMILY_BN] =
28-
gclone(closure_evalgen(compile_str("(z) -> 6*z + 1")));
26+
pz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 36*z^4 + 36*z^3 + 24*z^2 + 6*z + 1")));
27+
rz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 36*z^4 + 36*z^3 + 18*z^2 + 6*z + 1")));
28+
tz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 6*z + 1")));
2929
D_store[FAMILY_BN] = gclone(stoi(-3));
3030

3131
nz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z")));
32-
pz_store[FAMILY_BLS12] = gclone(closure_evalgen(
33-
compile_str("(z) -> (z - 1)^2 * (z^4 - z^2 + 1)/3 + z")));
34-
rz_store[FAMILY_BLS12] =
35-
gclone(closure_evalgen(compile_str("(z) -> z^4 - z^2 + 1")));
36-
tz_store[FAMILY_BLS12] =
37-
gclone(closure_evalgen(compile_str("(z) -> z + 1")));
32+
pz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> (z - 1)^2 * (z^4 - z^2 + 1)/3 + z")));
33+
rz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z^4 - z^2 + 1")));
34+
tz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z + 1")));
3835
D_store[FAMILY_BLS12] = gclone(stoi(-3));
3936

4037
nz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z")));
41-
pz_store[FAMILY_BLS24] = gclone(closure_evalgen(
42-
compile_str("(z) -> (z - 1)^2 * (z^8 - z^4 + 1)/3 + z")));
43-
rz_store[FAMILY_BLS24] =
44-
gclone(closure_evalgen(compile_str("(z) -> z^8 - z^4 + 1")));
45-
tz_store[FAMILY_BLS24] =
46-
gclone(closure_evalgen(compile_str("(z) -> z + 1")));
38+
pz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> (z - 1)^2 * (z^8 - z^4 + 1)/3 + z")));
39+
rz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z^8 - z^4 + 1")));
40+
tz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z + 1")));
4741
D_store[FAMILY_BLS24] = gclone(stoi(-3));
4842

49-
//TODO: This does not work...
50-
nz_store[FAMILY_KSS16] =
51-
gclone(closure_evalgen(compile_str("(z) -> 70*z + 25")));
52-
pz_store[FAMILY_KSS16] = gclone(closure_evalgen(
53-
compile_str("(z) -> (z^10 + 2*z^9 + 5*z^8 + 48*z^6 + 152*z^5 + 240*z^4 "
54-
"+ 625*z^2 + 2398*z + 3125)/980")));
55-
rz_store[FAMILY_KSS16] = gclone(
56-
closure_evalgen(compile_str("(z) -> (z^8 + 48*z^4 + 625)/61250")));
57-
tz_store[FAMILY_KSS16] =
58-
gclone(closure_evalgen(compile_str("(z) -> (2*z^5 + 41*z + 35)/35")));
59-
D_store[FAMILY_KSS16] = gclone(stoi(-1));
43+
nz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> 70*z + 25")));
44+
pz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> (z^10 + 2*z^9 + 5*z^8 + 48*z^6 + 152*z^5 + 240*z^4 + 625*z^2 + 2398*z + 3125)/980")));
45+
rz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> (z^8 + 48*z^4 + 625)/61250")));
46+
tz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> (2*z^5 + 41*z + 35)/35")));
47+
D_store[FAMILY_KSS16] = gclone(stoi(-4));
48+
49+
nz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> 42*z + 14")));
50+
pz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> (z^8 + 5*z^7 + 7*z^6 + 37*z^5 + 188*z^4 + 259*z^3 + 343*z^2 + 1763*z + 2401)/21")));
51+
rz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> (z^6 + 37*z^3 + 343)/343")));
52+
tz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> (z^4 + 16*z + 7)/7")));
53+
D_store[FAMILY_KSS18] = gclone(stoi(-3));
54+
55+
nz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> 777 * z + 287")));
56+
pz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> (z^14 - 4*z^13 + 7*z^12 + 683*z^8 - 2510*z^7 + 4781*z^6 + 117649*z^2 - 386569*z + 823543)/28749")));
57+
rz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> (z^12 + 683*z^6 + 117649)/161061481")));
58+
tz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> (2*z^7 + 757*z + 259)/259")));
59+
D_store[FAMILY_KSS36] = gclone(stoi(-3));
60+
61+
nz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> 2370*z + 1205")));
62+
pz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> (z^22 - 2*z^21 + 5*z^20 + 6232*z^12 - 10568*z^11 + 31160*z^10 + 9765625*z^2 - 13398638*z + 48828125)/1123380")));
63+
rz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> (z^16 + 8*z^14 + 39*z^12 + 112*z^10 - 79*z^8 + 2800*z^6 + 24375*z^4 + 125000*z^2 + 390625)/2437890625")));
64+
tz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> (2*z^11 + 6469*z + 1185)/1185")));
65+
D_store[FAMILY_KSS40] = gclone(stoi(-4));
6066

6167
avma = ltop;
6268
}
69+
// clang-format on
6370

6471
static seed_t *family_new_seed() {
6572
seed_t *result = seed_new();
@@ -70,21 +77,18 @@ static seed_t *family_new_seed() {
7077
GENERATOR(family_gen_seed_random) {
7178
curve->seed = family_new_seed();
7279
curve->seed->family.z = random_int(cfg->bits);
80+
if (random_bits(1)) {
81+
togglesign(curve->seed->family.z);
82+
}
83+
curve->seed->seed = bits_from_i(curve->seed->family.z);
7384
return 1;
7485
}
7586

7687
GENERATOR(family_gen_seed_input) {
77-
pari_sp ltop = avma;
7888
GEN inp = input_int("z:", cfg->bits);
79-
if (gequalm1(inp)) {
80-
avma = ltop;
81-
return 0;
82-
} else if (equalii(inp, gen_m2)) {
83-
avma = ltop;
84-
return INT_MIN;
85-
}
8689
curve->seed = family_new_seed();
8790
curve->seed->family.z = inp;
91+
curve->seed->seed = bits_from_i(curve->seed->family.z);
8892
return 1;
8993
}
9094

@@ -96,13 +100,11 @@ GENERATOR(family_gen_field) {
96100
avma = ltop;
97101
return -1;
98102
}
99-
printf("p");
100103
GEN rz = closure_callgen1(rz_store[cfg->family], n);
101104
if (typ(rz) != t_INT || !isprime(rz)) {
102105
avma = ltop;
103106
return -1;
104107
}
105-
printf("r");
106108
curve->field = gerepilecopy(ltop, pz);
107109
return 1;
108110
}

src/io/cli.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct argp_option cli_options[] = {
6363
{"nums", OPT_NUMS, 0, 0, "Generate a curve using the NUMS procedure.", 2},
6464
{"invalid", OPT_INVALID, "RANGE", OPTION_ARG_OPTIONAL, "Generate a set of invalid curves, for a given curve (using Invalid curve algorithm).", 2},
6565
{"twist", OPT_TWIST, 0, 0, "Generate a twist of a given curve.", 2},
66-
{"family", OPT_FAMILY, "NAME", 0, "Generate a curve from a curve family (e.g. BN, BLS12, BLS24, KSS)."},
66+
{"family", OPT_FAMILY, "NAME", 0, "Generate a curve from a curve family (e.g. BN, BLS12, BLS24, KSS16, KSS18, KSS36, KSS40).", 2},
6767

6868
{0, 0, 0, 0, "Generation options:", 3},
6969
{"random", OPT_RANDOM, "WHAT", OPTION_ARG_OPTIONAL, "Generate a random curve (using Random approach). "
@@ -294,16 +294,12 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
294294
} else if (strcasecmp(arg, "BLS24") == 0) {
295295
cfg->family = FAMILY_BLS24;
296296
} else if (strcasecmp(arg, "KSS16") == 0) {
297-
argp_failure(state, 1, 0, "Family not yet supported.");
298297
cfg->family = FAMILY_KSS16;
299298
} else if (strcasecmp(arg, "KSS18") == 0) {
300-
argp_failure(state, 1, 0, "Family not yet supported.");
301299
cfg->family = FAMILY_KSS18;
302300
} else if (strcasecmp(arg, "KSS36") == 0) {
303-
argp_failure(state, 1, 0, "Family not yet supported.");
304301
cfg->family = FAMILY_KSS36;
305302
} else if (strcasecmp(arg, "KSS40") == 0) {
306-
argp_failure(state, 1, 0, "Family not yet supported.");
307303
cfg->family = FAMILY_KSS40;
308304
} else {
309305
argp_failure(state, 1, 0, "Unknown curve family = %s", arg);

src/io/input.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ static GEN input_i(const char *prompt, unsigned long bits) {
3232
free(line);
3333
return gen_m1;
3434
}
35-
for (size_t i = 0, j = 0; (line[j] = line[i]); j += !isspace(line[i++]))
36-
;
35+
bool sign = line[0] == '-';
3736

3837
pari_sp ltop = avma;
39-
GEN in = strtoi(line);
38+
GEN in = strtoi(line + sign);
39+
if (sign) {
40+
togglesign(in);
41+
}
4042
free(line);
4143

4244
// check bitsize here

src/io/output.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,17 @@ static JSON_Value *output_jjson(curve_t *curve) {
8484
if (curve->seed && curve->seed->seed) {
8585
char *hex_str = bits_to_hex(curve->seed->seed);
8686
char *hex = try_calloc(strlen(hex_str) + 3);
87-
hex[0] = '0';
88-
hex[1] = 'x';
87+
if (curve->seed->seed->sign) {
88+
hex[0] = '-';
89+
hex[1] = '0';
90+
} else {
91+
hex[0] = '0';
92+
hex[1] = 'x';
93+
}
8994
strcat(hex, hex_str);
95+
if (curve->seed->seed->sign) {
96+
hex[2] = 'x';
97+
}
9098
json_object_set_string(root_object, "seed", hex);
9199
try_free(hex_str);
92100
try_free(hex);

src/misc/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
/**
1616
* @brief
1717
* @param bits
18+
* @param sign
1819
* @param bitlen
1920
* @param allocated
2021
*/
2122
typedef struct {
2223
unsigned char *bits;
24+
bool sign;
2325
size_t bitlen;
2426
size_t allocated;
2527
} bits_t;

src/util/bits.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ void bits_cpy(bits_t *dest, const bits_t *src) {
4444
memcpy(dest->bits, src->bits, src->allocated);
4545
dest->allocated = src->allocated;
4646
dest->bitlen = src->bitlen;
47+
dest->sign = src->sign;
4748
}
4849

4950
bits_t *bits_copy(const bits_t *bits) {
5051
bits_t *result = try_calloc(sizeof(bits_t));
52+
result->sign = bits->sign;
5153
result->bitlen = bits->bitlen;
5254
result->allocated = bits->allocated;
5355
if (bits->allocated != 0)
@@ -70,6 +72,7 @@ bits_t *bits_from_i(GEN i) {
7072
GEN bitvec = binary_zv(i);
7173
size_t bit_len = (size_t)glength(bitvec);
7274
bits_t *result = bits_new(bit_len);
75+
result->sign = signe(i) == -1;
7376
for (size_t j = 0; j < bit_len; ++j) {
7477
if (gel(bitvec, j + 1) == (GEN)1) {
7578
result->bits[j / 8] |= 1 << (7 - (j % 8));
@@ -84,6 +87,7 @@ bits_t *bits_from_i_len(GEN i, size_t bit_len) {
8487
GEN bitvec = binary_zv(i);
8588
size_t i_len = (size_t)glength(bitvec);
8689
bits_t *result = bits_new(bit_len);
90+
result->sign = signe(i) == -1;
8791
size_t offset = 0;
8892
if (i_len < bit_len) {
8993
offset = bit_len - i_len;
@@ -150,22 +154,53 @@ GEN bits_to_i(const bits_t *bits) {
150154
if (GET_BIT(bits->bits, i) != 0)
151155
result = addii(result, int2n(bits->bitlen - i - 1));
152156
}
157+
if (bits->sign) {
158+
setsigne(result, -1);
159+
}
153160
return gerepilecopy(ltop, result);
154161
}
155162

156163
char *bits_to_hex(const bits_t *bits) {
157-
char *result = try_calloc(BYTE_LEN(bits->bitlen) * 2 + 1);
158-
// probably right pad with zeroes, as thats what is actually stored.
164+
char *result =
165+
try_calloc(BYTE_LEN(bits->bitlen) * 2 + 1 + (bits->sign ? 1 : 0));
166+
if (bits->sign) {
167+
result[0] = '-';
168+
}
169+
size_t offset = bits->bitlen % 8;
170+
// if offset == 0
171+
// | a b | c d |
172+
// ^-----^ first byte
173+
// ^-----^ second byte
174+
// else
175+
// 0 0 | a b | c d | e
176+
// ^-----^ (8-offset zero bits, offset bits from first byte)
177+
// ^-----^ (8-offset bits from first byte, offset bits from second byte)
178+
// ....
179+
// ^-----^ (8-offset bits from second to last byte, offset bits from last byte)
159180
for (size_t i = 0; i < BYTE_LEN(bits->bitlen); ++i) {
160-
sprintf(result + (i * 2), "%02x", bits->bits[i]);
181+
size_t pos = (i * 2) + (bits->sign ? 1 : 0);
182+
unsigned char value;
183+
if (offset) {
184+
value = bits->bits[i] >> (8 - offset);
185+
if (i != 0) {
186+
value |= (bits->bits[i-1] & ~(1 << (8 - offset))) << offset;
187+
}
188+
} else {
189+
value = bits->bits[i];
190+
}
191+
sprintf(result + pos, "%02x", value);
161192
}
162193
return result;
163194
}
164195

165196
char *bits_to_bin(const bits_t *bits) {
166-
char *result = try_calloc(bits->bitlen + 1);
197+
char *result = try_calloc(bits->bitlen + 1 + (bits->sign ? 1 : 0));
198+
if (bits->sign) {
199+
result[0] = '-';
200+
}
167201
for (size_t i = 0; i < bits->bitlen; ++i) {
168-
sprintf(result + i, "%1u", GET_BIT(bits->bits, i));
202+
sprintf(result + i + (bits->sign ? 1 : 0), "%1u",
203+
GET_BIT(bits->bits, i));
169204
}
170205
return result;
171206
}
@@ -459,6 +494,7 @@ void bits_sha1(const bits_t *bits, unsigned char hashout[20]) {
459494
}
460495

461496
bool bits_eq(const bits_t *one, const bits_t *other) {
497+
if (one->sign != other->sign) return false;
462498
if (one->bitlen != other->bitlen) return false;
463499
if (one->bitlen == 0) return true;
464500
if (memcmp(one->bits, other->bits, one->bitlen / 8) != 0) return false;

test/ecgen.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,17 @@ function supersingular() {
128128

129129
function family() {
130130
start_test
131-
assert_raises "${ecgen} --fp -r --family=BN 32"
132-
assert_raises "${ecgen} --fp -r --family=BLS12 32"
133-
assert_raises "${ecgen} --fp -r --family=BLS24 32"
131+
assert_raises "${ecgen} --fp -r --family=BN 16"
132+
assert_raises "${ecgen} --fp -r --family=BLS12 16"
133+
assert_raises "${ecgen} --fp -r --family=BLS24 16"
134+
135+
assert_raises "${ecgen} --fp --family=BN 16" 0 "0xe5a2"
136+
assert_raises "${ecgen} --fp --family=BLS12 16" 0 "0xafa2"
137+
assert_raises "${ecgen} --fp --family=BLS24 16" 0 "0x8278"
138+
assert_raises "${ecgen} --fp --family=KSS16 16" 0 "0x8acc"
139+
assert_raises "${ecgen} --fp --family=KSS18 16" 0 "0xd2ac"
140+
assert_raises "${ecgen} --fp --family=KSS36 16" 0 "0xf07f"
141+
assert_raises "${ecgen} --fp --family=KSS40 16" 0 "-0xb18f"
134142
}
135143

136144
function invalid() {

test/src/util/test_bits.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ Test(bits, test_bits_to_hex) {
172172

173173
char *hex = bits_to_hex(bits);
174174
cr_assert_not_null(hex, );
175-
cr_assert_str_eq(hex, "abc0", );
175+
cr_assert_str_eq(hex, "0abc", );
176176
try_free(hex);
177177
bits_free(&bits);
178178
}

0 commit comments

Comments
 (0)