Skip to content

Commit

Permalink
Add KSS curve generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
J08nY committed Dec 1, 2024
1 parent 23c460d commit 0e9aa69
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 60 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Tool for generating Elliptic curve domain parameters.
- `-s / --ansi[=SEED]` Generate a curve from `SEED` (ANSI X9.62 verifiable procedure).
- `-b / --brainpool[=SEED]`Generate a curve using the Brainpool verifiably pseudorandom algorithm from the original paper.
- `--brainpool-rfc[=SEED]` Generate a curve using the Brainpool verifiably pseudorandom algorithm as per RFC 5639.
- `-F / --family=FAMILY` Generate a pairing friendly curve from a curve family (e.g. "BN", "BLS12", "BLS24").
- `-F / --family=FAMILY` Generate a pairing friendly curve from a curve family (e.g. "BN", "BLS12", "BLS24", "KSS16", "KSS18", "KSS36", "KSS40").
- `--nums` Generate a curve using the NUMS procedure (as per draft-black-numscurves-02).
- `--twist` Generate a twist of a given curve.

Expand Down
2 changes: 1 addition & 1 deletion src/exhaustive/exhaustive.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ static void exhaustive_ginit(gen_f *generators) {
}
generators[OFFSET_FIELD] = &family_gen_field;
generators[OFFSET_A] = &gen_skip;
if (cfg->family == FAMILY_KSS16) {
if (cfg->family == FAMILY_KSS16 || cfg->family == FAMILY_KSS40) {
generators[OFFSET_B] = &family_gen_equation_cm;
} else {
generators[OFFSET_B] = &family_gen_equation_iter;
Expand Down
80 changes: 41 additions & 39 deletions src/exhaustive/family.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "cm/cm_any.h"
#include "gen/seed.h"
#include "misc/config.h"
#include "util/bits.h"
#include "util/random.h"
#include "io/output.h"

#define FAMILIES (FAMILY_KSS40 + 1)

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

// clang-format off
void family_init() {
pari_sp ltop = avma;
nz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> z")));
pz_store[FAMILY_BN] = gclone(closure_evalgen(
compile_str("(z) -> 36*z^4 + 36*z^3 + 24*z^2 + 6*z + 1")));
rz_store[FAMILY_BN] = gclone(closure_evalgen(
compile_str("(z) -> 36*z^4 + 36*z^3 + 18*z^2 + 6*z + 1")));
tz_store[FAMILY_BN] =
gclone(closure_evalgen(compile_str("(z) -> 6*z + 1")));
pz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 36*z^4 + 36*z^3 + 24*z^2 + 6*z + 1")));
rz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 36*z^4 + 36*z^3 + 18*z^2 + 6*z + 1")));
tz_store[FAMILY_BN] = gclone(closure_evalgen(compile_str("(z) -> 6*z + 1")));
D_store[FAMILY_BN] = gclone(stoi(-3));

nz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z")));
pz_store[FAMILY_BLS12] = gclone(closure_evalgen(
compile_str("(z) -> (z - 1)^2 * (z^4 - z^2 + 1)/3 + z")));
rz_store[FAMILY_BLS12] =
gclone(closure_evalgen(compile_str("(z) -> z^4 - z^2 + 1")));
tz_store[FAMILY_BLS12] =
gclone(closure_evalgen(compile_str("(z) -> z + 1")));
pz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> (z - 1)^2 * (z^4 - z^2 + 1)/3 + z")));
rz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z^4 - z^2 + 1")));
tz_store[FAMILY_BLS12] = gclone(closure_evalgen(compile_str("(z) -> z + 1")));
D_store[FAMILY_BLS12] = gclone(stoi(-3));

nz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z")));
pz_store[FAMILY_BLS24] = gclone(closure_evalgen(
compile_str("(z) -> (z - 1)^2 * (z^8 - z^4 + 1)/3 + z")));
rz_store[FAMILY_BLS24] =
gclone(closure_evalgen(compile_str("(z) -> z^8 - z^4 + 1")));
tz_store[FAMILY_BLS24] =
gclone(closure_evalgen(compile_str("(z) -> z + 1")));
pz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> (z - 1)^2 * (z^8 - z^4 + 1)/3 + z")));
rz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z^8 - z^4 + 1")));
tz_store[FAMILY_BLS24] = gclone(closure_evalgen(compile_str("(z) -> z + 1")));
D_store[FAMILY_BLS24] = gclone(stoi(-3));

//TODO: This does not work...
nz_store[FAMILY_KSS16] =
gclone(closure_evalgen(compile_str("(z) -> 70*z + 25")));
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")));
rz_store[FAMILY_KSS16] = gclone(
closure_evalgen(compile_str("(z) -> (z^8 + 48*z^4 + 625)/61250")));
tz_store[FAMILY_KSS16] =
gclone(closure_evalgen(compile_str("(z) -> (2*z^5 + 41*z + 35)/35")));
D_store[FAMILY_KSS16] = gclone(stoi(-1));
nz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> 70*z + 25")));
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")));
rz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> (z^8 + 48*z^4 + 625)/61250")));
tz_store[FAMILY_KSS16] = gclone(closure_evalgen(compile_str("(z) -> (2*z^5 + 41*z + 35)/35")));
D_store[FAMILY_KSS16] = gclone(stoi(-4));

nz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> 42*z + 14")));
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")));
rz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> (z^6 + 37*z^3 + 343)/343")));
tz_store[FAMILY_KSS18] = gclone(closure_evalgen(compile_str("(z) -> (z^4 + 16*z + 7)/7")));
D_store[FAMILY_KSS18] = gclone(stoi(-3));

nz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> 777 * z + 287")));
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")));
rz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> (z^12 + 683*z^6 + 117649)/161061481")));
tz_store[FAMILY_KSS36] = gclone(closure_evalgen(compile_str("(z) -> (2*z^7 + 757*z + 259)/259")));
D_store[FAMILY_KSS36] = gclone(stoi(-3));

nz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> 2370*z + 1205")));
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")));
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")));
tz_store[FAMILY_KSS40] = gclone(closure_evalgen(compile_str("(z) -> (2*z^11 + 6469*z + 1185)/1185")));
D_store[FAMILY_KSS40] = gclone(stoi(-4));

avma = ltop;
}
// clang-format on

static seed_t *family_new_seed() {
seed_t *result = seed_new();
Expand All @@ -70,21 +77,18 @@ static seed_t *family_new_seed() {
GENERATOR(family_gen_seed_random) {
curve->seed = family_new_seed();
curve->seed->family.z = random_int(cfg->bits);
if (random_bits(1)) {
togglesign(curve->seed->family.z);
}
curve->seed->seed = bits_from_i(curve->seed->family.z);
return 1;
}

GENERATOR(family_gen_seed_input) {
pari_sp ltop = avma;
GEN inp = input_int("z:", cfg->bits);
if (gequalm1(inp)) {
avma = ltop;
return 0;
} else if (equalii(inp, gen_m2)) {
avma = ltop;
return INT_MIN;
}
curve->seed = family_new_seed();
curve->seed->family.z = inp;
curve->seed->seed = bits_from_i(curve->seed->family.z);
return 1;
}

Expand All @@ -96,13 +100,11 @@ GENERATOR(family_gen_field) {
avma = ltop;
return -1;
}
printf("p");
GEN rz = closure_callgen1(rz_store[cfg->family], n);
if (typ(rz) != t_INT || !isprime(rz)) {
avma = ltop;
return -1;
}
printf("r");
curve->field = gerepilecopy(ltop, pz);
return 1;
}
Expand Down
6 changes: 1 addition & 5 deletions src/io/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct argp_option cli_options[] = {
{"nums", OPT_NUMS, 0, 0, "Generate a curve using the NUMS procedure.", 2},
{"invalid", OPT_INVALID, "RANGE", OPTION_ARG_OPTIONAL, "Generate a set of invalid curves, for a given curve (using Invalid curve algorithm).", 2},
{"twist", OPT_TWIST, 0, 0, "Generate a twist of a given curve.", 2},
{"family", OPT_FAMILY, "NAME", 0, "Generate a curve from a curve family (e.g. BN, BLS12, BLS24, KSS)."},
{"family", OPT_FAMILY, "NAME", 0, "Generate a curve from a curve family (e.g. BN, BLS12, BLS24, KSS16, KSS18, KSS36, KSS40).", 2},

{0, 0, 0, 0, "Generation options:", 3},
{"random", OPT_RANDOM, "WHAT", OPTION_ARG_OPTIONAL, "Generate a random curve (using Random approach). "
Expand Down Expand Up @@ -294,16 +294,12 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
} else if (strcasecmp(arg, "BLS24") == 0) {
cfg->family = FAMILY_BLS24;
} else if (strcasecmp(arg, "KSS16") == 0) {
argp_failure(state, 1, 0, "Family not yet supported.");
cfg->family = FAMILY_KSS16;
} else if (strcasecmp(arg, "KSS18") == 0) {
argp_failure(state, 1, 0, "Family not yet supported.");
cfg->family = FAMILY_KSS18;
} else if (strcasecmp(arg, "KSS36") == 0) {
argp_failure(state, 1, 0, "Family not yet supported.");
cfg->family = FAMILY_KSS36;
} else if (strcasecmp(arg, "KSS40") == 0) {
argp_failure(state, 1, 0, "Family not yet supported.");
cfg->family = FAMILY_KSS40;
} else {
argp_failure(state, 1, 0, "Unknown curve family = %s", arg);
Expand Down
8 changes: 5 additions & 3 deletions src/io/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ static GEN input_i(const char *prompt, unsigned long bits) {
free(line);
return gen_m1;
}
for (size_t i = 0, j = 0; (line[j] = line[i]); j += !isspace(line[i++]))
;
bool sign = line[0] == '-';

pari_sp ltop = avma;
GEN in = strtoi(line);
GEN in = strtoi(line + sign);
if (sign) {
togglesign(in);
}
free(line);

// check bitsize here
Expand Down
12 changes: 10 additions & 2 deletions src/io/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,17 @@ static JSON_Value *output_jjson(curve_t *curve) {
if (curve->seed && curve->seed->seed) {
char *hex_str = bits_to_hex(curve->seed->seed);
char *hex = try_calloc(strlen(hex_str) + 3);
hex[0] = '0';
hex[1] = 'x';
if (curve->seed->seed->sign) {
hex[0] = '-';
hex[1] = '0';
} else {
hex[0] = '0';
hex[1] = 'x';
}
strcat(hex, hex_str);
if (curve->seed->seed->sign) {
hex[2] = 'x';
}
json_object_set_string(root_object, "seed", hex);
try_free(hex_str);
try_free(hex);
Expand Down
2 changes: 2 additions & 0 deletions src/misc/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
/**
* @brief
* @param bits
* @param sign
* @param bitlen
* @param allocated
*/
typedef struct {
unsigned char *bits;
bool sign;
size_t bitlen;
size_t allocated;
} bits_t;
Expand Down
46 changes: 41 additions & 5 deletions src/util/bits.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ void bits_cpy(bits_t *dest, const bits_t *src) {
memcpy(dest->bits, src->bits, src->allocated);
dest->allocated = src->allocated;
dest->bitlen = src->bitlen;
dest->sign = src->sign;
}

bits_t *bits_copy(const bits_t *bits) {
bits_t *result = try_calloc(sizeof(bits_t));
result->sign = bits->sign;
result->bitlen = bits->bitlen;
result->allocated = bits->allocated;
if (bits->allocated != 0)
Expand All @@ -70,6 +72,7 @@ bits_t *bits_from_i(GEN i) {
GEN bitvec = binary_zv(i);
size_t bit_len = (size_t)glength(bitvec);
bits_t *result = bits_new(bit_len);
result->sign = signe(i) == -1;
for (size_t j = 0; j < bit_len; ++j) {
if (gel(bitvec, j + 1) == (GEN)1) {
result->bits[j / 8] |= 1 << (7 - (j % 8));
Expand All @@ -84,6 +87,7 @@ bits_t *bits_from_i_len(GEN i, size_t bit_len) {
GEN bitvec = binary_zv(i);
size_t i_len = (size_t)glength(bitvec);
bits_t *result = bits_new(bit_len);
result->sign = signe(i) == -1;
size_t offset = 0;
if (i_len < bit_len) {
offset = bit_len - i_len;
Expand Down Expand Up @@ -150,22 +154,53 @@ GEN bits_to_i(const bits_t *bits) {
if (GET_BIT(bits->bits, i) != 0)
result = addii(result, int2n(bits->bitlen - i - 1));
}
if (bits->sign) {
setsigne(result, -1);
}
return gerepilecopy(ltop, result);
}

char *bits_to_hex(const bits_t *bits) {
char *result = try_calloc(BYTE_LEN(bits->bitlen) * 2 + 1);
// probably right pad with zeroes, as thats what is actually stored.
char *result =
try_calloc(BYTE_LEN(bits->bitlen) * 2 + 1 + (bits->sign ? 1 : 0));
if (bits->sign) {
result[0] = '-';
}
size_t offset = bits->bitlen % 8;
// if offset == 0
// | a b | c d |
// ^-----^ first byte
// ^-----^ second byte
// else
// 0 0 | a b | c d | e
// ^-----^ (8-offset zero bits, offset bits from first byte)
// ^-----^ (8-offset bits from first byte, offset bits from second byte)
// ....
// ^-----^ (8-offset bits from second to last byte, offset bits from last byte)
for (size_t i = 0; i < BYTE_LEN(bits->bitlen); ++i) {
sprintf(result + (i * 2), "%02x", bits->bits[i]);
size_t pos = (i * 2) + (bits->sign ? 1 : 0);
unsigned char value;
if (offset) {
value = bits->bits[i] >> (8 - offset);
if (i != 0) {
value |= (bits->bits[i-1] & ~(1 << (8 - offset))) << offset;
}
} else {
value = bits->bits[i];
}
sprintf(result + pos, "%02x", value);
}
return result;
}

char *bits_to_bin(const bits_t *bits) {
char *result = try_calloc(bits->bitlen + 1);
char *result = try_calloc(bits->bitlen + 1 + (bits->sign ? 1 : 0));
if (bits->sign) {
result[0] = '-';
}
for (size_t i = 0; i < bits->bitlen; ++i) {
sprintf(result + i, "%1u", GET_BIT(bits->bits, i));
sprintf(result + i + (bits->sign ? 1 : 0), "%1u",
GET_BIT(bits->bits, i));
}
return result;
}
Expand Down Expand Up @@ -459,6 +494,7 @@ void bits_sha1(const bits_t *bits, unsigned char hashout[20]) {
}

bool bits_eq(const bits_t *one, const bits_t *other) {
if (one->sign != other->sign) return false;
if (one->bitlen != other->bitlen) return false;
if (one->bitlen == 0) return true;
if (memcmp(one->bits, other->bits, one->bitlen / 8) != 0) return false;
Expand Down
14 changes: 11 additions & 3 deletions test/ecgen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,17 @@ function supersingular() {

function family() {
start_test
assert_raises "${ecgen} --fp -r --family=BN 32"
assert_raises "${ecgen} --fp -r --family=BLS12 32"
assert_raises "${ecgen} --fp -r --family=BLS24 32"
assert_raises "${ecgen} --fp -r --family=BN 16"
assert_raises "${ecgen} --fp -r --family=BLS12 16"
assert_raises "${ecgen} --fp -r --family=BLS24 16"

assert_raises "${ecgen} --fp --family=BN 16" 0 "0xe5a2"
assert_raises "${ecgen} --fp --family=BLS12 16" 0 "0xafa2"
assert_raises "${ecgen} --fp --family=BLS24 16" 0 "0x8278"
assert_raises "${ecgen} --fp --family=KSS16 16" 0 "0x8acc"
assert_raises "${ecgen} --fp --family=KSS18 16" 0 "0xd2ac"
assert_raises "${ecgen} --fp --family=KSS36 16" 0 "0xf07f"
assert_raises "${ecgen} --fp --family=KSS40 16" 0 "-0xb18f"
}

function invalid() {
Expand Down
2 changes: 1 addition & 1 deletion test/src/util/test_bits.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Test(bits, test_bits_to_hex) {

char *hex = bits_to_hex(bits);
cr_assert_not_null(hex, );
cr_assert_str_eq(hex, "abc0", );
cr_assert_str_eq(hex, "0abc", );
try_free(hex);
bits_free(&bits);
}
Expand Down

0 comments on commit 0e9aa69

Please sign in to comment.