Пример #1
0
/*
 *  this code assumes that a vlong is an integral number of
 *  mpdigits long.
 */
mpint*
vtomp(vlong v, mpint *b)
{
	int s;
	uvlong uv;

	if(b == nil)
		b = mpnew(VLDIGITS*sizeof(mpdigit));
	else
		mpbits(b, VLDIGITS*sizeof(mpdigit));
	mpassign(mpzero, b);
	if(v == 0)
		return b;
	if(v < 0){
		b->sign = -1;
		uv = -v;
	} else
		uv = v;
	for(s = 0; s < VLDIGITS && uv != 0; s++){
		b->p[s] = uv;
		uv >>= sizeof(mpdigit)*8;
	}
	b->top = s;
	return b;
}
Пример #2
0
// sum = abs(b1) + abs(b2), i.e., add the magnitudes
void
mpmagadd(mpint *b1, mpint *b2, mpint *sum)
{
	int m, n;
	mpint *t;

	// get the sizes right
	if(b2->top > b1->top){
		t = b1;
		b1 = b2;
		b2 = t;
	}
	n = b1->top;
	m = b2->top;
	if(n == 0){
		mpassign(mpzero, sum);
		return;
	}
	if(m == 0){
		mpassign(b1, sum);
		return;
	}
	mpbits(sum, (n+1)*Dbits);
	sum->top = n+1;

	mpvecadd(b1->p, n, b2->p, m, sum->p);
	sum->sign = 1;

	mpnorm(sum);
}
Пример #3
0
// convert a big-endian byte array (most significant byte first) to an mpint
mpint*
betomp(uchar *p, uint n, mpint *b)
{
    int m, s;
    mpdigit x;

    if(b == nil)
        b = mpnew(0);

    // dump leading zeros
    while(*p == 0 && n > 1) {
        p++;
        n--;
    }

    // get the space
    mpbits(b, n*8);
    b->top = DIGITS(n*8);
    m = b->top-1;

    // first digit might not be Dbytes long
    s = ((n-1)*8)%Dbits;
    x = 0;
    for(; n > 0; n--) {
        x |= ((mpdigit)(*p++)) << s;
        s -= 8;
        if(s < 0) {
            b->p[m--] = x;
            s = Dbits-8;
            x = 0;
        }
    }

    return b;
}
Пример #4
0
int main()
{
	dldp_p params;
	mpnumber gq;
	javalong start, now;
	int iterations = 0;

	dldp_pInit(&params);

	mpbsethex(&params.p, hp);
	mpbsethex(&params.q, hq);
	mpnsethex(&params.g, hg);
	mpnzero(&gq);

	/* get starting time */
	start = timestamp();
	do
	{
		mpbnpowmod(&params.p, &params.g, (mpnumber*) &params.q, &gq);
		now = timestamp();
		iterations++;
	} while (now < (start + (SECONDS * ONE_SECOND)));

	mpnfree(&gq);

	printf("(%d bits ^ %d bits) mod (%d bits): %d times in %d seconds\n",
		(int) mpbits(params.g.size, params.g.data),
		(int) mpbits(params.q.size, params.q.modl),
		(int) mpbits(params.p.size, params.p.modl),
		iterations,
		SECONDS);

	dldp_pFree(&params);

	return 0;
}
Пример #5
0
/*
 *  this code assumes that a vlong is an integral number of
 *  mpdigits long.
 */
mpint*
uvtomp(uint64_t v, mpint *b)
{
	int s;

	if(b == nil)
		b = mpnew(VLDIGITS*sizeof(mpdigit));
	else
		mpbits(b, VLDIGITS*sizeof(mpdigit));
	mpassign(mpzero, b);
	if(v == 0)
		return b;
	for(s = 0; s < VLDIGITS && v != 0; s++){
		b->p[s] = v;
		v >>= sizeof(mpdigit)*8;
	}
	b->top = s;
	return b;
}
Пример #6
0
//  generate a probable prime.  accuracy is the miller-rabin interations
void
genprime(mpint *p, int n, int accuracy)
{
	mpdigit x;

	// generate n random bits with high and low bits set
	mpbits(p, n);
	genrandom((uint8_t*)p->p, (n+7)/8);
	p->top = (n+Dbits-1)/Dbits;
	x = 1;
	x <<= ((n-1)%Dbits);
	p->p[p->top-1] &= (x-1);
	p->p[p->top-1] |= x;
	p->p[0] |= 1;

	// keep icrementing till it looks prime
	for(;;){
		if(probably_prime(p, accuracy))
			break;
		mpadd(p, mptwo, p);
	}
}
Пример #7
0
// convert a little endian byte array (least significant byte first) to an mpint
mpint*
letomp(uchar *s, uint n, mpint *b)
{
	int i=0, m = 0;
	mpdigit x=0;

	if(b == nil)
		b = mpnew(0);
	mpbits(b, 8*n);
	for(; n > 0; n--){
		x |= ((mpdigit)(*s++)) << i;
		i += 8;
		if(i == Dbits){
			b->p[m++] = x;
			i = 0;
			x = 0;
		}
	}
	if(i > 0)
		b->p[m++] = x;
	b->top = m;
	return b;
}
Пример #8
0
void
mpmul(mpint *b1, mpint *b2, mpint *prod)
{
	mpint *oprod;

	oprod = nil;
	if(prod == b1 || prod == b2){
		oprod = prod;
		prod = mpnew(0);
	}

	prod->top = 0;
	mpbits(prod, (b1->top+b2->top+1)*Dbits);
	mpvecmul(b1->p, b1->top, b2->p, b2->top, prod->p);
	prod->top = b1->top+b2->top+1;
	prod->sign = b1->sign*b2->sign;
	mpnorm(prod);

	if(oprod != nil){
		mpassign(prod, oprod);
		mpfree(prod);
	}
}
Пример #9
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;
		}
	}
}
Пример #10
0
/*
 * 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;
}
Пример #11
0
mpint*
mpfactorial(ulong n)
{
    int i;
    ulong k;
    unsigned cnt;
    int max, mmax;
    mpdigit p, pp[2];
    mpint *r, *s, *stk[31];

    cnt = 0;
    max = mmax = -1;
    p = 1;
    r = mpnew(0);
    for(k=2; k<=n; k++) {
        pp[0] = 0;
        pp[1] = 0;
        mpvecdigmuladd(&p, 1, (mpdigit)k, pp);
        if(pp[1] == 0)	/* !overflow */
            p = pp[0];
        else {
            cnt++;
            if((cnt & 1) == 0) {
                s = stk[max];
                mpbits(r, Dbits*(s->top+1+1));
                memset(r->p, 0, Dbytes*(s->top+1+1));
                mpvecmul(s->p, s->top, &p, 1, r->p);
                r->sign = 1;
                r->top = s->top+1+1;		/* XXX: norm */
                mpassign(r, s);
                for(i=4; (cnt & (i-1)) == 0; i=i<<1) {
                    mpmul(stk[max], stk[max-1], r);
                    mpassign(r, stk[max-1]);
                    max--;
                }
            } else {
                max++;
                if(max > mmax) {
                    mmax++;
                    if(max > nelem(stk))
                        abort();
                    stk[max] = mpnew(Dbits);
                }
                stk[max]->top = 1;
                stk[max]->p[0] = p;
            }
            p = (mpdigit)k;
        }
    }
    if(max < 0) {
        mpbits(r, Dbits);
        r->top = 1;
        r->sign = 1;
        r->p[0] = p;
    } else {
        s = stk[max--];
        mpbits(r, Dbits*(s->top+1+1));
        memset(r->p, 0, Dbytes*(s->top+1+1));
        mpvecmul(s->p, s->top, &p, 1, r->p);
        r->sign = 1;
        r->top = s->top+1+1;		/* XXX: norm */
    }

    while(max >= 0)
        mpmul(r, stk[max--], r);
    for(max=mmax; max>=0; max--)
        mpfree(stk[max]);
    mpnorm(r);
    return r;
}
Пример #12
0
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;
}
Пример #13
0
size_t mpbbits(const mpbarrett* b)
{
	return mpbits(b->size, b->modl);
}
Пример #14
0
Файл: mpdiv.c Проект: 8l/inferno
void
mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder)
{
	int j, s, vn, sign;
	mpdigit qd, *up, *vp, *qp;
	mpint *u, *v, *t;

	// divide bv zero
	if(divisor->top == 0)
		sysfatal("mpdiv: divide by zero");

	// quick check
	if(mpmagcmp(dividend, divisor) < 0){
		if(remainder != nil)
			mpassign(dividend, remainder);
		if(quotient != nil)
			mpassign(mpzero, quotient);
		return;
	}

	// D1: shift until divisor, v, has hi bit set (needed to make trial
	//     divisor accurate)
	qd = divisor->p[divisor->top-1];
	for(s = 0; (qd & mpdighi) == 0; s++)
		qd <<= 1;
	u = mpnew((dividend->top+2)*Dbits + s);
	if(s == 0 && divisor != quotient && divisor != remainder) {
		mpassign(dividend, u);
		v = divisor;
	} else {
		mpleft(dividend, s, u);
		v = mpnew(divisor->top*Dbits);
		mpleft(divisor, s, v);
	}
	up = u->p+u->top-1;
	vp = v->p+v->top-1;
	vn = v->top;

	// D1a: make sure high digit of dividend is less than high digit of divisor
	if(*up >= *vp){
		*++up = 0;
		u->top++;
	}

	// storage for multiplies
	t = mpnew(4*Dbits);

	qp = nil;
	if(quotient != nil){
		mpbits(quotient, (u->top - v->top)*Dbits);
		quotient->top = u->top - v->top;
		qp = quotient->p+quotient->top-1;
	}

	// D2, D7: loop on length of dividend
	for(j = u->top; j > vn; j--){

		// D3: calculate trial divisor
		mpdigdiv(up-1, *vp, &qd);

		// D3a: rule out trial divisors 2 greater than real divisor
		if(vn > 1) for(;;){
			memset(t->p, 0, 3*Dbytes);	// mpvecdigmuladd adds to what's there
			mpvecdigmuladd(vp-1, 2, qd, t->p);
			if(mpveccmp(t->p, 3, up-2, 3) > 0)
				qd--;
			else
				break;
		}

		// D4: u -= v*qd << j*Dbits
		sign = mpvecdigmulsub(v->p, vn, qd, up-vn);
		if(sign < 0){

			// D6: trial divisor was too high, add back borrowed
			//     value and decrease divisor
			mpvecadd(up-vn, vn+1, v->p, vn, up-vn);
			qd--;
		}

		// D5: save quotient digit
		if(qp != nil)
			*qp-- = qd;

		// push top of u down one
		u->top--;
		*up-- = 0;
	}
	if(qp != nil){
		mpnorm(quotient);
		if(dividend->sign != divisor->sign)
			quotient->sign = -1;
	}

	if(remainder != nil){
		mpright(u, s, remainder);	// u is the remainder shifted
		remainder->sign = dividend->sign;
	}

	mpfree(t);
	mpfree(u);
	if(v != divisor)
		mpfree(v);
}