RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q) { mpint *c2, *kq, *kp, *x; RSApriv *rsa; // make sure we're not being hoodwinked if(!probably_prime(p, 10) || !probably_prime(q, 10)){ werrstr("rsafill: p or q not prime"); return nil; } x = mpnew(0); mpmul(p, q, x); if(mpcmp(n, x) != 0){ werrstr("rsafill: n != p*q"); mpfree(x); return nil; } c2 = mpnew(0); mpsub(p, mpone, c2); mpsub(q, mpone, x); mpmul(c2, x, x); mpmul(e, d, c2); mpmod(c2, x, x); if(mpcmp(x, mpone) != 0){ werrstr("rsafill: e*d != 1 mod (p-1)*(q-1)"); mpfree(x); mpfree(c2); return nil; } // compute chinese remainder coefficient mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, x); mpmod(d, x, kp); mpsub(q, mpone, x); mpmod(d, x, kq); rsa = rsaprivalloc(); rsa->pub.ek = mpcopy(e); rsa->pub.n = mpcopy(n); rsa->dk = mpcopy(d); rsa->kp = kp; rsa->kq = kq; rsa->p = mpcopy(p); rsa->q = mpcopy(q); rsa->c2 = c2; mpfree(x); return rsa; }
ECpoint* strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret) { int allocd, o; mpint *r; allocd = 0; if(ret == nil){ allocd = 1; ret = mallocz(sizeof(*ret), 1); if(ret == nil) return nil; ret->x = mpnew(0); ret->y = mpnew(0); } o = 0; switch(octet(&s)){ case 0: ret->inf = 1; return ret; case 3: o = 1; case 2: if(halfpt(dom, s, &s, ret->x) == nil) goto err; r = mpnew(0); mpmul(ret->x, ret->x, r); mpadd(r, dom->a, r); mpmul(r, ret->x, r); mpadd(r, dom->b, r); if(!mpsqrt(r, dom->p, r)){ mpfree(r); goto err; } if((r->p[0] & 1) != o) mpsub(dom->p, r, r); mpassign(r, ret->y); mpfree(r); if(!ecverify(dom, ret)) goto err; return ret; case 4: if(halfpt(dom, s, &s, ret->x) == nil) goto err; if(halfpt(dom, s, &s, ret->y) == nil) goto err; if(!ecverify(dom, ret)) goto err; return ret; } err: if(rptr) *rptr = s; if(allocd){ mpfree(ret->x); mpfree(ret->y); free(ret); } return nil; }
void NR::mpdiv(Vec_O_UCHR &q, Vec_O_UCHR &r, Vec_I_UCHR &u, Vec_I_UCHR &v) { const int MACC=1; int i,is,mm; int n=u.size(); int m=v.size(); int p=r.size(); int n_min=MIN(m,p); if (m > n) nrerror("Divisor longer than dividend in mpdiv"); mm=m+MACC; Vec_UCHR s(mm),rr(mm),ss(mm+1),qq(n-m+1),t(n); mpinv(s,v); mpmul(rr,s,u); mpsad(ss,rr,1); mplsh(ss); mplsh(ss); mpmov(qq,ss); mpmov(q,qq); mpmul(t,qq,v); mplsh(t); mpsub(is,t,u,t); if (is != 0) nrerror("MACC too small in mpdiv"); for (i=0;i<n_min;i++) r[i]=t[i+n-m]; if (p>m) for (i=m;i<p;i++) r[i]=0; }
/* * needs workspace of (size*2) words */ static void mpprndbits(mpbarrett* p, size_t bits, size_t lsbset, const mpnumber* min, const mpnumber* max, randomGeneratorContext* rc, mpw* wksp) { register size_t size = p->size; register size_t msbclr = MP_WORDS_TO_BITS(size) - bits; /* assume that mpbits(max) == bits */ /* calculate k=max-min; generate q such that 0 <= q <= k; then set p = q + min */ /* for the second step, set the appropriate number of bits */ if (max) { mpsetx(size, wksp, max->size, max->data); } else { mpfill(size, wksp, MP_ALLMASK); wksp[0] &= (MP_ALLMASK >> msbclr); } if (min) { mpsetx(size, wksp+size, min->size, min->data); } else { mpzero(size, wksp+size); wksp[size] |= (MP_MSBMASK >> msbclr); } mpsub(size, wksp, wksp+size); rc->rng->next(rc->param, (byte*) p->modl, MP_WORDS_TO_BYTES(size)); p->modl[0] &= (MP_ALLMASK >> msbclr); while (mpgt(size, p->modl, wksp)) mpsub(size, p->modl, wksp); mpadd(size, p->modl, wksp+size); if (lsbset) p->modl[size-1] |= (MP_ALLMASK >> (MP_WBITS - lsbset)); }
DSApriv* dsagen(DSApub *opub) { DSApub *pub; DSApriv *priv; mpint *exp; mpint *g; mpint *r; int bits; priv = dsaprivalloc(); pub = &priv->pub; if(opub != nil){ pub->p = mpcopy(opub->p); pub->q = mpcopy(opub->q); } else { pub->p = mpnew(0); pub->q = mpnew(0); DSAprimes(pub->q, pub->p, nil); } bits = Dbits*pub->p->top; pub->alpha = mpnew(0); pub->key = mpnew(0); priv->secret = mpnew(0); // find a generator alpha of the multiplicative // group Z*p, i.e., of order n = p-1. We use the // fact that q divides p-1 to reduce the exponent. exp = mpnew(0); g = mpnew(0); r = mpnew(0); mpsub(pub->p, mpone, exp); mpdiv(exp, pub->q, exp, r); if(mpcmp(r, mpzero) != 0) sysfatal("dsagen foul up"); while(1){ mprand(bits, genrandom, g); mpmod(g, pub->p, g); mpexp(g, exp, pub->p, pub->alpha); if(mpcmp(pub->alpha, mpone) != 0) break; } mpfree(g); mpfree(exp); // create the secret key mprand(bits, genrandom, priv->secret); mpmod(priv->secret, pub->p, priv->secret); mpexp(pub->alpha, priv->secret, pub->p, pub->key); return priv; }
DSAsig* dsasign(DSApriv *priv, mpint *m) { DSApub *pub = &priv->pub; DSAsig *sig; mpint *qm1, *k, *kinv, *r, *s; mpint *q = pub->q, *p = pub->p, *alpha = pub->alpha; int qlen = mpsignif(q); qm1 = mpnew(0); kinv = mpnew(0); r = mpnew(0); s = mpnew(0); k = mpnew(0); mpsub(pub->q, mpone, qm1); // find a k that has an inverse mod q while(1){ mprand(qlen, genrandom, k); if((mpcmp(mpone, k) > 0) || (mpcmp(k, qm1) >= 0)) continue; mpextendedgcd(k, q, r, kinv, s); if(mpcmp(r, mpone) != 0) continue; break; } // make kinv positive mpmod(kinv, qm1, kinv); // r = ((alpha**k) mod p) mod q mpexp(alpha, k, p, r); mpmod(r, q, r); // s = (kinv*(m + ar)) mod q mpmul(r, priv->secret, s); mpadd(s, m, s); mpmul(s, kinv, s); mpmod(s, q, s); sig = dsasigalloc(); sig->r = r; sig->s = s; mpfree(qm1); mpfree(k); mpfree(kinv); return sig; }
/* * mpbmod_w * computes the barrett modular reduction of a number x, which has twice the size of b * needs workspace of (2*size+2) words */ void mpbmod_w(const mpbarrett* b, const mpw* data, mpw* result, mpw* wksp) { register mpw rc; register size_t sp = 2; register const mpw* src = data+b->size+1; register mpw* dst = wksp+b->size+1; rc = mpsetmul(sp, dst, b->mu, *(--src)); *(--dst) = rc; while (sp <= b->size) { sp++; if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; } if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; sp = b->size; rc = 0; dst = wksp+b->size+1; src = dst; *dst = mpsetmul(sp, dst+1, b->modl, *(--src)); while (sp > 0) mpaddmul(sp--, dst, b->modl+(rc++), *(--src)); mpsetx(b->size+1, wksp, b->size*2, data); mpsub(b->size+1, wksp, wksp+b->size+1); while (mpgex(b->size+1, wksp, b->size, b->modl)) mpsubx(b->size+1, wksp, b->size, b->modl); mpcopy(b->size, result, wksp+1); }
/* * mpbrnd_w * generates a random number in the range 1 < r < b-1 * need workspace of (size) words */ void mpbrnd_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* wksp) { size_t msz = mpmszcnt(b->size, b->modl); mpcopy(b->size, wksp, b->modl); mpsubw(b->size, wksp, 1); do { rc->rng->next(rc->param, (byte*) result, MP_WORDS_TO_BYTES(b->size)); result[0] &= (MP_ALLMASK >> msz); while (mpge(b->size, result, wksp)) mpsub(b->size, result, wksp); } while (mpleone(b->size, result)); }
/* garners algorithm for converting residue form to linear */ void crtout(CRTpre *crt, CRTres *res, mpint *x) { mpint *u; int i; u = mpnew(0); mpassign(res->r[0], x); for(i = 1; i < crt->n; i++){ mpsub(res->r[i], x, u); mpmul(u, crt->c[i], u); mpmod(u, crt->m[i], u); mpmul(u, crt->p[i-1], u); mpadd(x, u, x); } mpfree(u); }
static int Ympbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { size_t ysize = b->size+1; int k; mpw* u1 = wksp; mpw* u2 = u1+ysize; mpw* u3 = u2+ysize; mpw* v1 = u3+ysize; mpw* v2 = v1+ysize; mpw* v3 = v2+ysize; mpw* t1 = v3+ysize; mpw* t2 = t1+ysize; mpw* t3 = t2+ysize; mpw* u = t3+ysize; mpw* v = u+ysize; mpsetx(ysize, u, xsize, xdata); mpsetx(ysize, v, b->size, b->modl); /* Y1. Find power of 2. */ for (k = 0; mpeven(ysize, u) && mpeven(ysize, v); k++) { mpdivtwo(ysize, u); mpdivtwo(ysize, v); } if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); /* Y2. Initialize. */ mpsetw(ysize, u1, 1); if (_debug < 0) fprintf(stderr, " u1: "), mpfprintln(stderr, ysize, u1); mpzero(ysize, u2); if (_debug < 0) fprintf(stderr, " u2: "), mpfprintln(stderr, ysize, u2); mpsetx(ysize, u3, ysize, u); if (_debug < 0) fprintf(stderr, " u3: "), mpfprintln(stderr, ysize, u3); mpsetx(ysize, v1, ysize, v); if (_debug < 0) fprintf(stderr, " v1: "), mpfprintln(stderr, ysize, v1); mpsetw(ysize, v2, 1); (void) mpsub(ysize, v2, u); if (_debug < 0) fprintf(stderr, " v2: "), mpfprintln(stderr, ysize, v2); mpsetx(ysize, v3, ysize, v); if (_debug < 0) fprintf(stderr, " v3: "), mpfprintln(stderr, ysize, v3); if (mpodd(ysize, u)) { mpzero(ysize, t1); if (_debug < 0) fprintf(stderr, " t1: "), mpfprintln(stderr, ysize, t1); mpzero(ysize, t2); mpsubw(ysize, t2, 1); if (_debug < 0) fprintf(stderr, " t2: "), mpfprintln(stderr, ysize, t2); mpzero(ysize, t3); mpsub(ysize, t3, v); if (_debug < 0) fprintf(stderr, " t3: "), mpfprintln(stderr, ysize, t3); goto Y4; } else { mpsetw(ysize, t1, 1); if (_debug < 0) fprintf(stderr, " t1: "), mpfprintln(stderr, ysize, t1); mpzero(ysize, t2); if (_debug < 0) fprintf(stderr, " t2: "), mpfprintln(stderr, ysize, t2); mpsetx(ysize, t3, ysize, u); if (_debug < 0) fprintf(stderr, " t3: "), mpfprintln(stderr, ysize, t3); } do { do { if (mpodd(ysize, t1) || mpodd(ysize, t2)) { mpadd(ysize, t1, v); mpsub(ysize, t2, u); } mpsdivtwo(ysize, t1); mpsdivtwo(ysize, t2); mpsdivtwo(ysize, t3); Y4: if (_debug < 0) fprintf(stderr, " Y4 t3: "), mpfprintln(stderr, ysize, t3); } while (mpeven(ysize, t3)); /* Y5. Reset max(u3,v3). */ if (!(*t3 & 0x80000000)) { if (_debug < 0) fprintf(stderr, "--> Y5 (t3 > 0)\n"); mpsetx(ysize, u1, ysize, t1); if (_debug < 0) fprintf(stderr, " u1: "), mpfprintln(stderr, ysize, u1); mpsetx(ysize, u2, ysize, t2); if (_debug < 0) fprintf(stderr, " u2: "), mpfprintln(stderr, ysize, u2); mpsetx(ysize, u3, ysize, t3); if (_debug < 0) fprintf(stderr, " u3: "), mpfprintln(stderr, ysize, u3); } else { if (_debug < 0) fprintf(stderr, "--> Y5 (t3 <= 0)\n"); mpsetx(ysize, v1, ysize, v); mpsub(ysize, v1, t1); if (_debug < 0) fprintf(stderr, " v1: "), mpfprintln(stderr, ysize, v1); mpsetx(ysize, v2, ysize, u); mpneg(ysize, v2); mpsub(ysize, v2, t2); if (_debug < 0) fprintf(stderr, " v2: "), mpfprintln(stderr, ysize, v2); mpzero(ysize, v3); mpsub(ysize, v3, t3); if (_debug < 0) fprintf(stderr, " v3: "), mpfprintln(stderr, ysize, v3); } /* Y6. Subtract. */ mpsetx(ysize, t1, ysize, u1); mpsub(ysize, t1, v1); mpsetx(ysize, t2, ysize, u2); mpsub(ysize, t2, v2); mpsetx(ysize, t3, ysize, u3); mpsub(ysize, t3, v3); if (*t1 & 0x80000000) { mpadd(ysize, t1, v); mpsub(ysize, t2, u); } if (_debug < 0) fprintf(stderr, "-->Y6 t1: "), mpfprintln(stderr, ysize, t1); if (_debug < 0) fprintf(stderr, " t2: "), mpfprintln(stderr, ysize, t2); if (_debug < 0) fprintf(stderr, " t3: "), mpfprintln(stderr, ysize, t3); } while (mpnz(ysize, t3)); if (!(mpisone(ysize, u3) && mpisone(ysize, v3))) return 0; if (result) { while (--k > 0) mpadd(ysize, u1, u1); mpsetx(b->size, result, ysize, u1); } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u1: "), mpfprintln(stderr, ysize, u1); fprintf(stderr, " u2: "), mpfprintln(stderr, ysize, u2); fprintf(stderr, " u3: "), mpfprintln(stderr, ysize, u3); fprintf(stderr, " v1: "), mpfprintln(stderr, ysize, v1); fprintf(stderr, " v2: "), mpfprintln(stderr, ysize, v2); fprintf(stderr, " v3: "), mpfprintln(stderr, ysize, v3); fprintf(stderr, " t1: "), mpfprintln(stderr, ysize, t1); fprintf(stderr, " t2: "), mpfprintln(stderr, ysize, t2); fprintf(stderr, " t3: "), mpfprintln(stderr, ysize, t3); return 1; }
/* * mpbtwopowmod_w * needs workspace of (4*size+2) words */ void mpbtwopowmod_w(const mpbarrett* b, size_t psize, const mpw* pdata, mpw* result, mpw* wksp) { /* * Modular exponention, 2^p mod modulus, special optimization * * Uses left-to-right exponentiation; needs no extra storage * */ /* this routine calls mpbmod, which needs (size*2+2), this routine needs (size*2) for sdata */ register size_t size = b->size; register mpw temp = 0; mpsetw(size, result, 1); while (psize) { if ((temp = *(pdata++))) /* break when first non-zero word found */ break; psize--; } /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */ if (temp) { register int count = MP_WBITS; /* first skip bits until we reach a one */ while (count) { if (temp & MP_MSBMASK) break; temp <<= 1; count--; } while (psize--) { while (count) { /* always square */ mpbsqrmod_w(b, size, result, result, wksp); /* multiply by two if bit is 1 */ if (temp & MP_MSBMASK) { if (mpadd(size, result, result) || mpge(size, result, b->modl)) { /* there was carry, or the result is greater than the modulus, so we need to adjust */ mpsub(size, result, b->modl); } } temp <<= 1; count--; } count = MP_WBITS; temp = *(pdata++); } } }
void mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y) { mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r; if(a->sign<0 || b->sign<0) sysfatal("mpeuclid: negative arg"); if(mpcmp(a, b) < 0){ tmp = a; a = b; b = tmp; tmp = x; x = y; y = tmp; } if(b->top == 0){ mpassign(a, d); mpassign(mpone, x); mpassign(mpzero, y); return; } a = mpcopy(a); b = mpcopy(b); x0 = mpnew(0); x1 = mpcopy(mpzero); x2 = mpcopy(mpone); y0 = mpnew(0); y1 = mpcopy(mpone); y2 = mpcopy(mpzero); q = mpnew(0); r = mpnew(0); while(b->top != 0 && b->sign > 0){ // q = a/b // r = a mod b mpdiv(a, b, q, r); // x0 = x2 - qx1 mpmul(q, x1, x0); mpsub(x2, x0, x0); // y0 = y2 - qy1 mpmul(q, y1, y0); mpsub(y2, y0, y0); // rotate values tmp = a; a = b; b = r; r = tmp; tmp = x2; x2 = x1; x1 = x0; x0 = tmp; tmp = y2; y2 = y1; y1 = y0; y0 = tmp; } mpassign(a, d); mpassign(x2, x); mpassign(y2, y); mpfree(x0); mpfree(x1); mpfree(x2); mpfree(y0); mpfree(y1); mpfree(y2); mpfree(q); mpfree(r); mpfree(a); mpfree(b); }
static int mpsqrt(mpint *n, mpint *p, mpint *r) { mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N; if(mpleg(n, p) == -1) return 0; a = mpnew(0); t = mpnew(0); s = mpnew(0); N = mpnew(0); xp = mpnew(0); xq = mpnew(0); yp = mpnew(0); yq = mpnew(0); zp = mpnew(0); zq = mpnew(0); for(;;){ for(;;){ mprand(mpsignif(p), genrandom, a); if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0) break; } mpmul(a, a, t); mpsub(t, n, t); mpmod(t, p, t); if(mpleg(t, p) == -1) break; } mpadd(p, mpone, N); mpright(N, 1, N); mpmul(a, a, t); mpsub(t, n, t); mpassign(a, xp); uitomp(1, xq); uitomp(1, yp); uitomp(0, yq); while(mpcmp(N, mpzero) != 0){ if(N->p[0] & 1){ mpmul(xp, yp, zp); mpmul(xq, yq, zq); mpmul(zq, t, zq); mpadd(zp, zq, zp); mpmod(zp, p, zp); mpmul(xp, yq, zq); mpmul(xq, yp, s); mpadd(zq, s, zq); mpmod(zq, p, yq); mpassign(zp, yp); } mpmul(xp, xp, zp); mpmul(xq, xq, zq); mpmul(zq, t, zq); mpadd(zp, zq, zp); mpmod(zp, p, zp); mpmul(xp, xq, zq); mpadd(zq, zq, zq); mpmod(zq, p, xq); mpassign(zp, xp); mpright(N, 1, N); } if(mpcmp(yq, mpzero) != 0) abort(); mpassign(yp, r); mpfree(a); mpfree(t); mpfree(s); mpfree(N); mpfree(xp); mpfree(xq); mpfree(yp); mpfree(yq); mpfree(zp); mpfree(zq); return 1; }
void ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s) { mpint *l, *k, *sx, *sy; if(a->inf && b->inf){ s->inf = 1; return; } if(a->inf){ ecassign(dom, b, s); return; } if(b->inf){ ecassign(dom, a, s); return; } if(mpcmp(a->x, b->x) == 0 && (mpcmp(a->y, mpzero) == 0 || mpcmp(a->y, b->y) != 0)){ s->inf = 1; return; } l = mpnew(0); k = mpnew(0); sx = mpnew(0); sy = mpnew(0); if(mpcmp(a->x, b->x) == 0 && mpcmp(a->y, b->y) == 0){ mpadd(mpone, mptwo, k); mpmul(a->x, a->x, l); mpmul(l, k, l); mpadd(l, dom->a, l); mpleft(a->y, 1, k); mpmod(k, dom->p, k); mpinvert(k, dom->p, k); mpmul(k, l, l); mpmod(l, dom->p, l); mpleft(a->x, 1, k); mpmul(l, l, sx); mpsub(sx, k, sx); mpmod(sx, dom->p, sx); mpsub(a->x, sx, sy); mpmul(l, sy, sy); mpsub(sy, a->y, sy); mpmod(sy, dom->p, sy); mpassign(sx, s->x); mpassign(sy, s->y); mpfree(sx); mpfree(sy); mpfree(l); mpfree(k); return; } mpsub(b->y, a->y, l); mpmod(l, dom->p, l); mpsub(b->x, a->x, k); mpmod(k, dom->p, k); mpinvert(k, dom->p, k); mpmul(k, l, l); mpmod(l, dom->p, l); mpmul(l, l, sx); mpsub(sx, a->x, sx); mpsub(sx, b->x, sx); mpmod(sx, dom->p, sx); mpsub(a->x, sx, sy); mpmul(sy, l, sy); mpsub(sy, a->y, sy); mpmod(sy, dom->p, sy); mpassign(sx, s->x); mpassign(sy, s->y); mpfree(sx); mpfree(sy); mpfree(l); mpfree(k); }
// extended binary gcd // // For a anv b it solves, v = gcd(a,b) and finds x and y s.t. // ax + by = v // // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608. void mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y) { mpint *u, *A, *B, *C, *D; int g; if(a->top == 0){ mpassign(b, v); mpassign(mpone, y); mpassign(mpzero, x); return; } if(b->top == 0){ mpassign(a, v); mpassign(mpone, x); mpassign(mpzero, y); return; } g = 0; a = mpcopy(a); b = mpcopy(b); while(iseven(a) && iseven(b)){ mpright(a, 1, a); mpright(b, 1, b); g++; } u = mpcopy(a); mpassign(b, v); A = mpcopy(mpone); B = mpcopy(mpzero); C = mpcopy(mpzero); D = mpcopy(mpone); for(;;) { // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(u)){ mpright(u, 1, u); if(!iseven(A) || !iseven(B)) { mpadd(A, b, A); mpsub(B, a, B); } mpright(A, 1, A); mpright(B, 1, B); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(v)){ mpright(v, 1, v); if(!iseven(C) || !iseven(D)) { mpadd(C, b, C); mpsub(D, a, D); } mpright(C, 1, C); mpright(D, 1, D); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); if(mpcmp(u, v) >= 0){ mpsub(u, v, u); mpsub(A, C, A); mpsub(B, D, B); } else { mpsub(v, u, v); mpsub(C, A, C); mpsub(D, B, D); } if(u->top == 0) break; } mpassign(C, x); mpassign(D, y); mpleft(v, g, v); mpfree(A); mpfree(B); mpfree(C); mpfree(D); mpfree(u); mpfree(a); mpfree(b); }
RSApriv* rsagen(int nlen, int elen, int rounds) { mpint *p, *q, *e, *d, *phi, *n, *t1, *t2, *kp, *kq, *c2; RSApriv *rsa; p = mpnew(nlen/2); q = mpnew(nlen/2); n = mpnew(nlen); e = mpnew(elen); d = mpnew(0); phi = mpnew(nlen); // create the prime factors and euclid's function genprime(p, nlen/2, rounds); genprime(q, nlen - mpsignif(p) + 1, rounds); mpmul(p, q, n); mpsub(p, mpone, e); mpsub(q, mpone, d); mpmul(e, d, phi); // find an e relatively prime to phi t1 = mpnew(0); t2 = mpnew(0); mprand(elen, genrandom, e); if(mpcmp(e,mptwo) <= 0) itomp(3, e); // See Menezes et al. p.291 "8.8 Note (selecting primes)" for discussion // of the merits of various choices of primes and exponents. e=3 is a // common and recommended exponent, but doesn't necessarily work here // because we chose strong rather than safe primes. for(;;){ mpextendedgcd(e, phi, t1, d, t2); if(mpcmp(t1, mpone) == 0) break; mpadd(mpone, e, e); } mpfree(t1); mpfree(t2); // compute chinese remainder coefficient c2 = mpnew(0); mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, phi); mpmod(d, phi, kp); mpsub(q, mpone, phi); mpmod(d, phi, kq); rsa = rsaprivalloc(); rsa->pub.ek = e; rsa->pub.n = n; rsa->dk = d; rsa->kp = kp; rsa->kq = kq; rsa->p = p; rsa->q = q; rsa->c2 = c2; mpfree(phi); return rsa; }
static int Zmpbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { size_t ysize = b->size+1; size_t ubits, vbits; int k = 0; mpw* u = wksp; mpw* v = u+ysize; mpw* A = v+ysize; mpw* B = A+ysize; mpw* C = B+ysize; mpw* D = C+ysize; mpsetx(ysize, u, xsize, xdata); mpsetx(ysize, v, b->size, b->modl); mpsetw(ysize, A, 1); mpzero(ysize, B); mpzero(ysize, C); mpsetw(ysize, D, 1); for (k = 0; mpeven(ysize, u) && mpeven(ysize, v); k++) { mpdivtwo(ysize, u); mpdivtwo(ysize, v); } if (mpeven(ysize, u)) (void) mpadd(ysize, u, v); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); ubits = vbits = MP_WORDS_TO_BITS(ysize); do { while (mpeven(ysize, v)) { mpsdivtwo(ysize, v); vbits -= 1; if (mpodd(ysize, C)) { (void) mpaddx(ysize, C, b->size, b->modl); (void) mpsubx(ysize, D, xsize, xdata); } mpsdivtwo(ysize, C); mpsdivtwo(ysize, D); if (_debug < 0) fprintf(stderr, "-->> v: "), mpfprintln(stderr, ysize, v); } if (ubits >= vbits) { mpw* swapu; size_t swapi; if (_debug < 0) fprintf(stderr, "--> (swap u <-> v)\n"); swapu = u; u = v; v = swapu; swapi = ubits; ubits = vbits; vbits = swapi; swapu = A; A = C; C = swapu; swapu = B; B = D; D = swapu; } if (!((u[ysize-1] + v[ysize-1]) & 0x3)) { if (_debug < 0) fprintf(stderr, "--> (even parity)\n"); mpadd(ysize, v, u); mpadd(ysize, C, A); mpadd(ysize, D, B); } else { if (_debug < 0) fprintf(stderr, "--> (odd parity)\n"); mpsub(ysize, v, u); mpsub(ysize, C, A); mpsub(ysize, D, B); } if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); vbits++; } while (mpnz(ysize, v)); #ifdef NOTYET if (!mpisone(ysize, u)) return 0; #endif if (result) { mpsetx(b->size, result, ysize, A); /*@-usedef@*/ if (*A & 0x80000000) (void) mpneg(b->size, result); /*@=usedef@*/ while (--k > 0) mpadd(b->size, result, result); } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); return 1; }
/** * Computes the inverse (modulo b) of x, and returns 1 if x was invertible. * needs workspace of (6*size+6) words * @note xdata and result cannot point to the same area */ static int Xmpbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { /* * Fact: if a element of Zn, then a is invertible if and only if gcd(a,n) = 1 * Hence: if b->modl is even, then x must be odd, otherwise the gcd(x,n) >= 2 * * The calling routine must guarantee this condition. */ size_t ysize = b->size+1; mpw* u = wksp; mpw* v = u+ysize; mpw* A = v+ysize; mpw* B = A+ysize; mpw* C = B+ysize; mpw* D = C+ysize; mpsetx(ysize, u, b->size, b->modl); mpsetx(ysize, v, xsize, xdata); mpsetw(ysize, A, 1); mpzero(ysize, B); mpzero(ysize, C); mpsetw(ysize, D, 1); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); do { while (mpeven(ysize, u)) { mpdivtwo(ysize, u); if (mpodd(ysize, A) || mpodd(ysize, B)) { (void) mpaddx(ysize, A, xsize, xdata); (void) mpsubx(ysize, B, b->size, b->modl); } mpsdivtwo(ysize, A); mpsdivtwo(ysize, B); } while (mpeven(ysize, v)) { mpdivtwo(ysize, v); if (mpodd(ysize, C) || mpodd(ysize, D)) { (void) mpaddx(ysize, C, xsize, xdata); (void) mpsubx(ysize, D, b->size, b->modl); } mpsdivtwo(ysize, C); mpsdivtwo(ysize, D); } if (mpge(ysize, u, v)) { if (_debug < 0) fprintf(stderr, "--> 5 (u >= v)\n"); (void) mpsub(ysize, u, v); (void) mpsub(ysize, A, C); (void) mpsub(ysize, B, D); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); } else { if (_debug < 0) fprintf(stderr, "--> 5 (u < v)\n"); (void) mpsub(ysize, v, u); (void) mpsub(ysize, C, A); (void) mpsub(ysize, D, B); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); } } while (mpnz(ysize, u)); if (!mpisone(ysize, v)) return 0; if (result) { mpsetx(b->size, result, ysize, D); /*@-usedef@*/ if (*D & 0x80000000) (void) mpadd(b->size, result, b->modl); /*@=usedef@*/ } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); return 1; }
// Miller-Rabin probabilistic primality testing // Knuth (1981) Seminumerical Algorithms, p.379 // Menezes et al () Handbook, p.39 // 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep int probably_prime(mpint *n, int nrep) { int j, k, rep, nbits, isprime = 1; mpint *nm1, *q, *x, *y, *r; if(n->sign < 0) sysfatal("negative prime candidate"); if(nrep <= 0) nrep = 18; k = mptoi(n); if(k == 2) // 2 is prime return 1; if(k < 2) // 1 is not prime return 0; if((n->p[0] & 1) == 0) // even is not prime return 0; // test against small prime numbers if(smallprimetest(n) < 0) return 0; // fermat test, 2^n mod n == 2 if p is prime x = uitomp(2, nil); y = mpnew(0); mpexp(x, n, n, y); k = mptoi(y); if(k != 2){ mpfree(x); mpfree(y); return 0; } nbits = mpsignif(n); nm1 = mpnew(nbits); mpsub(n, mpone, nm1); // nm1 = n - 1 */ k = mplowbits0(nm1); q = mpnew(0); mpright(nm1, k, q); // q = (n-1)/2**k for(rep = 0; rep < nrep; rep++){ // x = random in [2, n-2] r = mprand(nbits, prng, nil); mpmod(r, nm1, x); mpfree(r); if(mpcmp(x, mpone) <= 0) continue; // y = x**q mod n mpexp(x, q, n, y); if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0) goto done; for(j = 1; j < k; j++){ mpmul(y, y, x); mpmod(x, n, y); // y = y*y mod n if(mpcmp(y, nm1) == 0) goto done; if(mpcmp(y, mpone) == 0){ isprime = 0; goto done; } } isprime = 0; } done: mpfree(y); mpfree(x); mpfree(q); mpfree(nm1); return isprime; }
/* * Miller-Rabin probabilistic primality testing * Knuth (1981) Seminumerical Algorithms, p.379 * Menezes et al () Handbook, p.39 * 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep */ int probably_prime(mpint *n, int nrep) { int j, k, rep, nbits, isprime; mpint *nm1, *q, *x, *y, *r; if(n->sign < 0) sysfatal("negative prime candidate"); if(nrep <= 0) nrep = 18; k = mptoi(n); if(k == 2) /* 2 is prime */ return 1; if(k < 2) /* 1 is not prime */ return 0; if((n->p[0] & 1) == 0) /* even is not prime */ return 0; /* test against small prime numbers */ if(smallprimetest(n) < 0) return 0; /* fermat test, 2^n mod n == 2 if p is prime */ x = uitomp(2, nil); y = mpnew(0); mpexp(x, n, n, y); k = mptoi(y); if(k != 2){ mpfree(x); mpfree(y); return 0; } nbits = mpsignif(n); nm1 = mpnew(nbits); mpsub(n, mpone, nm1); /* nm1 = n - 1 */ k = mplowbits0(nm1); q = mpnew(0); mpright(nm1, k, q); /* q = (n-1)/2**k */ for(rep = 0; rep < nrep; rep++){ for(;;){ /* find x = random in [2, n-2] */ r = mprand(nbits, prng, nil); mpmod(r, nm1, x); mpfree(r); if(mpcmp(x, mpone) > 0) break; } /* y = x**q mod n */ mpexp(x, q, n, y); if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0) continue; for(j = 1;; j++){ if(j >= k) { isprime = 0; goto done; } mpmul(y, y, x); mpmod(x, n, y); /* y = y*y mod n */ if(mpcmp(y, nm1) == 0) break; if(mpcmp(y, mpone) == 0){ isprime = 0; goto done; } } } isprime = 1; done: mpfree(y); mpfree(x); mpfree(q); mpfree(nm1); return isprime; }