/* -*-c-*-
*
- * $Id: ec-prime.c,v 1.2 2002/01/13 13:48:44 mdw Exp $
+ * $Id: ec-prime.c,v 1.3.4.1 2003/06/10 13:43:53 mdw Exp $
*
* Elliptic curves over prime fields
*
/*----- Revision history --------------------------------------------------*
*
* $Log: ec-prime.c,v $
+ * Revision 1.3.4.1 2003/06/10 13:43:53 mdw
+ * Simple (non-projective) curves over prime fields now seem to work.
+ *
+ * Revision 1.3 2003/05/15 23:25:59 mdw
+ * Make elliptic curve stuff build.
+ *
* Revision 1.2 2002/01/13 13:48:44 mdw
* Further progress.
*
/*----- Header files ------------------------------------------------------*/
+#include <mLib/sub.h>
+
#include "ec.h"
/*----- Data structures ---------------------------------------------------*/
mp *a, *b;
} ecctx;
-/*----- Main code ---------------------------------------------------------*/
+/*----- Simple prime curves -----------------------------------------------*/
+
+static const ec_ops ec_primeops;
-static ec *ecneg(ec_cuvrve *c, ec *d, const ec *p)
+static ec *ecneg(ec_curve *c, ec *d, const ec *p)
{
EC_COPY(d, p);
d->y = F_NEG(c->f, d->y, d->y);
dx = F_TPL(f, dx, dx);
dx = F_ADD(f, dx, dx, cc->a);
dy = F_INV(f, dy, dy);
- lambda = F_MUL(d, MP_NEW, dx, dy);
+ lambda = F_MUL(f, MP_NEW, dx, dy);
dx = F_SQR(f, dx, lambda);
- dy = F_DBL(d, dy, a->x);
+ dy = F_DBL(f, dy, a->x);
dx = F_SUB(f, dx, dx, dy);
dy = F_SUB(f, dy, a->x, dx);
dy = F_MUL(f, dy, lambda, dy);
dx = F_ADD(f, dx, dx, cc->a);
dy = F_DBL(f, MP_NEW, a->y);
dy = F_INV(f, dy, dy);
- lambda = F_MUL(d, MP_NEW, dx, dy);
+ lambda = F_MUL(f, MP_NEW, dx, dy);
}
dx = F_SQR(f, dx, lambda);
return (d);
}
+static void ecdestroy(ec_curve *c)
+{
+ ecctx *cc = (ecctx *)c;
+ MP_DROP(cc->a);
+ MP_DROP(cc->b);
+ DESTROY(cc);
+}
+
+/* --- @ec_prime@, @ec_primeproj@ --- *
+ *
+ * Arguments: @field *f@ = the underlying field for this elliptic curve
+ * @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns: A pointer to the curve.
+ *
+ * Use: Creates a curve structure for an elliptic curve defined over
+ * a prime field. The @primeproj@ variant uses projective
+ * coordinates, which can be a win.
+ */
+
+extern ec_curve *ec_prime(field *f, mp *a, mp *b)
+{
+ ecctx *cc = CREATE(ecctx);
+ cc->c.ops = &ec_primeops;
+ cc->c.f = f;
+ cc->a = F_IN(f, MP_NEW, a);
+ cc->b = F_IN(f, MP_NEW, b);
+ return (&cc->c);
+}
+
+static const ec_ops ec_primeops = {
+ ecdestroy, ec_idin, ec_idout, 0, ecneg, ecadd, ec_stdsub, ecdbl
+};
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+int main(void)
+{
+ field *f;
+ ec_curve *c;
+ ec g = EC_INIT, d = EC_INIT;
+ mp *p, *a, *b, *r;
+
+ printf("ec-prime: ");
+ fflush(stdout);
+ a = MP(-3);
+ b = MP(0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1);
+ p = MP(6277101735386680763835789423207666416083908700390324961279);
+ r = MP(6277101735386680763835789423176059013767194773182842284080);
+
+ f = field_prime(p);
+ c = ec_prime(f, a, b);
+
+ g.x = MP(0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012);
+ g.y = MP(0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811);
+
+ ec_mul(c, &d, &g, r);
+ if (EC_ATINF(&d)) {
+ fprintf(stderr, "zero too early\n");
+ return (1);
+ }
+ ec_add(c, &d, &d, &g);
+ if (!EC_ATINF(&d)) {
+ fprintf(stderr, "didn't reach zero\n");
+ MP_EPRINT("d.x", d.x);
+ MP_EPRINT("d.y", d.y);
+ return (1);
+ }
+
+ ec_destroy(&d);
+ ec_destroy(&g);
+ ec_destroycurve(c);
+ F_DESTROY(f);
+ MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r);
+ assert(!mparena_count(&mparena_global));
+ printf("ok\n");
+ return (0);
+}
+
+#endif
+
/*----- That's all, folks -------------------------------------------------*/