7 ecassign(ECdomain *, ECpoint *a, ECpoint *b)
15 ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s)
17 mpint *l, *k, *sx, *sy;
31 if(mpcmp(a->x, b->x) == 0 && (mpcmp(a->y, mpzero) == 0 || mpcmp(a->y, b->y) != 0)){
39 if(mpcmp(a->x, b->x) == 0 && mpcmp(a->y, b->y) == 0){
40 mpadd(mpone, mptwo, k);
46 mpinvert(k, dom->p, k);
53 mpmod(sx, dom->p, sx);
58 mpmod(sy, dom->p, sy);
71 mpinvert(k, dom->p, k);
78 mpmod(sx, dom->p, sx);
83 mpmod(sy, dom->p, sy);
94 ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
99 if(a->inf || mpcmp(k, mpzero) == 0){
108 ecassign(dom, a, &na);
111 while(mpcmp(l, mpzero) != 0){
113 ecadd(dom, &na, &ns, &ns);
114 ecadd(dom, &na, &na, &na);
119 mpmod(ns.y, dom->p, ns.y);
121 ecassign(dom, &ns, s);
130 ecverify(ECdomain *dom, ECpoint *a)
140 mpmul(a->y, a->y, p);
142 mpmul(a->x, a->x, q);
154 ecpubverify(ECdomain *dom, ECpub *a)
161 if(!ecverify(dom, a))
165 ecmul(dom, a, dom->n, &p);
200 halfpt(ECdomain *dom, char *s, char **rptr, mpint *out)
206 n = ((mpsignif(dom->p)+7)/8)*2;
212 ret = strtomp(buf, &r, 16, out);
213 *rptr = s + (r - buf);
219 mpleg(mpint *a, mpint *b)
230 if(mpcmp(m, mpzero) == 0){
234 if(mpcmp(m, mpone) == 0)
239 switch(n->p[0] & 15){
240 case 3: case 5: case 11: case 13:
245 if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3)
257 mpsqrt(mpint *n, mpint *p, mpint *r)
259 mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N;
261 if(mpleg(n, p) == -1)
275 mprand(mpsignif(p), genrandom, a);
276 if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0)
282 if(mpleg(t, p) == -1)
293 while(mpcmp(N, mpzero) != 0){
317 if(mpcmp(yq, mpzero) != 0)
334 strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
342 ret = mallocz(sizeof(*ret), 1);
356 if(halfpt(dom, s, &s, ret->x) == nil)
359 mpmul(ret->x, ret->x, r);
363 if(!mpsqrt(r, dom->p, r)){
367 if((r->p[0] & 1) != o)
371 if(!ecverify(dom, ret))
375 if(halfpt(dom, s, &s, ret->x) == nil)
377 if(halfpt(dom, s, &s, ret->y) == nil)
379 if(!ecverify(dom, ret))
395 ecgen(ECdomain *dom, ECpriv *p)
398 p = mallocz(sizeof(*p), 1);
406 mprand(mpsignif(dom->n), genrandom, p->d);
407 if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
410 ecmul(dom, dom->G, p->d, p);
415 ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
423 E = betomp(dig, len, nil);
425 if(mpsignif(dom->n) < 8*len)
426 mpright(E, 8*len - mpsignif(dom->n), E);
429 mpmod(tmp.x, dom->n, r);
430 if(mpcmp(r, mpzero) == 0)
432 mpmul(r, priv->d, s);
434 mpinvert(tmp.d, dom->n, t);
437 if(mpcmp(s, mpzero) != 0)
448 ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
450 mpint *E, *t, *u1, *u2;
454 if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0)
456 E = betomp(dig, len, nil);
457 if(mpsignif(dom->n) < 8*len)
458 mpright(E, 8*len - mpsignif(dom->n), E);
466 mpinvert(s, dom->n, t);
468 mpmod(u1, dom->n, u1);
470 mpmod(u2, dom->n, u2);
471 ecmul(dom, dom->G, u1, &R);
472 ecmul(dom, pub, u2, &S);
473 ecadd(dom, &R, &S, &R);
476 mpmod(R.x, dom->n, t);
477 ret = mpcmp(r, t) == 0;
489 static char *code = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
492 base58enc(uchar *src, char *dst, int len)
498 n = betomp(src, len, nil);
501 while(mpcmp(n, mpzero) != 0){
503 *dst++ = code[mptoui(r)];
505 for(; *src == 0; src++)
516 base58dec(char *src, uchar *dst, int len)
526 t = strchr(code, *src);
531 werrstr("invalid base58 char");
539 l = (mpsignif(n) + 7) / 8;
540 mptobe(n, dst + (len - l), l, nil);