void mpprndsafe_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, mpw* wksp) { /* * Initialize with a probable safe prime of 'size' words, with probability factor t * * A safe prime p has the property that p = 2q+1, where q is also prime * Use for ElGamal type schemes, where a generator of order (p-1) is required */ size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1); mpbinit(p, size); if (p->modl != (mpw*) 0) { mpbarrett q; mpbzero(&q); mpbinit(&q, size); while (1) { /* * Generate a random appropriate candidate prime, and test * it with small prime divisor test BEFORE computing mu */ mpprndbits(p, bits, 2, (mpnumber*) 0, (mpnumber*) 0, rc, wksp); mpcopy(size, q.modl, p->modl); mpdivtwo(size, q.modl); /* do a small prime product trial division on q */ if (!mppsppdiv_w(&q, wksp)) continue; /* do a small prime product trial division on p */ if (!mppsppdiv_w(p, wksp)) continue; /* candidate prime has passed small prime division test for p and q */ mpbmu_w(&q, wksp); if (!mppmilrab_w(&q, rc, t, wksp)) continue; mpbmu_w(p, wksp); if (!mppmilrab_w(p, rc, t, wksp)) continue; mpbfree(&q); return; } } }
/* * needs to make workspace of 8*size+2 */ int dldp_pValidate(const dldp_p* dp, randomGeneratorContext* rgc) { register size_t size = dp->p.size; register mpw* temp = (mpw*) malloc((8*size+2) * sizeof(mpw)); if (temp) { /* check that p > 2 and p odd, then run miller-rabin test with t 50 */ if (mpeven(dp->p.size, dp->p.modl)) { free(temp); return 0; } if (mppmilrab_w(&dp->p, rgc, 50, temp) == 0) { free(temp); return 0; } /* check that q > 2 and q odd, then run miller-rabin test with t 50 */ if (mpeven(dp->q.size, dp->q.modl)) { free(temp); return 0; } if (mppmilrab_w(&dp->q, rgc, 50, temp) == 0) { free(temp); return 0; } free(temp); /* check that 1 < g < p */ if (mpleone(dp->g.size, dp->g.data)) return 0; if (mpgex(dp->g.size, dp->g.data, dp->p.size, dp->p.modl)) return 0; return 1; } return -1; }
/* * needs workspace of (7*size+2) words */ int mpbpprime_w(const mpbarrett* b, randomGeneratorContext* r, int t, mpw* wksp) { /* * This test works for candidate probable primes >= 3, which are also not small primes. * * It assumes that b->modl contains the candidate prime * */ size_t size = b->size; /* first test if modl is odd */ if (mpodd(b->size, b->modl)) { /* * Small prime factor test: * * Tables in mpspprod contain multi-precision integers with products of small primes * If the greatest common divisor of this product and the candidate is not one, then * the candidate has small prime factors, or is a small prime. Neither is acceptable when * we are looking for large probable primes =) * */ if (size > SMALL_PRIMES_PRODUCT_MAX) { mpsetx(size, wksp+size, SMALL_PRIMES_PRODUCT_MAX, mpspprod[SMALL_PRIMES_PRODUCT_MAX-1]); mpgcd_w(size, b->modl, wksp+size, wksp, wksp+2*size); } else { mpgcd_w(size, b->modl, mpspprod[size-1], wksp, wksp+2*size); } if (mpisone(size, wksp)) { return mppmilrab_w(b, r, t, wksp); } } return 0; }
/* * needs workspace of (8*size+2) words */ void mpprndconone_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, const mpbarrett* q, const mpnumber* f, mpnumber* r, int cofactor, mpw* wksp) { /* * Generate a prime p with n bits such that p mod q = 1, and p = qr+1 where r = 2s * * Conditions: q > 2 and size(q) < size(p) and size(f) <= size(p) * * Conditions: r must be chosen so that r is even, otherwise p will be even! * * if cofactor == 0, then s will be chosen randomly * if cofactor == 1, then make sure that q does not divide r, i.e.: * q cannot be equal to r, since r is even, and q > 2; hence if q <= r make sure that GCD(q,r) == 1 * if cofactor == 2, then make sure that s is prime * * Optional input f: if f is not null, then search p so that GCD(p-1,f) = 1 */ mpbinit(p, MP_BITS_TO_WORDS(bits + MP_WBITS - 1)); if (p->modl != (mpw*) 0) { size_t sbits = bits - mpbits(q->size, q->modl) - 1; mpbarrett s; mpbzero(&s); mpbinit(&s, MP_BITS_TO_WORDS(sbits + MP_WBITS - 1)); while (1) { mpprndbits(&s, sbits, 0, (mpnumber*) 0, (mpnumber*) 0, rc, wksp); if (cofactor == 1) { mpsetlsb(s.size, s.modl); /* if (q <= s) check if GCD(q,s) != 1 */ if (mplex(q->size, q->modl, s.size, s.modl)) { /* we can find adequate storage for computing the gcd in s->wksp */ mpsetx(s.size, wksp, q->size, q->modl); mpgcd_w(s.size, s.modl, wksp, wksp+s.size, wksp+2*s.size); if (!mpisone(s.size, wksp+s.size)) continue; } } else if (cofactor == 2) { mpsetlsb(s.size, s.modl); } if (cofactor == 2) { /* do a small prime product trial division test on r */ if (!mppsppdiv_w(&s, wksp)) continue; } /* multiply q*s */ mpmul(wksp, s.size, s.modl, q->size, q->modl); /* s.size + q.size may be greater than p.size by 1, but the product will fit exactly into p */ mpsetx(p->size, p->modl, s.size+q->size, wksp); /* multiply by two and add 1 */ mpmultwo(p->size, p->modl); mpaddw(p->size, p->modl, 1); /* test if the product actually contains enough bits */ if (mpbits(p->size, p->modl) < bits) continue; /* do a small prime product trial division test on p */ if (!mppsppdiv_w(p, wksp)) continue; /* if we have an f, do the congruence test */ if (f != (mpnumber*) 0) { mpcopy(p->size, wksp, p->modl); mpsubw(p->size, wksp, 1); mpsetx(p->size, wksp, f->size, f->data); mpgcd_w(p->size, wksp, wksp+p->size, wksp+2*p->size, wksp+3*p->size); if (!mpisone(p->size, wksp+2*p->size)) continue; } /* if cofactor is two, test if s is prime */ if (cofactor == 2) { mpbmu_w(&s, wksp); if (!mppmilrab_w(&s, rc, mpptrials(sbits), wksp)) continue; } /* candidate has passed so far, now we do the probabilistic test on p */ mpbmu_w(p, wksp); if (!mppmilrab_w(p, rc, t, wksp)) continue; mpnset(r, s.size, s.modl); mpmultwo(r->size, r->data); mpbfree(&s); return; } } }
/* * implements IEEE P1363 A.15.6 * * f, min, max are optional */ int mpprndr_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, const mpnumber* min, const mpnumber* max, const mpnumber* f, mpw* wksp) { /* * Generate a prime into p with the requested number of bits * * Conditions: size(f) <= size(p) * * Optional input min: if min is not null, then search p so that min <= p * Optional input max: if max is not null, then search p so that p <= max * Optional input f: if f is not null, then search p so that GCD(p-1,f) = 1 */ size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1); /* if min has more bits than what was requested for p, bail out */ if (min && (mpbits(min->size, min->data) > bits)) return -1; /* if max has a different number of bits than what was requested for p, bail out */ if (max && (mpbits(max->size, max->data) != bits)) return -1; /* if min is not less than max, bail out */ if (min && max && mpgex(min->size, min->data, max->size, max->data)) return -1; mpbinit(p, size); if (p->modl) { while (1) { /* * Generate a random appropriate candidate prime, and test * it with small prime divisor test BEFORE computing mu */ mpprndbits(p, bits, 1, min, max, rc, wksp); /* do a small prime product trial division test on p */ if (!mppsppdiv_w(p, wksp)) continue; /* if we have an f, do the congruence test */ if (f != (mpnumber*) 0) { mpcopy(size, wksp, p->modl); mpsubw(size, wksp, 1); mpsetx(size, wksp+size, f->size, f->data); mpgcd_w(size, wksp, wksp+size, wksp+2*size, wksp+3*size); if (!mpisone(size, wksp+2*size)) continue; } /* candidate has passed so far, now we do the probabilistic test */ mpbmu_w(p, wksp); if (mppmilrab_w(p, rc, t, wksp)) return 0; } } return -1; }