diff options
Diffstat (limited to 'moon-abe/pbc-0.5.14/ecc/singular.c')
-rw-r--r-- | moon-abe/pbc-0.5.14/ecc/singular.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/moon-abe/pbc-0.5.14/ecc/singular.c b/moon-abe/pbc-0.5.14/ecc/singular.c new file mode 100644 index 00000000..95f00410 --- /dev/null +++ b/moon-abe/pbc-0.5.14/ecc/singular.c @@ -0,0 +1,447 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdint.h> // for intptr_t +#include <stdlib.h> +#include <gmp.h> +#include "pbc_utils.h" +#include "pbc_field.h" +#include "pbc_curve.h" +#include "pbc_param.h" +#include "pbc_pairing.h" +#include "pbc_fp.h" +#include "pbc_memory.h" + +//TODO: Store as integer mod ring instead and convert at last minute? +struct point_s { + int inf_flag; + element_t x; + element_t y; +}; +typedef struct point_s *point_ptr; +typedef struct point_s point_t[1]; + +static void sn_init(element_ptr e) { + field_ptr f = e->field->data; + e->data = pbc_malloc(sizeof(point_t)); + point_ptr p = e->data; + element_init(p->x, f); + element_init(p->y, f); + p->inf_flag = 1; +} + +static void sn_clear(element_ptr e) { + point_ptr p = e->data; + element_clear(p->x); + element_clear(p->y); + pbc_free(e->data); +} + +static void sn_set0(element_ptr x) { + point_ptr p = x->data; + p->inf_flag = 1; +} + +static int sn_is0(element_ptr x) { + point_ptr p = x->data; + return p->inf_flag; +} + +//singular with node: y^2 = x^3 + x^2 +static void sn_random(element_t a) { + point_ptr p = a->data; + element_t t; + + element_init(t, p->x->field); + p->inf_flag = 0; + do { + element_random(p->x); + if (element_is0(p->x)) continue; + element_square(t, p->x); + element_add(t, t, p->x); + element_mul(t, t, p->x); + } while (!element_is_sqr(t)); + element_sqrt(p->y, t); + + element_clear(t); +} + +static inline void sn_double_no_check(point_ptr r, point_ptr p) { + element_t lambda, e0, e1; + + element_init(lambda, p->x->field); + element_init(e0, p->x->field); + element_init(e1, p->x->field); + //same point: double them + + //lambda = (3x^2 + 2x) / 2y + element_mul_si(lambda, p->x, 3); + element_set_si(e0, 2); + element_add(lambda, lambda, e0); + element_mul(lambda, lambda, p->x); + element_add(e0, p->y, p->y); + element_invert(e0, e0); + element_mul(lambda, lambda, e0); + //x1 = lambda^2 - 2x - 1 + element_add(e1, p->x, p->x); + element_square(e0, lambda); + element_sub(e0, e0, e1); + element_set_si(e1, 1); + element_sub(e0, e0, e1); + //y1 = (x - x1)lambda - y + element_sub(e1, p->x, e0); + element_mul(e1, e1, lambda); + element_sub(e1, e1, p->y); + + element_set(r->x, e0); + element_set(r->y, e1); + r->inf_flag = 0; + + element_clear(lambda); + element_clear(e0); + element_clear(e1); + return; +} + +static void sn_double(element_t c, element_t a) { + point_ptr r = c->data; + point_ptr p = a->data; + if (p->inf_flag) { + r->inf_flag = 1; + return; + } + if (element_is0(p->y)) { + r->inf_flag = 1; + return; + } + sn_double_no_check(r, p); +} + +static void sn_set(element_ptr c, element_ptr a) { + point_ptr r = c->data, p = a->data; + if (p->inf_flag) { + r->inf_flag = 1; + return; + } + r->inf_flag = 0; + element_set(r->x, p->x); + element_set(r->y, p->y); +} + +static void sn_add(element_t c, element_t a, element_t b) { + point_ptr r = c->data; + point_ptr p = a->data; + point_ptr q = b->data; + if (p->inf_flag) { + sn_set(c, b); + return; + } + if (q->inf_flag) { + sn_set(c, a); + return; + } + if (!element_cmp(p->x, q->x)) { + if (!element_cmp(p->y, q->y)) { + if (element_is0(p->y)) { + r->inf_flag = 1; + return; + } else { + sn_double_no_check(r, p); + return; + } + } + //points are inverses of each other + r->inf_flag = 1; + return; + } else { + element_t lambda, e0, e1; + + element_init(lambda, p->x->field); + element_init(e0, p->x->field); + element_init(e1, p->x->field); + + //lambda = (y2-y1)/(x2-x1) + element_sub(e0, q->x, p->x); + element_invert(e0, e0); + element_sub(lambda, q->y, p->y); + element_mul(lambda, lambda, e0); + //x3 = lambda^2 - x1 - x2 - 1 + element_square(e0, lambda); + element_sub(e0, e0, p->x); + element_sub(e0, e0, q->x); + element_set1(e1); + element_sub(e0, e0, e1); + //y3 = (x1-x3)lambda - y1 + element_sub(e1, p->x, e0); + element_mul(e1, e1, lambda); + element_sub(e1, e1, p->y); + + element_set(r->x, e0); + element_set(r->y, e1); + r->inf_flag = 0; + + element_clear(lambda); + element_clear(e0); + element_clear(e1); + } +} + +static void sn_invert(element_ptr c, element_ptr a) { + point_ptr r = c->data, p = a->data; + + if (p->inf_flag) { + r->inf_flag = 1; + return; + } + r->inf_flag = 0; + element_set(r->x, p->x); + element_neg(r->y, p->y); +} + +static void sn_field_clear(field_ptr c) { + UNUSED_VAR(c); +} + +/* TODO: Write a test program that uses these functions. + +// Nonsingular points on sn curves map to finite field elements via +// (x, y) --> (y + x)/(y - x) +// The reverse map is +// a --> (4a/(a-1)^2, 4a(a+1)/(a-1)^3) + +void sn_point_to_field(element_t out, point_ptr P) { + element_t e0, e1; + if (P->inf_flag) { + element_set1(out); + return; + } + element_init(e0, out->field); + element_init(e1, out->field); + element_add(e0, P->y, P->x); + element_sub(e1, P->y, P->x); + element_invert(e1, e1); + element_mul(out, e0, e1); + element_clear(e0); + element_clear(e1); +} + +static void sn_field_to_point(point_ptr P, element_t in) { + element_t e0, e1, e2; + + if (element_is1(in)) { + P->inf_flag = 1; + return; + } + element_init(e0, in->field); + element_init(e1, in->field); + element_init(e2, in->field); + + element_set1(e1); + element_sub(e0, in, e1); + element_invert(e0, e0); + + element_mul_si(e2, in, 4); + + element_add(P->y, in, e1); + + element_mul(e1, e0, e0); + element_mul(P->x, e1, e2); + element_mul(P->y, P->y, e2); + element_mul(P->y, P->y, e0); + element_mul(P->y, P->y, e1); + P->inf_flag = 0; + + element_clear(e0); + element_clear(e1); + element_clear(e2); +} +*/ + +static size_t sn_out_str(FILE *stream, int base, element_ptr a) { + point_ptr p = a->data; + size_t result, status; + if (p->inf_flag) { + if (EOF == fputc('O', stream)) return 0; + return 1; + } + result = element_out_str(stream, base, p->x); + if (!result) return 0; + if (EOF == fputc(' ', stream)) return 0; + status = element_out_str(stream, base, p->y); + if (!status) return 0; + return result + status + 1; +} + +void naive_generic_pow_mpz(element_ptr x, element_ptr a, mpz_ptr n); +void field_init_curve_singular_with_node(field_t c, field_t field) { + mpz_set(c->order, field->order); + c->data = (void *) field; + c->init = sn_init; + c->clear = sn_clear; + c->random = sn_random; + //c->from_x = cc_from_x; + //c->from_hash = cc_from_hash; + c->set = sn_set; + c->invert = c->neg = sn_invert; + c->square = c->doub = sn_double; + c->mul = c->add = sn_add; + c->set1 = c->set0 = sn_set0; + c->is1 = c->is0 = sn_is0; + c->mul_mpz = element_pow_mpz; + c->out_str = sn_out_str; + c->field_clear = sn_field_clear; +} + +//TODO: the following code is useless as the Tate pairing is degenerate on singular curves +static void sn_miller(element_t res, mpz_t q, element_t P, + element_ptr Qx, element_ptr Qy) { + //collate divisions + int m; + element_t v, vd; + element_t Z; + element_t a, b, c; + element_t e0, e1; + element_ptr Zx; + element_ptr Zy; + const element_ptr Px = curve_x_coord(P); + const element_ptr Py = curve_y_coord(P); + + #define do_vertical(e) \ + element_sub(e0, Qx, Zx); \ + element_mul(e, e, e0); + + //a = -slope_tangent(Z.x, Z.y); + //b = 1; + //c = -(Z.y + a * Z.x); + //but we multiply by 2*Z.y to avoid division + //a = -Zx * (Zx + Zx + Zx + 2) + //b = 2 * Zy + //c = -(2 Zy^2 + a Zx); + #define do_tangent(e) \ + element_double(e0, Zx); \ + element_add(a, Zx, e0); \ + element_set_si(e0, 2); \ + element_add(a, a, e0); \ + element_mul(a, a, Zx); \ + element_neg(a, a); \ + element_add(b, Zy, Zy); \ + element_mul(e0, b, Zy); \ + element_mul(c, a, Zx); \ + element_add(c, c, e0); \ + element_neg(c, c); \ + element_mul(e0, a, Qx); \ + element_mul(e1, b, Qy); \ + element_add(e0, e0, e1); \ + element_add(e0, e0, c); \ + element_mul(e, e, e0); + + //a = -(B.y - A.y) / (B.x - A.x); + //b = 1; + //c = -(A.y + a * A.x); + //but we'll multiply by B.x - A.x to avoid division + #define do_line(e) \ + element_sub(b, Px, Zx); \ + element_sub(a, Zy, Py); \ + element_mul(e0, b, Zy); \ + element_mul(c, a, Zx); \ + element_add(c, c, e0); \ + element_neg(c, c); \ + element_mul(e0, a, Qx); \ + element_mul(e1, b, Qy); \ + element_add(e0, e0, e1); \ + element_add(e0, e0, c); \ + element_mul(e, e, e0); + + element_init(a, Px->field); + element_init(b, Px->field); + element_init(c, Px->field); + element_init(e0, res->field); + element_init(e1, res->field); + + element_init(v, res->field); + element_init(vd, res->field); + element_init(Z, P->field); + + element_set(Z, P); + Zx = curve_x_coord(Z); + Zy = curve_y_coord(Z); + + element_set1(v); + element_set1(vd); + m = mpz_sizeinbase(q, 2) - 2; + + while(m >= 0) { + element_mul(v, v, v); + element_mul(vd, vd, vd); + do_tangent(v); + element_double(Z, Z); + do_vertical(vd); + if (mpz_tstbit(q, m)) { + do_line(v); + element_add(Z, Z, P); + do_vertical(vd); + } + m--; + } + #undef do_tangent + #undef do_vertical + #undef do_line + + element_invert(vd, vd); + element_mul(res, v, vd); + + element_clear(v); + element_clear(vd); + element_clear(Z); + element_clear(a); + element_clear(b); + element_clear(c); + element_clear(e0); + element_clear(e1); +} + +struct sn_pairing_data_s { + field_t Fq, Eq; +}; +typedef struct sn_pairing_data_s sn_pairing_data_t[1]; +typedef struct sn_pairing_data_s *sn_pairing_data_ptr; + +static void sn_pairing(element_ptr out, element_ptr in1, element_ptr in2, + pairing_t pairing) { + sn_pairing_data_ptr p = pairing->data; + element_ptr Q = in2; + element_t e0; + element_t R, QR; + element_init(R, p->Eq); + element_init(QR, p->Eq); + element_random(R); + element_init(e0, out->field); + element_add(QR, Q, R); + sn_miller(out, pairing->r, in1, curve_x_coord(QR), curve_y_coord(QR)); + sn_miller(e0, pairing->r, in1, curve_x_coord(R), curve_y_coord(R)); + element_invert(e0, e0); + element_mul(out, out, e0); + //element_pow_mpz(out, out, p->tateexp); + element_clear(R); + element_clear(QR); +} + +void pairing_init_singular_with_node(pairing_t pairing, mpz_t q) { + sn_pairing_data_ptr p; + + mpz_init(pairing->r); + mpz_sub_ui(pairing->r, q, 1); + field_init_fp(pairing->Zr, pairing->r); + pairing->map = sn_pairing; + + p = pairing->data = pbc_malloc(sizeof(sn_pairing_data_t)); + field_init_fp(p->Fq, q); + field_init_curve_singular_with_node(p->Eq, p->Fq); + + //mpz_init(p->tateexp); + //mpz_sub_ui(p->tateexp, p->Fq->order, 1); + //mpz_divexact(p->tateexp, p->tateexp, pairing->r); + + pairing->G2 = pairing->G1 = p->Eq; + + pairing_GT_init(pairing, p->Fq); +} |