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);
129 ecverify(ECdomain *dom, ECpoint *a)
139 mpmul(a->y, a->y, p);
141 mpmul(a->x, a->x, q);
153 ecpubverify(ECdomain *dom, ECpub *a)
160 if(!ecverify(dom, a))
164 ecmul(dom, a, dom->n, &p);
199 halfpt(ECdomain *dom, char *s, char **rptr, mpint *out)
205 n = ((mpsignif(dom->p)+7)/8)*2;
211 ret = strtomp(buf, &r, 16, out);
212 *rptr = s + (r - buf);
218 mpleg(mpint *a, mpint *b)
229 if(mpcmp(m, mpzero) == 0){
233 if(mpcmp(m, mpone) == 0)
238 switch(n->p[0] & 15){
239 case 3: case 5: case 11: case 13:
244 if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3)
256 mpsqrt(mpint *n, mpint *p, mpint *r)
258 mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N;
260 if(mpleg(n, p) == -1)
274 mprand(mpsignif(p), genrandom, a);
275 if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0)
281 if(mpleg(t, p) == -1)
292 while(mpcmp(N, mpzero) != 0){
316 if(mpcmp(yq, mpzero) != 0)
333 strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
341 ret = mallocz(sizeof(*ret), 1);
355 if(halfpt(dom, s, &s, ret->x) == nil)
358 mpmul(ret->x, ret->x, r);
362 if(!mpsqrt(r, dom->p, r)){
366 if((r->p[0] & 1) != o)
370 if(!ecverify(dom, ret))
374 if(halfpt(dom, s, &s, ret->x) == nil)
376 if(halfpt(dom, s, &s, ret->y) == nil)
378 if(!ecverify(dom, ret))
394 ecgen(ECdomain *dom, ECpriv *p)
397 p = mallocz(sizeof(*p), 1);
405 mprand(mpsignif(dom->n), genrandom, p->d);
406 if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
409 ecmul(dom, dom->G, p->d, p);
414 ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
422 E = betomp(dig, len, nil);
424 if(mpsignif(dom->n) < 8*len)
425 mpright(E, 8*len - mpsignif(dom->n), E);
428 mpmod(tmp.x, dom->n, r);
429 if(mpcmp(r, mpzero) == 0)
431 mpmul(r, priv->d, s);
433 mpinvert(tmp.d, dom->n, t);
436 if(mpcmp(s, mpzero) != 0)
447 ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
449 mpint *E, *t, *u1, *u2;
453 if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0)
455 E = betomp(dig, len, nil);
456 if(mpsignif(dom->n) < 8*len)
457 mpright(E, 8*len - mpsignif(dom->n), E);
465 mpinvert(s, dom->n, t);
467 mpmod(u1, dom->n, u1);
469 mpmod(u2, dom->n, u2);
470 ecmul(dom, dom->G, u1, &R);
471 ecmul(dom, pub, u2, &S);
472 ecadd(dom, &R, &S, &R);
475 mpmod(R.x, dom->n, t);
476 ret = mpcmp(r, t) == 0;
488 static char *code = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
491 base58enc(uchar *src, char *dst, int len)
497 n = betomp(src, len, nil);
500 while(mpcmp(n, mpzero) != 0){
502 *dst++ = code[mptoui(r)];
504 for(; *src == 0; src++)
515 base58dec(char *src, uchar *dst, int len)
525 t = strchr(code, *src);
530 werrstr("invalid base58 char");
538 l = (mpsignif(n) + 7) / 8;
539 mptobe(n, dst + (len - l), l, nil);