void ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s) { ECpriv tmp; mpint *E, *t; tmp.x = mpnew(0); tmp.y = mpnew(0); tmp.d = mpnew(0); E = betomp(dig, len, nil); t = mpnew(0); if(mpsignif(dom->n) < 8*len) mpright(E, 8*len - mpsignif(dom->n), E); for(;;){ ecgen(dom, &tmp); mpmod(tmp.x, dom->n, r); if(mpcmp(r, mpzero) == 0) continue; mpmul(r, priv->d, s); mpadd(E, s, s); mpinvert(tmp.d, dom->n, t); mpmul(s, t, s); mpmod(s, dom->n, s); if(mpcmp(s, mpzero) != 0) break; } mpfree(t); mpfree(E); mpfree(tmp.x); mpfree(tmp.y); mpfree(tmp.d); }
// find a prime p of length n and a generator alpha of Z^*_p // Alg 4.86 Menezes et al () Handbook, p.164 void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy) { mpint *q, *b; q = mpnew(n-1); while(1){ genprime(q, n-1, accuracy); mpleft(q, 1, p); mpadd(p, mpone, p); // p = 2*q+1 if(probably_prime(p, accuracy)) break; } // now find a generator alpha of the multiplicative // group Z*_p of order p-1=2q b = mpnew(0); while(1){ mprand(n, genrandom, alpha); mpmod(alpha, p, alpha); mpmul(alpha, alpha, b); mpmod(b, p, b); if(mpcmp(b, mpone) == 0) continue; mpexp(alpha, q, p, b); if(mpcmp(b, mpone) != 0) break; } mpfree(b); mpfree(q); }
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; }
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; }
void ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s) { ECpoint ns, na; mpint *l; if(a->inf || mpcmp(k, mpzero) == 0){ s->inf = 1; return; } ns.inf = 1; ns.x = mpnew(0); ns.y = mpnew(0); na.x = mpnew(0); na.y = mpnew(0); ecassign(dom, a, &na); l = mpcopy(k); l->sign = 1; while(mpcmp(l, mpzero) != 0){ if(l->p[0] & 1) ecadd(dom, &na, &ns, &ns); ecadd(dom, &na, &na, &na); mpright(l, 1, l); } if(k->sign < 0){ ns.y->sign = -1; mpmod(ns.y, dom->p, ns.y); } ecassign(dom, &ns, s); mpfree(ns.x); mpfree(ns.y); mpfree(na.x); mpfree(na.y); }
int egverify(EGpub *pub, EGsig *sig, mpint *m) { mpint *p = pub->p, *alpha = pub->alpha; mpint *r = sig->r, *s = sig->s; mpint *v1, *v2, *rs; int rv = -1; if(mpcmp(r, mpone) < 0 || mpcmp(r, p) >= 0) return rv; v1 = mpnew(0); rs = mpnew(0); v2 = mpnew(0); mpexp(pub->key, r, p, v1); mpexp(r, s, p, rs); mpmul(v1, rs, v1); mpmod(v1, p, v1); mpexp(alpha, m, p, v2); if(mpcmp(v1, v2) == 0) rv = 0; mpfree(v1); mpfree(rs); mpfree(v2); return rv; }
int dsaverify(DSApub *pub, DSAsig *sig, mpint *m) { int rv = -1; mpint *u1, *u2, *v, *sinv; if(sig->r->sign < 0 || mpcmp(sig->r, pub->q) >= 0) return rv; if(sig->s->sign < 0 || mpcmp(sig->s, pub->q) >= 0) return rv; u1 = mpnew(0); u2 = mpnew(0); v = mpnew(0); sinv = mpnew(0); // find (s**-1) mod q, make sure it exists mpextendedgcd(sig->s, pub->q, u1, sinv, v); if(mpcmp(u1, mpone) != 0) goto out; // u1 = (sinv * m) mod q, u2 = (r * sinv) mod q mpmul(sinv, m, u1); mpmod(u1, pub->q, u1); mpmul(sig->r, sinv, u2); mpmod(u2, pub->q, u2); // v = (((alpha**u1)*(key**u2)) mod p) mod q mpexp(pub->alpha, u1, pub->p, sinv); mpexp(pub->key, u2, pub->p, v); mpmul(sinv, v, v); mpmod(v, pub->p, v); mpmod(v, pub->q, v); if(mpcmp(v, sig->r) == 0) rv = 0; out: mpfree(v); mpfree(u1); mpfree(u2); mpfree(sinv); return rv; }
int ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s) { mpint *E, *t, *u1, *u2; ECpoint R, S; int ret; if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0) return 0; E = betomp(dig, len, nil); if(mpsignif(dom->n) < 8*len) mpright(E, 8*len - mpsignif(dom->n), E); t = mpnew(0); u1 = mpnew(0); u2 = mpnew(0); R.x = mpnew(0); R.y = mpnew(0); S.x = mpnew(0); S.y = mpnew(0); mpinvert(s, dom->n, t); mpmul(E, t, u1); mpmod(u1, dom->n, u1); mpmul(r, t, u2); mpmod(u2, dom->n, u2); ecmul(dom, dom->G, u1, &R); ecmul(dom, pub, u2, &S); ecadd(dom, &R, &S, &R); ret = 0; if(!R.inf){ mpmod(R.x, dom->n, t); ret = mpcmp(r, t) == 0; } mpfree(t); mpfree(u1); mpfree(u2); mpfree(R.x); mpfree(R.y); mpfree(S.x); mpfree(S.y); return ret; }
int ecverify(ECdomain *dom, ECpoint *a) { mpint *p, *q; int r; if(a->inf) return 1; p = mpnew(0); q = mpnew(0); mpmul(a->y, a->y, p); mpmod(p, dom->p, p); mpmul(a->x, a->x, q); mpadd(q, dom->a, q); mpmul(a->x, q, q); mpadd(q, dom->b, q); mpmod(q, dom->p, q); r = mpcmp(p, q); mpfree(p); mpfree(q); return r == 0; }
// use extended gcd to find the multiplicative inverse // res = b**-1 mod m void mpinvert(mpint *b, mpint *m, mpint *res) { mpint *dc1, *dc2; // don't care dc1 = mpnew(0); dc2 = mpnew(0); mpextendedgcd(b, m, dc1, res, dc2); if(mpcmp(dc1, mpone) != 0) abort(); mpmod(res, m, res); mpfree(dc1); mpfree(dc2); }
/* convert to residues, returns a newly created structure */ CRTres* crtin(CRTpre *crt, mpint *x) { int i; CRTres *res; res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n); if(res == nil) sysfatal("crtin: %r"); res->n = crt->n; for(i = 0; i < res->n; i++){ res->r[i] = mpnew(0); mpmod(x, crt->m[i], res->r[i]); } return res; }
/* 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); }
/* setup crt info, returns a newly created structure */ CRTpre* crtpre(int n, mpint **m) { CRTpre *crt; int i, j; mpint *u; crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n); if(crt == nil) sysfatal("crtpre: %r"); crt->m = crt->a; crt->c = crt->a+n; crt->p = crt->c+n; crt->n = n; /* make a copy of the moduli */ for(i = 0; i < n; i++) crt->m[i] = mpcopy(m[i]); /* precompute the products */ u = mpcopy(mpone); for(i = 0; i < n; i++){ mpmul(u, m[i], u); crt->p[i] = mpcopy(u); } /* precompute the coefficients */ for(i = 1; i < n; i++){ crt->c[i] = mpcopy(mpone); for(j = 0; j < i; j++){ mpinvert(m[j], m[i], u); mpmul(u, crt->c[i], u); mpmod(u, m[i], crt->c[i]); } } mpfree(u); return crt; }
static int mpleg(mpint *a, mpint *b) { int r, k; mpint *m, *n, *t; r = 1; m = mpcopy(a); n = mpcopy(b); for(;;){ if(mpcmp(m, n) > 0) mpmod(m, n, m); if(mpcmp(m, mpzero) == 0){ r = 0; break; } if(mpcmp(m, mpone) == 0) break; k = mplowbits0(m); if(k > 0){ if(k & 1) switch(n->p[0] & 15){ case 3: case 5: case 11: case 13: r = -r; } mpright(m, k, m); } if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3) r = -r; t = m; m = n; n = t; } mpfree(m); mpfree(n); return r; }
int dsasign(const mpbarrett* p, const mpbarrett* q, const mpnumber* g, randomGeneratorContext* rgc, const mpnumber* hm, const mpnumber* x, mpnumber* r, mpnumber* s) { register size_t psize = p->size; register size_t qsize = q->size; register mpw* ptemp; register mpw* qtemp; register mpw* pwksp; register mpw* qwksp; register int rc = -1; ptemp = (mpw*) malloc((5*psize+2)*sizeof(mpw)); if (ptemp == (mpw*) 0) return rc; qtemp = (mpw*) malloc((9*qsize+6)*sizeof(mpw)); if (qtemp == (mpw*) 0) { free(ptemp); return rc; } pwksp = ptemp+psize; qwksp = qtemp+3*qsize; /* allocate r */ mpnfree(r); mpnsize(r, qsize); /* get a random k, invertible modulo q; store k @ qtemp, inv(k) @ qtemp+qsize */ mpbrndinv_w(q, rgc, qtemp, qtemp+qsize, qwksp); /* g^k mod p */ mpbpowmod_w(p, g->size, g->data, qsize, qtemp, ptemp, pwksp); /* (g^k mod p) mod q - simple modulo */ mpmod(qtemp+2*qsize, psize, ptemp, qsize, q->modl, pwksp); mpcopy(qsize, r->data, qtemp+psize+qsize); /* allocate s */ mpnfree(s); mpnsize(s, qsize); /* x*r mod q */ mpbmulmod_w(q, x->size, x->data, r->size, r->data, qtemp, qwksp); /* add h(m) mod q */ mpbaddmod_w(q, qsize, qtemp, hm->size, hm->data, qtemp+2*qsize, qwksp); /* multiply inv(k) mod q */ mpbmulmod_w(q, qsize, qtemp+qsize, qsize, qtemp+2*qsize, s->data, qwksp); rc = 0; free(qtemp); free(ptemp); return rc; }
/* * 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; }
// 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; }
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); }
void mpexp(mpint *b, mpint *e, mpint *m, mpint *res) { mpint *t[2]; int tofree; mpdigit d, bit; int i, j; t[0] = mpcopy(b); t[1] = res; tofree = 0; if(res == b){ b = mpcopy(b); tofree |= Freeb; } if(res == e){ e = mpcopy(e); tofree |= Freee; } if(res == m){ m = mpcopy(m); tofree |= Freem; } // skip first bit i = e->top-1; d = e->p[i]; for(bit = mpdighi; (bit & d) == 0; bit >>= 1) ; bit >>= 1; j = 0; for(;;){ for(; bit != 0; bit >>= 1){ mpmul(t[j], t[j], t[j^1]); if(bit & d) mpmul(t[j^1], b, t[j]); else j ^= 1; if(m != nil && t[j]->top > m->top){ mpmod(t[j], m, t[j^1]); j ^= 1; } } if(--i < 0) break; bit = mpdighi; d = e->p[i]; } if(m != nil){ mpmod(t[j], m, t[j^1]); j ^= 1; } if(t[j] == res){ mpfree(t[j^1]); } else { mpassign(t[j], res); mpfree(t[j]); } if(tofree){ if(tofree & Freeb) mpfree(b); if(tofree & Freee) mpfree(e); if(tofree & Freem) mpfree(m); } }
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; }
int dsavrfy(const mpbarrett* p, const mpbarrett* q, const mpnumber* g, const mpnumber* hm, const mpnumber* y, const mpnumber* r, const mpnumber* s) { register size_t psize = p->size; register size_t qsize = q->size; register mpw* ptemp; register mpw* qtemp; register mpw* pwksp; register mpw* qwksp; register int rc = 0; /* h(m) shouldn't contain more bits than q */ if (mpbits(hm->size, hm->data) > mpbits(q->size, q->modl)) return rc; /* check 0 < r < q */ if (mpz(r->size, r->data)) return rc; if (mpgex(r->size, r->data, qsize, q->modl)) return rc; /* check 0 < s < q */ if (mpz(s->size, s->data)) return rc; if (mpgex(s->size, s->data, qsize, q->modl)) return rc; ptemp = (mpw*) malloc((6*psize+2)*sizeof(mpw)); if (ptemp == (mpw*) 0) return rc; qtemp = (mpw*) malloc((8*qsize+6)*sizeof(mpw)); if (qtemp == (mpw*) 0) { free(ptemp); return rc; } pwksp = ptemp+2*psize; qwksp = qtemp+2*qsize; mpsetx(qsize, qtemp+qsize, s->size, s->data); /* compute w = inv(s) mod q */ if (mpextgcd_w(qsize, q->modl, qtemp+qsize, qtemp, qwksp)) { /* compute u1 = h(m)*w mod q */ mpbmulmod_w(q, hm->size, hm->data, qsize, qtemp, qtemp+qsize, qwksp); /* compute u2 = r*w mod q */ mpbmulmod_w(q, r->size, r->data, qsize, qtemp, qtemp, qwksp); /* compute g^u1 mod p */ mpbpowmod_w(p, g->size, g->data, qsize, qtemp+qsize, ptemp, pwksp); /* compute y^u2 mod p */ mpbpowmod_w(p, y->size, y->data, qsize, qtemp, ptemp+psize, pwksp); /* multiply mod p */ mpbmulmod_w(p, psize, ptemp, psize, ptemp+psize, ptemp, pwksp); /* modulo q */ mpmod(ptemp+psize, psize, ptemp, qsize, q->modl, pwksp); rc = mpeqx(r->size, r->data, psize, ptemp+psize); } free(qtemp); free(ptemp); return rc; }