6 extern void jacobian_affine(mpint *p,
7 mpint *X, mpint *Y, mpint *Z);
8 extern void jacobian_dbl(mpint *p, mpint *a,
9 mpint *X1, mpint *Y1, mpint *Z1,
10 mpint *X3, mpint *Y3, mpint *Z3);
11 extern void jacobian_add(mpint *p, mpint *a,
12 mpint *X1, mpint *Y1, mpint *Z1,
13 mpint *X2, mpint *Y2, mpint *Z2,
14 mpint *X3, mpint *Y3, mpint *Z3);
17 ecassign(ECdomain *dom, ECpoint *a, ECpoint *b)
19 if((b->inf = a->inf) != 0)
24 mpassign(a->z != nil ? a->z : mpone, b->z);
29 jacobian_affine(dom->p, b->x, b->y, b->z);
36 ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s)
55 jacobian_affine(dom->p, s->x, s->y, s->z);
62 jacobian_dbl(dom->p, dom->a,
63 a->x, a->y, a->z != nil ? a->z : mpone,
66 jacobian_add(dom->p, dom->a,
67 a->x, a->y, a->z != nil ? a->z : mpone,
68 b->x, b->y, b->z != nil ? b->z : mpone,
70 s->inf = mpcmp(s->z, mpzero) == 0;
74 ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
79 if(a->inf || mpcmp(k, mpzero) == 0){
90 ecassign(dom, a, &na);
93 while(mpcmp(l, mpzero) != 0){
95 ecadd(dom, &na, &ns, &ns);
96 ecadd(dom, &na, &na, &na);
99 if(k->sign < 0 && !ns.inf){
101 mpmod(ns.y, dom->p, ns.y);
103 ecassign(dom, &ns, s);
114 ecverify(ECdomain *dom, ECpoint *a)
122 assert(a->z == nil); /* need affine coordinates */
125 mpmodmul(a->y, a->y, dom->p, p);
126 mpmodmul(a->x, a->x, dom->p, q);
127 mpmodadd(q, dom->a, dom->p, q);
128 mpmodmul(q, a->x, dom->p, q);
129 mpmodadd(q, dom->b, dom->p, q);
137 ecpubverify(ECdomain *dom, ECpub *a)
144 if(!ecverify(dom, a))
149 ecmul(dom, a, dom->n, &p);
185 halfpt(ECdomain *dom, char *s, char **rptr, mpint *out)
191 n = ((mpsignif(dom->p)+7)/8)*2;
197 ret = strtomp(buf, &r, 16, out);
198 *rptr = s + (r - buf);
204 mpleg(mpint *a, mpint *b)
215 if(mpcmp(m, mpzero) == 0){
219 if(mpcmp(m, mpone) == 0)
224 switch(n->p[0] & 15){
225 case 3: case 5: case 11: case 13:
230 if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3)
242 mpsqrt(mpint *n, mpint *p, mpint *r)
244 mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N;
246 if(mpleg(n, p) == -1)
260 mpnrand(p, genrandom, a);
261 if(mpcmp(a, mpzero) > 0)
267 if(mpleg(t, p) == -1)
278 while(mpcmp(N, mpzero) != 0){
302 if(mpcmp(yq, mpzero) != 0)
319 strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
327 ret = mallocz(sizeof(*ret), 1);
342 if(halfpt(dom, s, &s, ret->x) == nil)
345 mpmul(ret->x, ret->x, r);
349 if(!mpsqrt(r, dom->p, r)){
353 if((r->p[0] & 1) != o)
357 if(!ecverify(dom, ret))
361 if(halfpt(dom, s, &s, ret->x) == nil)
363 if(halfpt(dom, s, &s, ret->y) == nil)
365 if(!ecverify(dom, ret))
369 if(ret->z != nil && !ret->inf)
370 mpassign(mpone, ret->z);
385 ecgen(ECdomain *dom, ECpriv *p)
388 p = mallocz(sizeof(*p), 1);
396 mpnrand(dom->n, genrandom, p->d);
397 if(mpcmp(p->d, mpzero) > 0)
400 ecmul(dom, &dom->G, p->d, p);
405 ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
414 E = betomp(dig, len, nil);
416 if(mpsignif(dom->n) < 8*len)
417 mpright(E, 8*len - mpsignif(dom->n), E);
420 mpmod(tmp.x, dom->n, r);
421 if(mpcmp(r, mpzero) == 0)
423 mpmul(r, priv->d, s);
425 mpinvert(tmp.d, dom->n, t);
426 mpmodmul(s, t, dom->n, s);
427 if(mpcmp(s, mpzero) != 0)
438 ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
440 mpint *E, *t, *u1, *u2;
444 if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0)
446 E = betomp(dig, len, nil);
447 if(mpsignif(dom->n) < 8*len)
448 mpright(E, 8*len - mpsignif(dom->n), E);
458 mpinvert(s, dom->n, t);
459 mpmodmul(E, t, dom->n, u1);
460 mpmodmul(r, t, dom->n, u2);
461 ecmul(dom, &dom->G, u1, &R);
462 ecmul(dom, pub, u2, &S);
463 ecadd(dom, &R, &S, &R);
466 jacobian_affine(dom->p, R.x, R.y, R.z);
467 mpmod(R.x, dom->n, t);
468 ret = mpcmp(r, t) == 0;
483 static char *code = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
486 base58enc(uchar *src, char *dst, int len)
492 n = betomp(src, len, nil);
495 while(mpcmp(n, mpzero) != 0){
497 *dst++ = code[mptoui(r)];
499 for(; *src == 0; src++)
510 base58dec(char *src, uchar *dst, int len)
519 t = strchr(code, *src);
524 werrstr("invalid base58 char");
531 mptober(n, dst, len);
539 ecdominit(ECdomain *dom, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h))
541 memset(dom, 0, sizeof(*dom));
550 (*init)(dom->p, dom->a, dom->b, dom->G.x, dom->G.y, dom->n, dom->h);
551 dom->p = mpfield(dom->p);
556 ecdomfree(ECdomain *dom)
565 memset(dom, 0, sizeof(*dom));
569 ecencodepub(ECdomain *dom, ECpub *pub, uchar *data, int len)
573 n = (mpsignif(dom->p)+7)/8;
578 mptober(pub->x, data+1, n);
579 mptober(pub->y, data+1+n, n);
584 ecdecodepub(ECdomain *dom, uchar *data, int len)
589 n = (mpsignif(dom->p)+7)/8;
590 if(len != 1 + 2*n || data[0] != 0x04)
592 pub = mallocz(sizeof(*pub), 1);
595 pub->x = betomp(data+1, n, nil);
596 pub->y = betomp(data+1+n, n, nil);
597 if(!ecpubverify(dom, pub)){