Skip to content

Commit

Permalink
Add curve family generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
J08nY committed Dec 1, 2024
1 parent 2e3b816 commit 23c460d
Show file tree
Hide file tree
Showing 15 changed files with 374 additions and 15 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +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").
- `--nums` Generate a curve using the NUMS procedure (as per draft-black-numscurves-02).
- `--twist` Generate a twist of a given curve.

Expand Down Expand Up @@ -203,7 +204,7 @@ for Doxygen.

### Generation methods

Four different EC curve parameters generation methods are implemented.
Five different EC curve parameters generation methods are implemented.

[Efficient Algorithms for Generating Elliptic Curves over Finite Fields Suitable for Use in Cryptography - [Baier]](https://www.cdc.informatik.tu-darmstadt.de/reports/reports/harald_baier.diss.pdf)

Expand Down Expand Up @@ -258,6 +259,11 @@ Four different EC curve parameters generation methods are implemented.
- [Elliptic curves over F_p suitable for cryptosystems - [Miyaji]](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4464/1/73-61.pdf)
- TODO: Extend with [Generating Anomalous Elliptic Curves - [Leprevost, Monnerat, Varrette, Vaydenay]](https://www.monnerat.info/publications/anomalous.pdf)

#### Curve families

- Generates pairing friendly curves.
- Used with the `-F / --family` option. Select from BN, BLS12 or BLS24 currently.

### Build

ecgen can be built using Make or CMake. ecgen uses git submodules for testing at:
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FAST ?= 0
STATIC ?= 0

ifeq ($(DEBUG), 1)
ECGEN_CFLAGS = -DDEBUG -g -Og -Werror -pedantic
ECGEN_CFLAGS = -DDEBUG -g -O0 -Werror -pedantic
else ifeq ($(TEST), 1)
ECGEN_CFLAGS = -DNDEBUG --coverage -g -O0
else ifeq ($(FAST), 1)
Expand Down
38 changes: 38 additions & 0 deletions src/cm/cm_any.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime) {
GEN r = FpX_roots(H, p);
debug_log("roots = %Ps", r);
if (gequal(r, gtovec(gen_0))) {
avma = ltop;
return NULL;
}

Expand Down Expand Up @@ -206,6 +207,43 @@ GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime) {
}
}
}
avma = ltop;
return NULL;
}

GEN cm_construct_curve_subgroup(GEN r, GEN d, GEN p) {
debug_log("Constructing a curve with r = %Pi, d = %Pi, p = %Pi", r, d,
p);
pari_sp ltop = avma;
GEN H = polclass(d, 0, 0);
debug_log("H = %Ps", H);

GEN roots = FpX_roots(H, p);
debug_log("roots = %Ps", roots);
if (gequal(roots, gtovec(gen_0))) {
avma = ltop;
return NULL;
}

long rlen = glength(roots);
pari_sp btop = avma;
for (long i = 1; i <= rlen; ++i) {
GEN root = gel(roots, i);
debug_log("trying root = %Pi", root);

GEN e = ellinit(ellfromj(mkintmod(root, p)), p, 0);
pari_CATCH(e_TYPE) { avma = btop; continue; }
pari_TRY { checkell(e); };
pari_ENDCATCH{};

GEN ord = ellff_get_card(e);
if (dvdii(ord, r)) {
debug_log("Got curve.");
return gerepilecopy(ltop, e);
}
avma = btop;
}
avma = ltop;
return NULL;
}

Expand Down
6 changes: 6 additions & 0 deletions src/cm/cm_any.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ typedef struct {
*/
GEN cm_construct_curve(GEN order, GEN d, GEN p, bool ord_prime);

/**
* @brief Construct an elliptic curve given a factor of its order, CM
* discriminant and field order.
*/
GEN cm_construct_curve_subgroup(GEN r, GEN d, GEN p);

/**
* @brief
* @param curve
Expand Down
28 changes: 23 additions & 5 deletions src/exhaustive/exhaustive.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "brainpool.h"
#include "brainpool_rfc.h"
#include "nums.h"
#include "family.h"
#include "check.h"
#include "gen/curve.h"
#include "gen/equation.h"
Expand Down Expand Up @@ -137,6 +138,25 @@ static void exhaustive_ginit(gen_f *generators) {
default:
break;
}
} else if (cfg->method == METHOD_FAMILY) {
// setup family generators
if (GET_BOOL(random)) {
generators[OFFSET_SEED] = &family_gen_seed_random;
} else {
generators[OFFSET_SEED] = &family_gen_seed_input;

}
generators[OFFSET_FIELD] = &family_gen_field;
generators[OFFSET_A] = &gen_skip;
if (cfg->family == FAMILY_KSS16) {
generators[OFFSET_B] = &family_gen_equation_cm;
} else {
generators[OFFSET_B] = &family_gen_equation_iter;
}

//TODO make the prime check optional, based on cfg->prime.
generators[OFFSET_ORDER] = &family_gen_order;
generators[OFFSET_GENERATORS] = &gens_gen_any;
} else {
// setup normal generators
generators[OFFSET_SEED] = &gen_skip;
Expand Down Expand Up @@ -250,8 +270,6 @@ static void exhaustive_cinit(check_t **validators) {
if (cfg->method == METHOD_SEED) {
GET(seed_algo);
switch (cfg->seed_algo) {
case SEED_ANSI:
break;
case SEED_BRAINPOOL:
case SEED_BRAINPOOL_RFC: {
// TODO: Missing Brainpool CM disc check.
Expand All @@ -267,8 +285,6 @@ static void exhaustive_cinit(check_t **validators) {
check_new(gens_check_anomalous, brainpool_check_gens, NULL);
validators[OFFSET_GENERATORS] = gens_check;
} break;
case SEED_FIPS:
break;
default:
break;
}
Expand Down Expand Up @@ -310,7 +326,7 @@ static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) {
}

void exhaustive_uinit(unroll_f *unrolls) {
if (cfg->seed_algo) {
if (cfg->seed_algo || cfg->method == METHOD_FAMILY) {
unrolls[OFFSET_SEED] = &seed_unroll;
} else {
unrolls[OFFSET_SEED] = &unroll_skip;
Expand Down Expand Up @@ -436,12 +452,14 @@ static void exhaustive_init(exhaustive_t *setup) {
exhaustive_cinit(setup->validators);
exhaustive_ainit(setup->gen_argss, setup->check_argss);
exhaustive_uinit(setup->unrolls);
family_init();
}

static void exhaustive_quit(exhaustive_t *setup) {
field_quit();
equation_quit();
nums_quit();
family_quit();
exhaustive_clear(setup);
}

Expand Down
193 changes: 193 additions & 0 deletions src/exhaustive/family.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* ecgen, tool for generating Elliptic curve domain parameters
* Copyright (C) 2024 J08nY
*/

#include "family.h"
#include "cm/cm_any.h"
#include "gen/seed.h"
#include "misc/config.h"
#include "util/random.h"

#define FAMILIES (FAMILY_KSS40 + 1)

static GEN nz_store[FAMILIES] = {0};
static GEN pz_store[FAMILIES] = {0};
static GEN rz_store[FAMILIES] = {0};
static GEN tz_store[FAMILIES] = {0};
static GEN D_store[FAMILIES] = {0};

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")));
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")));
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")));
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));

avma = ltop;
}

static seed_t *family_new_seed() {
seed_t *result = seed_new();
result->type = SEED_FAMILY;
return result;
}

GENERATOR(family_gen_seed_random) {
curve->seed = family_new_seed();
curve->seed->family.z = random_int(cfg->bits);
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;
return 1;
}

GENERATOR(family_gen_field) {
pari_sp ltop = avma;
GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z);
GEN pz = closure_callgen1(pz_store[cfg->family], n);
if (typ(pz) != t_INT || !isprime(pz)) {
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;
}

static GEN b = NULL;
static curve_t *b_curve = NULL;

GENERATOR(family_gen_equation_iter) {
curve->a = gmodulo(gen_0, curve->field);

pari_sp ltop = avma;
if (!b) {
b = gclone(gen_1);
curve->b = gmodulo(gen_1, curve->field);
b_curve = curve;
return 1;
} else {
if (curve == b_curve) {
GEN bn = addii(b, gen_1);
gunclone(b);
b = gclone(bn);
curve->b = gerepilecopy(ltop, gmodulo(bn, curve->field));
return 1;
} else {
// dont use b, regenerate it,
gunclone(b);
b = gclone(gen_1);
curve->b = gerepilecopy(ltop, gmodulo(gen_1, curve->field));
b_curve = curve;
return 1;
}
}
}

GENERATOR(family_gen_equation_cm) {
GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z);
GEN rz = closure_callgen1(rz_store[cfg->family], n);
GEN D = D_store[cfg->family];
GEN e = cm_construct_curve_subgroup(rz, D, curve->field);
if (e) {
curve->a = ell_get_a4(e);
curve->b = ell_get_a6(e);
return 1;
}
return -3;
}

GENERATOR(family_gen_order) {
pari_sp ltop = avma;
GEN n = closure_callgen1(nz_store[cfg->family], curve->seed->family.z);
GEN rz = closure_callgen1(rz_store[cfg->family], n);
GEN ord = ellff_get_card(curve->curve);
if (dvdii(ord, rz)) {
if (isclone(ord)) {
curve->order = gerepilecopy(ltop, ord);
} else {
avma = ltop;
curve->order = ord;
}
return 1;
} else {
avma = ltop;
return -2;
}
}

void family_quit() {
for (int i = 0; i < FAMILIES; i++) {
if (nz_store[i]) {
gunclone(nz_store[i]);
}
if (pz_store[i]) {
gunclone(pz_store[i]);
}
if (rz_store[i]) {
gunclone(rz_store[i]);
}
if (tz_store[i]) {
gunclone(tz_store[i]);
}
if (D_store[i]) {
gunclone(D_store[i]);
}
}
if (b) {
gunclone(b);
}
}
Loading

0 comments on commit 23c460d

Please # to comment.