aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2018-03-03 01:02:08 +0100
committerJ08nY2018-03-03 01:02:08 +0100
commitac60f78a253efde94cab36264b0555b0691fdd8a (patch)
tree12ce2bfdee1f13f0b6e56a017c3c29979475fe02 /src
parent40cbb213ac910ddcaf22a26a247d2a9eeddca1fc (diff)
downloadecgen-ac60f78a253efde94cab36264b0555b0691fdd8a.tar.gz
ecgen-ac60f78a253efde94cab36264b0555b0691fdd8a.tar.zst
ecgen-ac60f78a253efde94cab36264b0555b0691fdd8a.zip
Diffstat (limited to 'src')
-rw-r--r--src/exhaustive/brainpool.c10
-rw-r--r--src/exhaustive/exhaustive.c12
-rw-r--r--src/gen/curve.c17
-rw-r--r--src/gen/gens.c75
-rw-r--r--src/gen/gens.h13
-rw-r--r--src/gen/gp.c176
-rw-r--r--src/gen/gp.h30
-rw-r--r--src/gen/hex.c48
-rw-r--r--src/gen/order.c38
-rw-r--r--src/gen/order.h4
-rw-r--r--src/gen/point.c175
-rw-r--r--src/gen/point.h8
-rw-r--r--src/io/cli.c15
-rw-r--r--src/io/output.c96
-rw-r--r--src/math/subgroup.c237
-rw-r--r--src/math/subgroup.h139
-rw-r--r--src/math/subgroups.c150
-rw-r--r--src/math/subgroups.h35
-rw-r--r--src/math/twists.c5
-rw-r--r--src/misc/config.h2
-rw-r--r--src/misc/types.h24
-rw-r--r--src/util/random.c10
-rw-r--r--src/util/random.h8
-rw-r--r--src/util/str.c38
-rw-r--r--src/util/str.h19
25 files changed, 772 insertions, 612 deletions
diff --git a/src/exhaustive/brainpool.c b/src/exhaustive/brainpool.c
index 17c2c65..62a3352 100644
--- a/src/exhaustive/brainpool.c
+++ b/src/exhaustive/brainpool.c
@@ -3,11 +3,13 @@
* Copyright (C) 2017-2018 J08nY
*/
+#include <misc/types.h>
#include "brainpool.h"
#include "gen/gens.h"
#include "gen/point.h"
#include "gen/seed.h"
#include "io/output.h"
+#include "math/subgroup.h"
#include "util/bits.h"
#include "util/str.h"
@@ -237,10 +239,12 @@ GENERATOR(brainpool_gen_gens) {
return INT_MIN;
}
- curve->generators = points_new(1);
+ curve->generators = subgroups_new(1);
curve->ngens = 1;
+ subgroup_t *sub = subgroup_new();
+ curve->generators[0] = sub;
point_t *G = point_new();
- curve->generators[0] = G;
+ sub->generator = G;
G->point = ellmul(curve->curve, P, k);
G->order = ellorder(curve->curve, G->point, NULL);
G->cofactor = divii(curve->order, G->order);
@@ -252,7 +256,7 @@ GENERATOR(brainpool_gen_gens) {
CHECK(brainpool_check_gens) {
pari_sp ltop = avma;
- point_t *G = curve->generators[0];
+ point_t *G = curve->generators[0]->generator;
GEN min_degree = divis(subii(G->order, gen_1), 100);
if (mpcmp(min_degree, gens_get_embedding(curve->field, G->order)) >= 0) {
avma = ltop;
diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c
index e7d6350..7ad4705 100644
--- a/src/exhaustive/exhaustive.c
+++ b/src/exhaustive/exhaustive.c
@@ -43,13 +43,15 @@ static void exhaustive_ginit(gen_f *generators) {
if (cfg->prime) {
generators[OFFSET_ORDER] = &order_gen_prime;
} else if (cfg->cofactor) {
- generators[OFFSET_ORDER] = &order_gen_smallfact;
+ generators[OFFSET_ORDER] = &order_gen_cofactor;
} else {
generators[OFFSET_ORDER] = &order_gen_any;
}
if (cfg->unique) {
generators[OFFSET_GENERATORS] = &gens_gen_one;
+ } else if (cfg->cofactor) {
+ generators[OFFSET_GENERATORS] = &gens_gen_cofactor;
} else {
generators[OFFSET_GENERATORS] = &gens_gen_any;
}
@@ -144,7 +146,7 @@ static void exhaustive_ginit(gen_f *generators) {
if (cfg->prime) {
generators[OFFSET_ORDER] = &order_gen_prime;
} else if (cfg->cofactor) {
- generators[OFFSET_ORDER] = &order_gen_smallfact;
+ generators[OFFSET_ORDER] = &order_gen_cofactor;
} else if (cfg->method == METHOD_ANOMALOUS) {
generators[OFFSET_ORDER] = &anomalous_gen_order;
} else {
@@ -161,6 +163,8 @@ static void exhaustive_ginit(gen_f *generators) {
if (cfg->unique) {
generators[OFFSET_GENERATORS] = &gens_gen_one;
+ } else if (cfg->cofactor) {
+ generators[OFFSET_GENERATORS] = &gens_gen_cofactor;
} else {
generators[OFFSET_GENERATORS] = &gens_gen_any;
}
@@ -249,9 +253,9 @@ static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) {
if (cfg->cofactor) {
arg_t *order_arg = arg_new();
arg_t *gens_arg = arg_new();
- order_arg->args = &cfg->cofactor_bound;
+ order_arg->args = &cfg->cofactor_value;
order_arg->nargs = 1;
- gens_arg->args = &cfg->cofactor_bound;
+ gens_arg->args = &cfg->cofactor_value;
gens_arg->nargs = 1;
gen_argss[OFFSET_ORDER] = order_arg;
gen_argss[OFFSET_GENERATORS] = gens_arg;
diff --git a/src/gen/curve.c b/src/gen/curve.c
index f89044a..8c7d4c9 100644
--- a/src/gen/curve.c
+++ b/src/gen/curve.c
@@ -4,7 +4,7 @@
*/
#include "curve.h"
#include "math/twists.h"
-#include "point.h"
+#include "math/subgroup.h"
#include "seed.h"
#include "util/memory.h"
@@ -18,13 +18,9 @@ curve_t *curve_copy(const curve_t *src, curve_t *dest) {
if (src->curve) dest->curve = gcopy(src->curve);
if (src->order) dest->order = gcopy(src->order);
if (src->generators) {
- dest->generators = points_new_copy(src->generators, src->ngens);
+ dest->generators = subgroups_new_copy(src->generators, src->ngens);
dest->ngens = src->ngens;
}
- if (src->points) {
- dest->points = points_new_copy(src->points, src->npoints);
- dest->npoints = src->npoints;
- }
return dest;
}
@@ -41,13 +37,9 @@ curve_t *curve_clone(const curve_t *src, curve_t *dest) {
if (src->curve) dest->curve = gclone(src->curve);
if (src->order) dest->order = gclone(src->order);
if (src->generators) {
- dest->generators = points_new_clone(src->generators, src->ngens);
+ dest->generators = subgroups_new_clone(src->generators, src->ngens);
dest->ngens = src->ngens;
}
- if (src->points) {
- dest->points = points_new_clone(src->points, src->npoints);
- dest->npoints = src->npoints;
- }
return dest;
}
@@ -59,8 +51,7 @@ curve_t *curve_new_clone(const curve_t *src) {
void curve_free(curve_t **curve) {
if (*curve) {
seed_free(&(*curve)->seed);
- points_free_deep(&(*curve)->generators, (*curve)->ngens);
- points_free_deep(&(*curve)->points, (*curve)->npoints);
+ subgroups_free_deep(&(*curve)->generators, (*curve)->ngens);
if ((*curve)->curve) {
// TODO, this is possibly dangerous...
diff --git a/src/gen/gens.c b/src/gen/gens.c
index ba94c64..9d870e7 100644
--- a/src/gen/gens.c
+++ b/src/gen/gens.c
@@ -3,21 +3,28 @@
* Copyright (C) 2017-2018 J08nY
*/
#include "gens.h"
+#include "math/subgroup.h"
#include "exhaustive/arg.h"
#include "point.h"
+
+static subgroup_t *gens_point(GEN point, const curve_t *curve) {
+ subgroup_t *sub = subgroup_new();
+ point_t *p = point_new();
+ sub->generator = p;
+ p->point = gcopy(point);
+ p->order = ellorder(curve->curve, p->point, NULL);
+ p->cofactor = divii(curve->order, p->order);
+ return sub;
+}
+
static int gens_put(curve_t *curve, GEN generators, long len) {
- curve->generators = points_new((size_t)len);
- curve->ngens = (size_t)len;
+ curve->generators = subgroups_new((size_t) len);
+ curve->ngens = (size_t) len;
for (long i = 1; i <= len; ++i) {
- point_t *p = point_new();
- p->point = gcopy(gel(generators, i));
- p->order = ellorder(curve->curve, p->point, NULL);
- p->cofactor = divii(curve->order, p->order);
- curve->generators[i - 1] = p;
+ curve->generators[i - 1] = gens_point(gel(generators, i), curve);
}
-
return 1;
}
@@ -38,10 +45,56 @@ GENERATOR(gens_gen_one) {
return gens_put(curve, generators, len);
}
+GENERATOR(gens_gen_cofactor) {
+ HAS_ARG(args);
+ pari_ulong cofactor = *(pari_ulong *) args->args;
+ pari_sp ltop = avma;
+ GEN order = diviuexact(curve->order, cofactor);
+
+ GEN generators = ellff_get_gens(curve->curve);
+ long len = glength(generators);
+ point_t *p = NULL;
+ for (long i = 1; i <= len; ++i) {
+ GEN gen = gel(generators, i);
+ GEN gen_order = ellorder(curve->curve, gen, NULL);
+
+ if (equalii(order, gen_order)) {
+ p = point_new();
+ p->point = gcopy(gen);
+ p->order = gen_order;
+ p->cofactor = utoi(cofactor);
+ break;
+ }
+ GEN res = cgeti(DEFAULTPREC);
+ if (dvdiuz(gen_order, cofactor, res)) {
+ p = point_new();
+ p->point = gcopy(ellmul(curve->curve, gen, utoi(cofactor)));
+ p->order = res;
+ p->cofactor = utoi(cofactor);
+ break;
+ }
+ }
+
+ if (p) {
+ curve->ngens = (size_t) (len + 1);
+ curve->generators = subgroups_new(curve->ngens);
+ for (long i = 1; i <= len; ++i) {
+ curve->generators[i] = gens_point(gel(generators, i), curve);
+ }
+ subgroup_t *sub = subgroup_new();
+ sub->generator = p;
+ curve->generators[0] = sub;
+ return 1;
+ } else {
+ avma = ltop;
+ return -5;
+ }
+}
+
CHECK(gens_check_anomalous) {
if (cfg->field == FIELD_BINARY) return 1;
for (size_t i = 0; i < curve->ngens; ++i) {
- if (mpcmp(curve->field, curve->generators[i]->order) == 0) {
+ if (mpcmp(curve->field, curve->generators[i]->generator->order) == 0) {
return -5;
}
}
@@ -62,7 +115,7 @@ CHECK(gens_check_embedding) {
for (size_t i = 0; i < curve->ngens; ++i) {
GEN power =
- gens_get_embedding(curve->field, curve->generators[i]->order);
+ gens_get_embedding(curve->field, curve->generators[i]->generator->order);
if (mpcmp(power, mind) <= 0) {
avma = ltop;
@@ -75,7 +128,7 @@ CHECK(gens_check_embedding) {
UNROLL(gens_unroll) {
if (curve->generators) {
- points_free_deep(&curve->generators, curve->ngens);
+ subgroups_free_deep(&curve->generators, curve->ngens);
}
return -1;
}
diff --git a/src/gen/gens.h b/src/gen/gens.h
index 0929bbf..4d1ea88 100644
--- a/src/gen/gens.h
+++ b/src/gen/gens.h
@@ -16,6 +16,7 @@
*
* @param curve A curve_t being generated
* @param args unused
+ * @param state
* @return state diff
*/
GENERATOR(gens_gen_any);
@@ -25,10 +26,22 @@ GENERATOR(gens_gen_any);
*
* @param curve A curve_t being generated
* @param args unused
+ * @param state
* @return state diff
*/
GENERATOR(gens_gen_one);
+
+/**
+ * GENERATOR(gen_f)
+ *
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(gens_gen_cofactor);
+
/**
* CHECK(check_f)
*
diff --git a/src/gen/gp.c b/src/gen/gp.c
deleted file mode 100644
index 1800f26..0000000
--- a/src/gen/gp.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * ecgen, tool for generating Elliptic curve domain parameters
- * Copyright (C) 2017-2018 J08nY
- */
-#include "gp.h"
-#include "exhaustive/arg.h"
-#include "io/output.h"
-#include "point.h"
-#include "seed.h"
-#include "util/bits.h"
-
-static point_t **gp_points(const curve_t *curve, GEN point_vec) {
- long len = glength(point_vec);
- point_t **result = points_new((size_t)len);
-
- for (long i = 1; i <= len; ++i) {
- point_t *point = point_new();
- point->point = gel(point_vec, i);
- point->order = ellorder(curve->curve, point->point, NULL);
- result[i - 1] = point;
- }
- return result;
-}
-
-static point_t **gp_gens(const curve_t *curve, GEN gens_vec) {
- point_t **result = gp_points(curve, gens_vec);
-
- long len = glength(gens_vec);
- for (long i = 1; i <= len; ++i) {
- point_t *gen = result[i - 1];
- gen->cofactor = divii(curve->order, gen->order);
- }
- return result;
-}
-
-GENERATOR(gp_gen) {
- HAS_ARG(args);
- pari_sp ltop = avma;
- GEN closure = compile_str(args->args);
- GEN params = zerovec(state - OFFSET_SEED);
-
- if (state > OFFSET_SEED) {
- if (curve->seed && curve->seed->seed) {
- gel(params, 1) = bits_to_bitvec(curve->seed->seed);
- }
- }
-
- if (state > OFFSET_FIELD) {
- gel(params, 2) = curve->field;
- }
-
- if (state > OFFSET_A) {
- gel(params, 3) = curve->a;
- }
-
- if (state > OFFSET_B) {
- gel(params, 4) = curve->b;
- }
-
- if (state > OFFSET_CURVE) {
- gel(params, 5) = curve->curve;
- }
-
- if (state > OFFSET_ORDER) {
- gel(params, 6) = curve->order;
- }
-
- if (state > OFFSET_GENERATORS) {
- GEN gens = zerovec(curve->ngens);
- for (size_t i = 0; i < curve->ngens; ++i) {
- gel(gens, i + 1) = curve->generators[i]->point;
- }
- gel(params, 7) = gens;
- }
-
- if (state > OFFSET_POINTS) {
- GEN points = zerovec(curve->npoints);
- for (size_t i = 0; i < curve->npoints; ++i) {
- gel(points, i + 1) = curve->points[i]->point;
- }
- gel(params, 8) = points;
- }
-
- GEN res = call0(closure, zerovec(0));
- res = call0(res, params);
-
- res = gerepileupto(ltop, res);
- switch (state) {
- case OFFSET_SEED:
- curve->seed = seed_new();
- curve->seed->seed = bits_from_bitvec(res);
- break;
- case OFFSET_FIELD:
- curve->field = res;
- break;
- case OFFSET_A:
- curve->a = res;
- break;
- case OFFSET_B:
- curve->b = res;
- break;
- case OFFSET_CURVE:
- curve->curve = res;
- break;
- case OFFSET_ORDER:
- curve->order = res;
- break;
- case OFFSET_GENERATORS:
- curve->ngens = (size_t)glength(res);
- curve->generators = gp_gens(curve, res);
- break;
- case OFFSET_POINTS:
- curve->npoints = (size_t)glength(res);
- curve->points = gp_points(curve, res);
- break;
- case OFFSET_END:
- break;
- }
- return 1;
-}
-
-CHECK(gp_check) {
- HAS_ARG(args);
- pari_sp ltop = avma;
- GEN closure = compile_str(args->args);
- GEN params = zerovec(state - OFFSET_SEED + 1);
-
- if (state >= OFFSET_SEED) {
- if (curve->seed && curve->seed->seed) {
- gel(params, 1) = bits_to_bitvec(curve->seed->seed);
- }
- }
-
- if (state >= OFFSET_FIELD) {
- gel(params, 2) = curve->field;
- }
-
- if (state >= OFFSET_A) {
- gel(params, 3) = curve->a;
- }
-
- if (state >= OFFSET_B) {
- gel(params, 4) = curve->b;
- }
-
- if (state >= OFFSET_CURVE) {
- gel(params, 5) = curve->curve;
- }
-
- if (state >= OFFSET_ORDER) {
- gel(params, 6) = curve->order;
- }
-
- if (state >= OFFSET_GENERATORS) {
- GEN gens = zerovec(curve->ngens);
- for (size_t i = 0; i < curve->ngens; ++i) {
- gel(gens, i + 1) = curve->generators[i]->point;
- }
- gel(params, 7) = gens;
- }
-
- if (state >= OFFSET_POINTS) {
- GEN points = zerovec(curve->npoints);
- for (size_t i = 0; i < curve->npoints; ++i) {
- gel(points, i + 1) = curve->points[i]->point;
- }
- gel(params, 8) = points;
- }
-
- GEN res = call0(closure, zerovec(0));
- res = call0(res, params);
-
- int result = (int)itos(res);
- avma = ltop;
- return result;
-} \ No newline at end of file
diff --git a/src/gen/gp.h b/src/gen/gp.h
deleted file mode 100644
index 4506816..0000000
--- a/src/gen/gp.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * ecgen, tool for generating Elliptic curve domain parameters
- * Copyright (C) 2017-2018 J08nY
- */
-/**
- * @file gp.h
- */
-#ifndef ECGEN_GP_H
-#define ECGEN_GP_H
-
-#include "misc/types.h"
-
-/**
- * @brief
- * @param curve
- * @param args
- * @return
- */
-GENERATOR(gp_gen);
-
-/**
- * @brief
- * @param curve
- * @param args
- * @param state
- * @return
- */
-CHECK(gp_check);
-
-#endif // ECGEN_GP_H
diff --git a/src/gen/hex.c b/src/gen/hex.c
index 39200a8..08c280f 100644
--- a/src/gen/hex.c
+++ b/src/gen/hex.c
@@ -2,20 +2,30 @@
* ecgen, tool for generating Elliptic curve domain parameters
* Copyright (C) 2017-2018 J08nY
*/
+#include <misc/types.h>
#include "hex.h"
#include "exhaustive/arg.h"
#include "field.h"
#include "util/bits.h"
#include "util/memory.h"
+#include "util/str.h"
+
+static char *hex_point(point_t *point) {
+ GEN fx = field_elementi(gel(point->point, 1));
+ GEN fy = field_elementi(gel(point->point, 2));
+ char *fxs = pari_sprintf("%P0#*x", cfg->hex_digits, fx);
+ char *fxy = pari_sprintf("%P0#*x", cfg->hex_digits, fy);
+ char *result = str_joinv(",", fxs, fxy, NULL);
+ pari_free(fxs);
+ pari_free(fxy);
+ return result;
+}
static char *hex_points(point_t *points[], size_t len) {
char *p[len];
for (size_t i = 0; i < len; ++i) {
point_t *pt = points[i];
- GEN fx = field_elementi(gel(pt->point, 1));
- GEN fy = field_elementi(gel(pt->point, 2));
- p[i] = pari_sprintf("%P0#*x,%P0#*x,", cfg->hex_digits, fx,
- cfg->hex_digits, fy);
+ p[i] = hex_point(pt);
}
size_t total = 1;
@@ -26,7 +36,7 @@ static char *hex_points(point_t *points[], size_t len) {
char *result = try_calloc(total);
for (size_t i = 0; i < len; ++i) {
strcat(result, p[i]);
- pari_free(p[i]);
+ try_free(p[i]);
}
return result;
}
@@ -36,7 +46,7 @@ CHECK(hex_check_param) {
char *search_hex = try_strdup(args->args);
char *p = search_hex;
- for (; *p; ++p) *p = (char)tolower(*p);
+ for (; *p; ++p) *p = (char) tolower(*p);
char *params[OFFSET_END] = {NULL};
bool pari[OFFSET_END] = {false};
@@ -50,7 +60,7 @@ CHECK(hex_check_param) {
if (state >= OFFSET_FIELD) {
if (cfg->field == FIELD_PRIME) {
params[OFFSET_FIELD] =
- pari_sprintf("%P0#*x", cfg->hex_digits, curve->field);
+ pari_sprintf("%P0#*x", cfg->hex_digits, curve->field);
pari[OFFSET_FIELD] = true;
} else if (cfg->field == FIELD_BINARY) {
}
@@ -58,28 +68,42 @@ CHECK(hex_check_param) {
if (state >= OFFSET_A) {
params[OFFSET_A] =
- pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->a));
+ pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->a));
pari[OFFSET_A] = true;
}
if (state >= OFFSET_B) {
params[OFFSET_B] =
- pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->b));
+ pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->b));
pari[OFFSET_B] = true;
}
if (state >= OFFSET_ORDER) {
params[OFFSET_ORDER] =
- pari_sprintf("%P0#*x", cfg->hex_digits, curve->order);
+ pari_sprintf("%P0#*x", cfg->hex_digits, curve->order);
pari[OFFSET_ORDER] = true;
}
if (state >= OFFSET_GENERATORS) {
- params[OFFSET_GENERATORS] = hex_points(curve->generators, curve->ngens);
+ char *subgroups[curve->ngens];
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ subgroups[i] = hex_point(curve->generators[i]->generator);
+ }
+ params[OFFSET_GENERATORS] = str_join(",", subgroups, curve->ngens);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ try_free(subgroups[i]);
+ }
}
if (state >= OFFSET_POINTS) {
- params[OFFSET_POINTS] = hex_points(curve->points, curve->npoints);
+ char *subgroups[curve->ngens];
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ subgroups[i] = hex_points(curve->generators[i]->points, curve->generators[i]->npoints);
+ }
+ params[OFFSET_POINTS] = str_join(",", subgroups, curve->ngens);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ try_free(subgroups[i]);
+ }
}
int result = OFFSET_FIELD - state;
diff --git a/src/gen/order.c b/src/gen/order.c
index 16d597a..0c0779c 100644
--- a/src/gen/order.c
+++ b/src/gen/order.c
@@ -44,39 +44,23 @@ GENERATOR(order_gen_sea) {
}
}
-GENERATOR(order_gen_smallfact) {
+GENERATOR(order_gen_cofactor) {
HAS_ARG(args);
- pari_ulong smallfact = *(pari_ulong *)args->args;
+ pari_ulong cofactor = *(pari_ulong *)args->args;
pari_sp ltop = avma;
- GEN fact = mpfact(smallfact);
- pari_ulong lfact = 0;
- if (lgefint(fact) > 3) {
- lfact = 0;
- } else {
- lfact = itou(fact);
- }
-
- GEN order = ellsea(curve->curve, lfact);
- if (gequal0(order)) {
+ GEN order = ellff_get_card(curve->curve);
+ GEN res = cgeti(DEFAULTPREC);
+ if (!dvdiiz(order, utoi(cofactor), res)) {
avma = ltop;
- return -4;
+ return -4;
}
-
- GEN factors = factor(order);
- GEN primes = gel(factors, 1);
- GEN powers = gel(factors, 2);
- long len = glength(primes);
- GEN total = gen_1;
- for (long i = 1; i < len; ++i) {
- GEN pow = powii(gel(primes, i), gel(powers, i));
- total = mulii(total, pow);
- if (abscmpiu(total, smallfact) > 0) {
- avma = ltop;
- return -4;
- }
+ if (!isprime(res)) {
+ avma = ltop;
+ return -4;
}
+ verbose_log("cofactor");
- curve->order = gerepileupto(ltop, order);
+ curve->order = gerepilecopy(ltop, order);
obj_insert_shallow(curve->curve, 1, curve->order);
return 1;
}
diff --git a/src/gen/order.h b/src/gen/order.h
index 97d31ab..e77937f 100644
--- a/src/gen/order.h
+++ b/src/gen/order.h
@@ -48,11 +48,11 @@ GENERATOR(order_gen_sea);
* GENERATOR(gen_f)
*
* @param curve A curve_t being generated
- * @param args pari_ulong passed to ellsea(curve, smallfact)
+ * @param args pari_ulong the desired cofactor
* @param state
* @return state diff
*/
-GENERATOR(order_gen_smallfact);
+GENERATOR(order_gen_cofactor);
/**
* GENERATOR(gen_f)
diff --git a/src/gen/point.c b/src/gen/point.c
index 4d716e8..1f17d0f 100644
--- a/src/gen/point.c
+++ b/src/gen/point.c
@@ -4,9 +4,9 @@
*/
#include "point.h"
#include "exhaustive/arg.h"
-#include "io/output.h"
-#include "math/subgroups.h"
+#include "math/subgroup.h"
#include "util/memory.h"
+#include "util/random.h"
point_t *point_new(void) { return try_calloc(sizeof(point_t)); }
@@ -93,74 +93,85 @@ void points_free_deep(point_t ***points, size_t npoints) {
}
GENERATOR(point_gen_random) {
- point_t *p = point_new();
- p->point = genrand(curve->curve);
- p->order = ellorder(curve->curve, p->point, NULL);
+ long which_gen = itos(random_range(gen_0, stoi(curve->ngens)));
- curve->points = points_new(1);
- curve->points[0] = p;
- curve->npoints = 1;
+ subgroup_t *subgroup = curve->generators[which_gen];
+ GEN mul = random_range(gen_0, subgroup->generator->order);
+ GEN p = ellmul(curve->curve, subgroup->generator->point, mul);
+ point_t *point = point_new();
+ point->point = p;
+ point->order = ellorder(curve->curve, p, NULL);
+ subgroup->npoints = 1;
+ subgroup->points = points_new(1);
+ subgroup->points[0] = point;
return 1;
}
GENERATOR(points_gen_random) {
HAS_ARG(args);
- size_t npoints = *(size_t *)args->args;
+ size_t npoints = *(size_t *) args->args;
+ size_t npoints_per_gen[curve->ngens];
+
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ npoints_per_gen[i] = 0;
+ }
- curve->points = points_new(npoints);
- curve->npoints = npoints;
for (size_t i = 0; i < npoints; ++i) {
- point_t *p = point_new();
- p->point = genrand(curve->curve);
- p->order = ellorder(curve->curve, p->point, NULL);
- curve->points[i] = p;
+ long which_gen = itos(random_range(gen_0, stoi(curve->ngens)));
+ npoints_per_gen[which_gen]++;
}
- return 1;
-}
-static int points_from_orders(curve_t *curve, GEN orders) {
- // TODO better stack code
- size_t norders = (size_t)glength(orders);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ subgroup_t *subgroup = curve->generators[i];
+ subgroup->npoints = npoints_per_gen[i];
+ subgroup->points = points_new(npoints_per_gen[i]);
- curve->points = points_new(norders);
- curve->npoints = norders;
+ for (size_t j = 0; j < npoints_per_gen[i]; ++j) {
+ GEN mul = random_range(gen_0, subgroup->generator->order);
+ GEN p = ellmul(curve->curve, subgroup->generator->point, mul);
+ point_t *point = point_new();
+ point->point = p;
+ point->order = ellorder(curve->curve, p, NULL);
+ subgroup->points[j] = point;
+ }
+ }
+ return 1;
+}
- for (size_t ngen = 0; ngen < curve->ngens; ++ngen) {
- point_t *gen = curve->generators[ngen];
+static point_t **points_from_orders(GEN curve, point_t *generator, GEN orders) {
+ size_t norders = (size_t) glength(orders);
+ point_t **result = points_new(norders);
- for (long i = 0; i < norders; ++i) {
- GEN num = gel(orders, i + 1);
- if (curve->points[i] == NULL) {
- pari_sp ftop = avma;
+ for (long i = 0; i < norders; ++i) {
+ pari_sp ftop = avma;
+ GEN num = gel(orders, i + 1);
- GEN point = NULL;
- if (equalii(gen->order, num)) {
- point = gcopy(gen->point);
- } else if (dvdii(gen->order, num)) {
- GEN mul = divii(gen->order, num);
- point = ellmul(curve->curve, gen->point, mul);
- }
+ GEN point = NULL;
+ if (equalii(generator->order, num)) {
+ point = gcopy(generator->point);
+ } else if (dvdii(generator->order, num)) {
+ GEN mul = divii(generator->order, num);
+ point = ellmul(curve, generator->point, mul);
+ }
- if (point) {
- debug_log("VERIFY %Ps %Ps", num,
- ellorder(curve->curve, point, NULL));
- curve->points[i] = point_new();
- gerepileall(ftop, 1, &point);
- curve->points[i]->point = point;
- curve->points[i]->order = gcopy(num);
- }
- }
+ if (point) {
+ debug_log("VERIFY %Ps %Ps", num,
+ ellorder(curve, point, NULL));
+ result[i] = point_new();
+ gerepileall(ftop, 1, &point);
+ result[i]->point = point;
+ result[i]->order = gcopy(num);
}
}
- return 1;
+ return result;
}
GENERATOR(points_gen_trial) {
HAS_ARG(args);
- pari_ulong *primes = (pari_ulong *)args->args;
+ pari_ulong *primes = (pari_ulong *) args->args;
size_t nprimes = args->nargs;
GEN orders = gtovec0(gen_0, nprimes);
@@ -168,32 +179,78 @@ GENERATOR(points_gen_trial) {
gel(orders, i) = utoi(primes[i - 1]);
}
- return points_from_orders(curve, orders);
+ GEN orders_per_gen[curve->ngens];
+
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ orders_per_gen[i] = gen_0;
+ }
+
+ for (size_t j = 0; j < nprimes; ++j) {
+ GEN num = gel(orders, j + 1);
+
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ point_t *gen = curve->generators[i]->generator;
+ if (equalii(gen->order, num) || dvdii(gen->order, num)) {
+ if (orders_per_gen[i] == gen_0) {
+ orders_per_gen[i] = gtovec(num);
+ } else {
+ vec_append(orders_per_gen[i], num);
+ }
+ break;
+ }
+ }
+ debug_log("Should not happen.");
+ }
+
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ subgroup_t *subgroup = curve->generators[i];
+ if (orders_per_gen[i] != gen_0) {
+ subgroup->npoints = (size_t) glength(orders_per_gen[i]);
+ subgroup->points = points_from_orders(curve->curve, subgroup->generator, orders_per_gen[i]);
+ }
+ }
+
+ return 1;
}
GENERATOR(points_gen_prime) {
- GEN primes = subgroups_prime(curve);
- return points_from_orders(curve, primes);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ GEN primes = subgroups_prime(curve->generators[i]->generator->order);
+ curve->generators[i]->npoints = (size_t) glength(primes);
+ curve->generators[i]->points = points_from_orders(curve->curve, curve->generators[i]->generator, primes);
+ }
+
+ return 1;
}
GENERATOR(points_gen_allgroups) {
- GEN groups = subgroups_all(curve);
- return points_from_orders(curve, groups);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ GEN primes = subgroups_all(curve->generators[i]->generator->order);
+ curve->generators[i]->npoints = (size_t) glength(primes);
+ curve->generators[i]->points = points_from_orders(curve->curve, curve->generators[i]->generator, primes);
+ }
+
+ return 1;
}
GENERATOR(points_gen_nonprime) {
- GEN groups = subgroups_nonprime(curve);
- if (!groups) {
- // No non-prime order points on curve.
- return 1;
- } else {
- return points_from_orders(curve, groups);
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ GEN primes = subgroups_nonprime(curve->generators[i]->generator->order);
+ if (primes) {
+ curve->generators[i]->npoints = (size_t) glength(primes);
+ curve->generators[i]->points = points_from_orders(curve->curve, curve->generators[i]->generator, primes);
+ }
}
+
+ return 1;
}
UNROLL(points_unroll) {
- if (curve->points) {
- points_free_deep(&curve->points, curve->npoints);
+ if (curve->generators) {
+ for (size_t i = 0; i < curve->ngens; ++i) {
+ points_free_deep(&curve->generators[i]->points, curve->generators[i]->npoints);
+ }
+
}
return -1;
}
diff --git a/src/gen/point.h b/src/gen/point.h
index c411dee..c97e738 100644
--- a/src/gen/point.h
+++ b/src/gen/point.h
@@ -66,7 +66,7 @@ point_t **points_new(size_t num);
* @param num
* @return
*/
-point_t **points_copy(point_t **const src, point_t **dest, size_t num);
+point_t **points_copy(point_t **src, point_t **dest, size_t num);
/**
*
@@ -74,7 +74,7 @@ point_t **points_copy(point_t **const src, point_t **dest, size_t num);
* @param num
* @return
*/
-point_t **points_new_copy(point_t **const src, size_t num);
+point_t **points_new_copy(point_t **src, size_t num);
/**
*
@@ -83,7 +83,7 @@ point_t **points_new_copy(point_t **const src, size_t num);
* @param num
* @return
*/
-point_t **points_clone(point_t **const src, point_t **dest, size_t num);
+point_t **points_clone(point_t **src, point_t **dest, size_t num);
/**
*
@@ -91,7 +91,7 @@ point_t **points_clone(point_t **const src, point_t **dest, size_t num);
* @param num
* @return
*/
-point_t **points_new_clone(point_t **const src, size_t num);
+point_t **points_new_clone(point_t **src, size_t num);
/**
*
diff --git a/src/io/cli.c b/src/io/cli.c
index c192021..ae11836 100644
--- a/src/io/cli.c
+++ b/src/io/cli.c
@@ -24,7 +24,6 @@ enum opt_keys {
OPT_ORDER = 'n',
OPT_KOBLITZ = 'K',
OPT_UNIQUE = 'u',
- OPT_FORMAT = 't',
OPT_OUTPUT = 'o',
OPT_INPUT = 'f',
OPT_APPEND = 'a',
@@ -37,8 +36,6 @@ enum opt_keys {
OPT_TSTACK,
OPT_TIMEOUT,
OPT_ANOMALOUS,
- OPT_GPGEN,
- OPT_GPCHECK,
OPT_HEXCHECK,
OPT_BRAINPOOL_RFC,
OPT_TWIST,
@@ -62,11 +59,9 @@ struct argp_option cli_options[] = {
{0, 0, 0, 0, "Generation options:", 3},
{"random", OPT_RANDOM, 0, 0, "Generate a random curve (using Random approach).", 3},
{"prime", OPT_PRIME, 0, 0, "Generate a curve with prime order.", 3},
- {"cofactor", OPT_COFACTOR, "BOUND", 0, "Generate a curve with cofactor up to BOUND.", 3},
+ {"cofactor", OPT_COFACTOR, "VALUE", 0, "Generate a curve with cofactor of VALUE.", 3},
{"koblitz", OPT_KOBLITZ, "A", OPTION_ARG_OPTIONAL, "Generate a Koblitz curve (a in {0, 1}, b = 1).", 3},
{"unique", OPT_UNIQUE, 0, 0, "Generate a curve with only one generator.", 3},
- {"gp-gen", OPT_GPGEN, "FUNC", 0, "Generate a curve param using a GP function. **NOT IMPLEMENTED**", 3},
- {"gp-check", OPT_GPCHECK, "FUNC", 0, "Check a generated curve param using a GP function. **NOT IMPLEMENTED**", 3},
{"hex-check", OPT_HEXCHECK, "HEX", 0, "Check a generated curve param hex expansion for the HEX string.", 3},
{"points", OPT_POINTS, "TYPE", 0, "Generate points of given type (random/prime/all/nonprime/none).", 3},
{"count", OPT_COUNT, "COUNT", 0, "Generate multiple curves.", 3},
@@ -275,7 +270,7 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
break;
case OPT_COFACTOR:
cfg->cofactor = true;
- cfg->cofactor_bound = strtol(arg, NULL, 10);
+ cfg->cofactor_value = strtol(arg, NULL, 10);
break;
case OPT_KOBLITZ:
cfg->koblitz = true;
@@ -290,12 +285,6 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
case OPT_UNIQUE:
cfg->unique = true;
break;
- case OPT_GPGEN:
- cfg->gp_gens[cfg->gp_gens_size++] = arg;
- break;
- case OPT_GPCHECK:
- cfg->gp_checks[cfg->gp_checks_size++] = arg;
- break;
case OPT_HEXCHECK: {
char *str_start = arg;
if (strlen(arg) > 2) {
diff --git a/src/io/output.c b/src/io/output.c
index 4d8fca0..6fb82d3 100644
--- a/src/io/output.c
+++ b/src/io/output.c
@@ -19,6 +19,34 @@ char *output_malloc(const char *what) {
return s;
}
+
+static JSON_Value *output_json_point(point_t *point) {
+ JSON_Value *point_value = json_value_init_object();
+ JSON_Object *point_object = json_value_get_object(point_value);
+
+ char *x = pari_sprintf(
+ "%P0#*x", cfg->hex_digits,
+ field_elementi(gel(point->point, 1)));
+ json_object_set_string(point_object, "x", x);
+ pari_free(x);
+ char *y = pari_sprintf(
+ "%P0#*x", cfg->hex_digits,
+ field_elementi(gel(point->point, 2)));
+ json_object_set_string(point_object, "y", y);
+ pari_free(y);
+ char *p_order = pari_sprintf("%P#x", point->order);
+ json_object_set_string(point_object, "order", p_order);
+ pari_free(p_order);
+ if (point->cofactor) {
+ char *cofactor =
+ pari_sprintf("%P#x", point->cofactor);
+ json_object_set_string(point_object, "cofactor", cofactor);
+ pari_free(cofactor);
+ }
+
+ return point_value;
+}
+
static JSON_Value *output_jjson(curve_t *curve) {
pari_sp ltop = avma;
// root object/value is curve
@@ -77,68 +105,22 @@ static JSON_Value *output_jjson(curve_t *curve) {
JSON_Array *gens_array = json_value_get_array(gens_value);
for (size_t i = 0; i < curve->ngens; ++i) {
- JSON_Value *point_value = json_value_init_object();
- JSON_Object *point_object = json_value_get_object(point_value);
+ JSON_Value *gen_value = output_json_point(curve->generators[i]->generator);
+ JSON_Object *gen_object = json_value_get_object(gen_value);
- char *x = pari_sprintf(
- "%P0#*x", cfg->hex_digits,
- field_elementi(gel(curve->generators[i]->point, 1)));
- json_object_set_string(point_object, "x", x);
- pari_free(x);
- char *y = pari_sprintf(
- "%P0#*x", cfg->hex_digits,
- field_elementi(gel(curve->generators[i]->point, 2)));
- json_object_set_string(point_object, "y", y);
- pari_free(y);
- char *p_order = pari_sprintf("%P#x", curve->generators[i]->order);
- json_object_set_string(point_object, "order", p_order);
- pari_free(p_order);
- if (curve->generators[i]->cofactor) {
- char *cofactor =
- pari_sprintf("%P#x", curve->generators[i]->cofactor);
- json_object_set_string(point_object, "cofactor", cofactor);
- pari_free(cofactor);
+ if (curve->generators[i]->npoints) {
+ JSON_Value *gens_points_value = json_value_init_array();
+ JSON_Array *gens_points_array = json_value_get_array(gens_points_value);
+ for (size_t j = 0; j < curve->generators[i]->npoints; ++j) {
+ json_array_append_value(gens_points_array, output_json_point(curve->generators[i]->points[j]));
+ }
+ json_object_set_value(gen_object, "points", gens_points_value);
}
-
- json_array_append_value(gens_array, point_value);
+ json_array_append_value(gens_array, gen_value);
}
-
- json_object_set_value(root_object, "generators", gens_value);
+ json_object_set_value(root_object, "subgroups", gens_value);
}
- if (curve->npoints) {
- JSON_Value *points_value = json_value_init_array();
- JSON_Array *points_array = json_value_get_array(points_value);
-
- for (size_t i = 0; i < curve->npoints; ++i) {
- JSON_Value *point_value = json_value_init_object();
- JSON_Object *point_object = json_value_get_object(point_value);
-
- char *x =
- pari_sprintf("%P0#*x", cfg->hex_digits,
- field_elementi(gel(curve->points[i]->point, 1)));
- json_object_set_string(point_object, "x", x);
- pari_free(x);
- char *y =
- pari_sprintf("%P0#*x", cfg->hex_digits,
- field_elementi(gel(curve->points[i]->point, 2)));
- json_object_set_string(point_object, "y", y);
- pari_free(y);
- char *p_order = pari_sprintf("%P#x", curve->points[i]->order);
- json_object_set_string(point_object, "order", p_order);
- pari_free(p_order);
- if (curve->points[i]->cofactor) {
- char *cofactor =
- pari_sprintf("%P#x", curve->points[i]->cofactor);
- json_object_set_string(point_object, "cofactor", cofactor);
- pari_free(cofactor);
- }
-
- json_array_append_value(points_array, point_value);
- }
-
- json_object_set_value(root_object, "points", points_value);
- }
avma = ltop;
return root_value;
}
diff --git a/src/math/subgroup.c b/src/math/subgroup.c
new file mode 100644
index 0000000..3d78db5
--- /dev/null
+++ b/src/math/subgroup.c
@@ -0,0 +1,237 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017-2018 J08nY
+ */
+#include "gen/point.h"
+#include "subgroup.h"
+#include "util/memory.h"
+
+subgroup_t *subgroup_new(void) {
+ return try_calloc(sizeof(subgroup_t));
+}
+
+subgroup_t *subgroup_copy(const subgroup_t *src, subgroup_t *dst) {
+ if (src->generator)
+ dst->generator = point_new_copy(src->generator);
+ if (src->points) {
+ dst->points = points_new_copy(src->points, src->npoints);
+ dst->npoints = src->npoints;
+ }
+ return dst;
+}
+
+subgroup_t *subgroup_new_copy(const subgroup_t *src) {
+ subgroup_t *result = subgroup_new();
+ return subgroup_copy(src, result);
+}
+
+subgroup_t *subgroup_clone(const subgroup_t *src, subgroup_t *dst) {
+ if (src->generator)
+ dst->generator = point_new_clone(src->generator);
+ if (src->points) {
+ dst->points = points_new_clone(src->points, src->npoints);
+ dst->npoints = src->npoints;
+ }
+ return dst;
+}
+
+subgroup_t *subgroup_new_clone(const subgroup_t *src) {
+ subgroup_t *result = subgroup_new();
+ return subgroup_clone(src, result);
+}
+
+void subgroup_free(subgroup_t **subgroup) {
+ if (*subgroup) {
+ if ((*subgroup)->generator) {
+ point_free(&(*subgroup)->generator);
+ }
+ try_free(*subgroup);
+ *subgroup = NULL;
+ }
+}
+
+void subgroup_free_deep(subgroup_t **subgroup) {
+ if (*subgroup) {
+ points_free_deep(&(*subgroup)->points, (*subgroup)->npoints);
+ subgroup_free(subgroup);
+ }
+}
+
+subgroup_t **subgroups_new(size_t num) {
+ return try_calloc(num * sizeof(subgroup_t *));
+}
+
+subgroup_t **subgroups_copy(subgroup_t **const src, subgroup_t **dest, size_t num) {
+ for (size_t i = 0; i < num; ++i) {
+ dest[i] = subgroup_new_copy(src[i]);
+ }
+ return dest;
+}
+
+subgroup_t **subgroups_new_copy(subgroup_t **const src, size_t num) {
+ subgroup_t **result = subgroups_new(num);
+ return subgroups_copy(src, result, num);
+}
+
+subgroup_t **subgroups_clone(subgroup_t **const src, subgroup_t **dest, size_t num) {
+ for (size_t i = 0; i < num; ++i) {
+ dest[i] = subgroup_new_clone(src[i]);
+ }
+ return dest;
+}
+
+subgroup_t **subgroups_new_clone(subgroup_t **const src, size_t num) {
+ subgroup_t **result = subgroups_new(num);
+ return subgroups_clone(src, result, num);
+}
+
+void subgroups_free(subgroup_t ***subgroups) {
+ if (*subgroups) {
+ try_free(*subgroups);
+ *subgroups = NULL;
+ }
+}
+
+void subgroups_free_deep(subgroup_t ***subgroups, size_t num) {
+ if (*subgroups) {
+ for (size_t i = 0; i < num; ++i) {
+ subgroup_free(&(*subgroups)[i]);
+ }
+ subgroups_free(subgroups);
+ }
+}
+
+/**
+ * @brief All prime divisors of a given integer with multiplicity.
+ *
+ * subgroups_divisors(27) = [3, 3, 3]
+ * @param order
+ * @return a t_VEC of prime divisors.
+ */
+static GEN subgroups_divisors(GEN order) {
+ GEN factors = Z_factor(order);
+ GEN primes = gel(factors, 1);
+ GEN multiples = gel(factors, 2);
+ long uniqs = glength(primes);
+
+ long size = 0;
+ for (long i = 1; i <= uniqs; ++i) {
+ size += itos(gel(multiples, i));
+ }
+ GEN result = gtovec0(gen_0, size);
+
+ long count = 0;
+ for (long i = 1; i <= uniqs; ++i) {
+ long multiple = itos(gel(multiples, i));
+ for (long j = 1; j <= multiple; ++j) {
+ gel(result, ++count) = gel(primes, i);
+ }
+ }
+ return result;
+}
+
+/**
+ * @brief All factors consisting of at least <code>min_bits</code> prime
+ * <code>factors</code>.
+ *
+ * @param factors
+ * @param min_bits
+ * @return a t_VEC of factors
+ */
+static GEN subgroups_2n_factors(GEN factors, size_t min_bits) {
+ pari_sp ltop = avma;
+ long nprimes = glength(factors);
+ if (nprimes == min_bits) return NULL;
+ GEN amount = int2n(nprimes);
+ GEN groups = gtovec0(gen_0, itos(amount) - (min_bits * nprimes) - 1);
+
+ size_t i = 0;
+ for (size_t count = 1; count < (size_t) (1) << nprimes; ++count) {
+ pari_sp btop = avma;
+ GEN result = gen_1;
+ size_t bits = 0;
+ for (long bit = 0; bit < nprimes; ++bit) {
+ size_t mask = (size_t) (1) << bit;
+ if (count & mask) {
+ result = mulii(result, gel(factors, bit + 1));
+ bits++;
+ }
+ }
+ if (bits > min_bits) {
+ gel(groups, ++i) = result;
+ } else {
+ avma = btop;
+ }
+ }
+ GEN ret = gtoset(groups);
+ return gerepilecopy(ltop, ret);
+}
+
+GEN subgroups_prime(GEN order) {
+ GEN factors = Z_factor(order);
+ return gtovec(gel(factors, 1));
+}
+
+GEN subgroups_nonprime(GEN order) {
+ if (isprime(order)) {
+ return NULL;
+ }
+ GEN factors = subgroups_divisors(order);
+ return subgroups_2n_factors(factors, 1);
+}
+
+GEN subgroups_all(GEN order) {
+ if (isprime(order)) {
+ return gtovec(order);
+ }
+ GEN factors = subgroups_divisors(order);
+ return subgroups_2n_factors(factors, 0);
+}
+
+/**
+ * @brief
+ * @param curve
+ * @param min_bits
+ * @return
+ */
+/*
+static GEN subgroups_2n_gens(const curve_t *curve, size_t min_bits) {
+ GEN one_factors = subgroups_divisors(curve->generators[0]->order);
+ GEN one = subgroups_2n_factors(one_factors, min_bits);
+ GEN other_factors = subgroups_divisors(curve->generators[1]->order);
+ GEN other = subgroups_2n_factors(other_factors, min_bits);
+ if (!one) {
+ return other;
+ }
+ if (!other) {
+ return one;
+ }
+ GEN result = gtovec0(gen_0, glength(one) + glength(other));
+ for (long i = 1; i <= glength(result); ++i) {
+ if (i <= glength(one)) {
+ gel(result, i) = gel(one, i);
+ } else {
+ gel(result, i) = gel(other, i - glength(one));
+ }
+ }
+ return result;
+}
+ */
+
+/**
+ * @brief
+ * @param curve
+ * @param min_bits
+ * @return
+ */
+/*
+static GEN subgroups_2n(const curve_t *curve, size_t min_bits) {
+ if (curve->ngens == 1) {
+ GEN factors = subgroups_divisors(curve->order);
+ return subgroups_2n_factors(factors, min_bits);
+ }
+
+ return subgroups_2n_gens(curve, min_bits);
+}
+
+*/ \ No newline at end of file
diff --git a/src/math/subgroup.h b/src/math/subgroup.h
new file mode 100644
index 0000000..ad36826
--- /dev/null
+++ b/src/math/subgroup.h
@@ -0,0 +1,139 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017-2018 J08nY
+ */
+/**
+ * @file subgroup.h
+ */
+#ifndef ECGEN_SUBGROUPS_H
+#define ECGEN_SUBGROUPS_H
+
+#include <pari/pari.h>
+#include "misc/types.h"
+
+/**
+ * @brief
+ * @return
+ */
+subgroup_t *subgroup_new(void);
+
+/**
+ * @brief
+ * @param src
+ * @param dst
+ * @return
+ */
+subgroup_t *subgroup_copy(const subgroup_t *src, subgroup_t *dst);
+
+/**
+ * @brief
+ * @param src
+ * @return
+ */
+subgroup_t *subgroup_new_copy(const subgroup_t *src);
+
+/**
+ * @brief
+ * @param src
+ * @param dst
+ * @return
+ */
+subgroup_t *subgroup_clone(const subgroup_t *src, subgroup_t *dst);
+
+/**
+ * @brief
+ * @param src
+ * @return
+ */
+subgroup_t *subgroup_new_clone(const subgroup_t *src);
+
+/**
+ * @brief
+ * @param subgroup
+ */
+void subgroup_free(subgroup_t **subgroup);
+
+/**
+ * @brief
+ * @param subgroup
+ */
+void subgroup_free_deep(subgroup_t **subgroup);
+
+/**
+ * @brief
+ * @param num
+ * @return
+ */
+subgroup_t **subgroups_new(size_t num);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @param num
+ * @return
+ */
+subgroup_t **subgroups_copy(subgroup_t **src, subgroup_t **dest, size_t num);
+
+/**
+ *
+ * @param src
+ * @param num
+ * @return
+ */
+subgroup_t **subgroups_new_copy(subgroup_t **src, size_t num);
+
+/**
+ *
+ * @param src
+ * @param dest
+ * @param num
+ * @return
+ */
+subgroup_t **subgroups_clone(subgroup_t **src, subgroup_t **dest, size_t num);
+
+/**
+ *
+ * @param src
+ * @param num
+ * @return
+ */
+subgroup_t **subgroups_new_clone(subgroup_t **src, size_t num);
+
+/**
+ * @brief
+ * @param subgroups
+ */
+void subgroups_free(subgroup_t ***subgroups);
+
+/**
+ * @brief
+ * @param subgroups
+ * @param num
+ */
+void subgroups_free_deep(subgroup_t ***subgroups, size_t num);
+
+/**
+ * @brief All prime factors of a given integer, without multipliticity.
+ *
+ * subgroups_factors(27) = [3]
+ * @param order
+ * @return a t_VEC of prime factors.
+ */
+GEN subgroups_prime(GEN order);
+
+/**
+ * @brief All nonprime subgroup orders of a given integer.
+ * @param order
+ * @return a t_VEC of nonprime factors.
+ */
+GEN subgroups_nonprime(GEN order);
+
+/**
+ * @brief All all subgroup orders of a given integer.
+ * @param order
+ * @return a t_VEC of all factors.
+ */
+GEN subgroups_all(GEN order);
+
+#endif // ECGEN_SUBGROUPS_H
diff --git a/src/math/subgroups.c b/src/math/subgroups.c
deleted file mode 100644
index 8fe3918..0000000
--- a/src/math/subgroups.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * ecgen, tool for generating Elliptic curve domain parameters
- * Copyright (C) 2017-2018 J08nY
- */
-#include "subgroups.h"
-
-/**
- * @brief All prime factors of a given integer.
- *
- * subgroups_factors(27) = [3]
- * @param order
- * @return a t_VEC of prime factors.
- */
-static GEN subgroups_factors(GEN order) {
- GEN factors = Z_factor(order);
- return gtovec(gel(factors, 1));
-}
-
-/**
- * @brief All prime divisors of a given integer with multiplicity.
- *
- * subgroups_divisors(27) = [3, 3, 3]
- * @param order
- * @return a t_VEC of prime divisors.
- */
-static GEN subgroups_divisors(GEN order) {
- GEN factors = Z_factor(order);
- GEN primes = gel(factors, 1);
- GEN multiples = gel(factors, 2);
- long uniqs = glength(primes);
-
- long size = 0;
- for (long i = 1; i <= uniqs; ++i) {
- size += itos(gel(multiples, i));
- }
- GEN result = gtovec0(gen_0, size);
-
- long count = 0;
- for (long i = 1; i <= uniqs; ++i) {
- long multiple = itos(gel(multiples, i));
- for (long j = 1; j <= multiple; ++j) {
- gel(result, ++count) = gel(primes, i);
- }
- }
- return result;
-}
-
-/**
- * @brief All factors consisting of at least <code>min_bits</code> prime
- * <code>factors</code>.
- *
- * @param factors
- * @param min_bits
- * @return a t_VEC of factors
- */
-static GEN subgroups_2n_factors(GEN factors, size_t min_bits) {
- pari_sp ltop = avma;
- long nprimes = glength(factors);
- if (nprimes == min_bits) return NULL;
- GEN amount = int2n(nprimes);
- GEN groups = gtovec0(gen_0, itos(amount) - (min_bits * nprimes) - 1);
-
- size_t i = 0;
- for (size_t count = 1; count < (size_t)(1) << nprimes; ++count) {
- pari_sp btop = avma;
- GEN result = gen_1;
- size_t bits = 0;
- for (long bit = 0; bit < nprimes; ++bit) {
- size_t mask = (size_t)(1) << bit;
- if (count & mask) {
- result = mulii(result, gel(factors, bit + 1));
- bits++;
- }
- }
- if (bits > min_bits) {
- gel(groups, ++i) = result;
- } else {
- avma = btop;
- }
- }
- GEN ret = gtoset(groups);
- return gerepilecopy(ltop, ret);
-}
-
-/**
- * @brief
- * @param curve
- * @param min_bits
- * @return
- */
-static GEN subgroups_2n_gens(const curve_t *curve, size_t min_bits) {
- GEN one_factors = subgroups_divisors(curve->generators[0]->order);
- GEN one = subgroups_2n_factors(one_factors, min_bits);
- GEN other_factors = subgroups_divisors(curve->generators[1]->order);
- GEN other = subgroups_2n_factors(other_factors, min_bits);
- if (!one) {
- return other;
- }
- if (!other) {
- return one;
- }
- GEN result = gtovec0(gen_0, glength(one) + glength(other));
- for (long i = 1; i <= glength(result); ++i) {
- if (i <= glength(one)) {
- gel(result, i) = gel(one, i);
- } else {
- gel(result, i) = gel(other, i - glength(one));
- }
- }
- return result;
-}
-
-/**
- * @brief
- * @param curve
- * @param min_bits
- * @return
- */
-static GEN subgroups_2n(const curve_t *curve, size_t min_bits) {
- if (curve->ngens == 1) {
- GEN factors = subgroups_divisors(curve->order);
- return subgroups_2n_factors(factors, min_bits);
- }
-
- return subgroups_2n_gens(curve, min_bits);
-}
-
-GEN subgroups_prime(const curve_t *curve) {
- if (cfg->prime || isprime(curve->order)) {
- return gtovec(curve->order);
- }
-
- return subgroups_factors(curve->order);
-}
-
-GEN subgroups_nonprime(const curve_t *curve) {
- if (cfg->prime || isprime(curve->order)) {
- return NULL;
- }
-
- return subgroups_2n(curve, 1);
-}
-
-GEN subgroups_all(const curve_t *curve) {
- if (cfg->prime || isprime(curve->order)) {
- return gtovec(curve->order);
- }
-
- return subgroups_2n(curve, 0);
-}
diff --git a/src/math/subgroups.h b/src/math/subgroups.h
deleted file mode 100644
index e08bfa5..0000000
--- a/src/math/subgroups.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * ecgen, tool for generating Elliptic curve domain parameters
- * Copyright (C) 2017-2018 J08nY
- */
-/**
- * @file subgroups.h
- */
-#ifndef ECGEN_SUBGROUPS_H
-#define ECGEN_SUBGROUPS_H
-
-#include <pari/pari.h>
-#include "misc/types.h"
-
-/**
- * @brief Enumerates prime subgroup orders of a given curve.
- * @param curve
- * @return
- */
-GEN subgroups_prime(const curve_t *curve);
-
-/**
- * @brief Enumerates nonprime subgroup orders of a given curve.
- * @param curve
- * @return
- */
-GEN subgroups_nonprime(const curve_t *curve);
-
-/**
- * @brief Enumerates all subgroup orders of a given curve.
- * @param curve
- * @return
- */
-GEN subgroups_all(const curve_t *curve);
-
-#endif // ECGEN_SUBGROUPS_H
diff --git a/src/math/twists.c b/src/math/twists.c
index 043594f..a6bb06d 100644
--- a/src/math/twists.c
+++ b/src/math/twists.c
@@ -3,7 +3,7 @@
* Copyright (C) 2017-2018 J08nY
*/
#include "twists.h"
-#include "gen/point.h"
+#include "math/subgroup.h"
#include "gen/seed.h"
void twist_rand_to(curve_t *to, const curve_t *of) {
@@ -32,6 +32,5 @@ void twist_rand_to(curve_t *to, const curve_t *of) {
void twist_rand(curve_t *what) {
twist_rand_to(what, what);
seed_free(&what->seed);
- points_free_deep(&what->points, what->npoints);
- points_free_deep(&what->generators, what->ngens);
+ subgroups_free_deep(&what->generators, what->ngens);
} \ No newline at end of file
diff --git a/src/misc/config.h b/src/misc/config.h
index 9a8f8af..ab5b0ba 100644
--- a/src/misc/config.h
+++ b/src/misc/config.h
@@ -71,7 +71,7 @@ typedef struct {
long koblitz_value;
/** @brief Whether the curves should have a bound on the cofactor value. */
bool cofactor;
- long cofactor_bound;
+ long cofactor_value;
/** @brief What seed algorithm, if any, to use to generate the curves. */
seed_e seed_algo;
/** @brief What seed to use, if any, to generate the curves. */
diff --git a/src/misc/types.h b/src/misc/types.h
index 1e74e04..f2e5ae2 100644
--- a/src/misc/types.h
+++ b/src/misc/types.h
@@ -67,6 +67,18 @@ typedef struct {
} point_t;
/**
+ * @brief A subgroup type.
+ * @param generator a point generating the subgroup
+ * @param npoints number of points stored in the subgroup
+ * @param points the stored points
+ */
+typedef struct {
+ point_t *generator;
+ size_t npoints;
+ point_t **points;
+} subgroup_t;
+
+/**
* @brief A curve type.
* @param seed a seed_t
* @param field a t_INT or t_FFELT
@@ -75,9 +87,7 @@ typedef struct {
* @param curve a t_ELL, curve object
* @param order a t_INT, curve order
* @param generators generators saved
- * @param ngens numver of generators saved in the curve type
- * @param points points saved
- * @param npoints number of points saved in the curve type
+ * @param ngens number of generators saved in the curve type
*/
typedef struct {
seed_t *seed;
@@ -86,10 +96,8 @@ typedef struct {
GEN b;
GEN curve;
GEN order;
- point_t **generators;
+ subgroup_t **generators;
size_t ngens;
- point_t **points;
- size_t npoints;
} curve_t;
/**
@@ -126,7 +134,7 @@ typedef struct {
* @return state diff
*/
#define GENERATOR(gen_name) \
- int gen_name(curve_t *curve, arg_t *args, offset_e state)
+ int gen_name(curve_t *curve, arg_t *args, offset_e state)
typedef GENERATOR((*gen_f));
@@ -138,7 +146,7 @@ typedef GENERATOR((*gen_f));
* @return
*/
#define UNROLL(unroll_name) \
- int unroll_name(curve_t *curve, pari_sp from, pari_sp to)
+ int unroll_name(curve_t *curve, pari_sp from, pari_sp to)
typedef UNROLL((*unroll_f));
diff --git a/src/util/random.c b/src/util/random.c
index 860cff0..eaeceaf 100644
--- a/src/util/random.c
+++ b/src/util/random.c
@@ -62,6 +62,16 @@ GEN random_int(unsigned long bits) {
return gerepilecopy(ltop, genrand(range));
}
+GEN random_range(GEN lower, GEN upper) {
+ pari_sp ltop = avma;
+ if (gequal(lower, upper)) {
+ return gcopy(lower);
+ }
+
+ GEN range = mkvec2(lower, subis(upper, 1));
+ return gerepilecopy(ltop, genrand(range));
+}
+
GEN random_field_element(GEN field) {
switch (typ(field)) {
case t_INT:
diff --git a/src/util/random.h b/src/util/random.h
index 56e2efd..f5844da 100644
--- a/src/util/random.h
+++ b/src/util/random.h
@@ -30,6 +30,14 @@ bool random_init(void);
GEN random_prime(unsigned long bits);
/**
+ * @brief
+ * @param lower
+ * @param upper
+ * @return
+ */
+GEN random_range(GEN lower, GEN upper);
+
+/**
* @brief Generate random <code>bits</code> sized integer.
* @param bits the size of the integer to generate
* @return a random integer in range [2^(bits - 1), 2^bits]
diff --git a/src/util/str.c b/src/util/str.c
index f213c99..8b1bf92 100644
--- a/src/util/str.c
+++ b/src/util/str.c
@@ -5,6 +5,7 @@
#include "str.h"
#include <ctype.h>
#include <string.h>
+#include <stdarg.h>
#include "util/memory.h"
const char *str_is_hex(const char *hex_str) {
@@ -22,16 +23,47 @@ const char *str_is_hex(const char *hex_str) {
return str_start;
}
-char *str_join(char *strings[], size_t len) {
- size_t total = 0;
+char *str_join(char *separator, char **strings, size_t len) {
+ size_t total = 1;
for (size_t i = 0; i < len; ++i) {
if (strings[i]) total += strlen(strings[i]);
}
+ if (separator)
+ total += (len - 1) * strlen(separator);
char *result = try_calloc(total);
for (size_t i = 0; i < len; ++i) {
if (strings[i]) {
strcat(result, strings[i]);
}
+ if (separator && i != len - 1) {
+ strcat(result, separator);
+ }
+ }
+ return result;
+}
+
+char *str_joinv(char *separator, ...) {
+ va_list valist;
+ va_start(valist, separator);
+
+ size_t len = 5;
+ char **strings = try_malloc(len * sizeof(char *));
+ char *next;
+ size_t i = 0;
+ while ((next = va_arg(valist, char *)) != NULL) {
+ if (i == len) {
+ strings = try_realloc(strings, (len * 2) * sizeof(char *));
+ }
+ strings[i++] = next;
}
+
+ va_end(valist);
+ char *result = str_join(separator, strings, i);
+ try_free(strings);
return result;
-} \ No newline at end of file
+}
+
+char *str_concat(char **strings, size_t len) {
+ return str_join(NULL, strings, len);
+}
+
diff --git a/src/util/str.h b/src/util/str.h
index 8fd2540..fb828da 100644
--- a/src/util/str.h
+++ b/src/util/str.h
@@ -19,10 +19,27 @@ const char *str_is_hex(const char *hex_str);
/**
* @brief
+ * @param separator
* @param strings
* @param len
* @return
*/
-char *str_join(char *strings[], size_t len);
+char *str_join(char *separator, char **strings, size_t len);
+
+/**
+ * @brief
+ * @param separator
+ * @param ...
+ * @return
+ */
+char *str_joinv(char *separator, ...);
+
+/**
+ * @brief
+ * @param strings
+ * @param len
+ * @return
+ */
+char *str_concat(char **strings, size_t len);
#endif // ECGEN_STR_H