Ejemplo n.º 1
0
int root(mpz_class& result, const mpz_class arg, const mpz_class prime)
{
	mpz_class y, b, t;
	unsigned int r, m;

	if (arg % prime == 0) {
		result = 0;
		return 1;
	}
	if (mpz_legendre(arg.get_mpz_t(), prime.get_mpz_t()) == -1)
		return -1;

	b = 0;
	t = 0;
	y = 2;
	while(mpz_legendre(y.get_mpz_t(), prime.get_mpz_t()) != -1)
	{
		y++;
	}

	result = prime - 1;
	r = mpz_scan1(result.get_mpz_t(), 0);
	mpz_rshift(result.get_mpz_t(), result.get_mpz_t(), r);

	mpz_powm(y.get_mpz_t(), y.get_mpz_t(), result.get_mpz_t(), prime.get_mpz_t());

	mpz_rshift(result.get_mpz_t(), result.get_mpz_t(), 1);
	mpz_powm(b.get_mpz_t(), arg.get_mpz_t(), result.get_mpz_t(), prime.get_mpz_t());

	result = (arg * b) % prime;

	b = (result * b) % prime;

	while(b != 1) {
		t = (b * b) % prime;
		for(m = 1; t != 1; m++) {
			t = (t * t) % prime;
		}

		t = 0;
		mpz_setbit(t.get_mpz_t(), r - m - 1);
		mpz_powm(t.get_mpz_t(), y.get_mpz_t(), t.get_mpz_t(), prime.get_mpz_t());

		y = t * t;

		r = m;

		result = (result * t) % prime;

		b = (b * y) % prime;
	}
	return 1;
}
Ejemplo n.º 2
0
static PyObject *
GMPy_MPZ_Function_Legendre(PyObject *self, PyObject *args)
{
    MPZ_Object *tempx = NULL, *tempy = NULL;
    long res;

    if (PyTuple_GET_SIZE(args) != 2) {
        TYPE_ERROR("legendre() requires 'mpz','mpz' arguments");
        return NULL;
    }

    if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
        !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {

        Py_XDECREF((PyObject*)tempx);
        Py_XDECREF((PyObject*)tempy);
        return NULL;
    }

    if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) {
        VALUE_ERROR("y must be odd, prime, and >0");
        Py_DECREF((PyObject*)tempx);
        Py_DECREF((PyObject*)tempy);
        return NULL;
    }

    res = (long)(mpz_legendre(tempx->z, tempy->z));
    Py_DECREF((PyObject*)tempx);
    Py_DECREF((PyObject*)tempy);
    return PyIntOrLong_FromLong(res);
}
Ejemplo n.º 3
0
Archivo: tinyfp.c Proyecto: blynn/pbc
static int fp_is_sqr(element_ptr a) {
  int res;
  mpz_t z;
  mpz_init(z);
  //0 is a square
  if (fp_is0(a)) return 1;
  fp_to_mpz(z, a);
  res = mpz_legendre(z, a->field->order) == 1;
  mpz_clear(z);
  return res;
}
Ejemplo n.º 4
0
static int fp_is_sqr(element_ptr a) {
	eptr ad = (eptr)a->data;
	int res;
	mpz_t z;
	mpz_init(z);
	// 0 is a square.
	if (!ad->flag) return 1;
	fp_to_mpz(z, a);
	res = mpz_legendre(z, a->field->order) == 1;
	mpz_clear(z);
	return res;
}
Ejemplo n.º 5
0
static Variant HHVM_FUNCTION(gmp_legendre,
                             const Variant& dataA,
                             const Variant& dataB) {
  mpz_t gmpDataA, gmpDataB;

  if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_LEGENDRE, gmpDataA, dataA)) {
    return false;
  }
  if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_LEGENDRE, gmpDataB, dataB)) {
    mpz_clear(gmpDataA);
    return false;
  }

  int64_t result = mpz_legendre(gmpDataA, gmpDataB);

  mpz_clear(gmpDataA);
  mpz_clear(gmpDataB);

  return result;
}
Ejemplo n.º 6
0
void Sieve::CreateFactorBase(void)
{
	factorbase.push_back(2);
	mpz_class tmpmpz;
	for (int i = 1; i < lowprimes::n && lowprimes::primearray[i] < B; i++)
	{
		tmpmpz = lowprimes::primearray[i];
		if (mpz_legendre(N.get_mpz_t(), tmpmpz.get_mpz_t()) == 1)
		{
#ifdef PRINTALL
			std::cout << lowprimes::primearray[i] << " ";
#endif
			factorbase.push_back(lowprimes::primearray[i]);
		}
	}
#ifdef PRINTALL
	std::cout << std::endl;
#endif

	array = new int[factorbase.size()];
}
Ejemplo n.º 7
0
static int zp_is_sqr(element_ptr a) {
  //0 is a square
  if (mpz_is0(a->data)) return 1;
  return mpz_legendre(a->data, a->field->order) == 1;
}
Ejemplo n.º 8
0
// A quadratic sieve implementation for integers up to 100 bits. N must be composite.
mpz_class quadratic_sieve(mpz_class &N) {
	std::vector<uint32_t> factor_base;

	mpz_class sqrt_N = sqrt(N);
	//const unsigned long sqrt_N_long = sqrt_N.get_ui();

	// Set the smoothness bound.
	uint32_t B;
	{
		// Approximation of the natural logarithm of N.
		float log_N = mpz_sizeinbase(N.get_mpz_t(), 2) * log(2);

		// The optimal smoothness bound is exp((0.5 + o(1)) * sqrt(log(n)*log(log(n)))).
		B = (uint32_t)ceil(exp(0.56 * sqrt(log_N * log(log_N)))) + 300;
	}

	// Generate the factor base using a sieve.
	{
		char *sieve = new char[B + 1];
		memset(sieve, 1, B + 1);
		for(unsigned long p = 2; p <= B; ++p) {
			if(!sieve[p])
				continue;

			if(mpz_legendre(N.get_mpz_t(), mpz_class(p).get_mpz_t()) == 1)
				factor_base.push_back(p);

			for(unsigned long i = p; i <= B; i += p)
				sieve[i] = 0;
		}
		delete[] sieve;
	}

	std::vector<uint32_t> X;
	float *Y = new float[SIEVE_CHUNK];

	std::vector<std::vector<uint32_t> > smooth;

	int fails = 0;

	// The sieve boundary.
	uint32_t min_x = 0;
	uint32_t max_x = SIEVE_CHUNK;

	// Calculate sieve index (where to start the sieve) for each factor base number.
	uint32_t **fb_indexes = new uint32_t*[2];
	fb_indexes[0] = new uint32_t[factor_base.size()];
	fb_indexes[1] = new uint32_t[factor_base.size()];
	for(uint32_t p = 0; p < factor_base.size(); ++p) {
		// At what indexes do we start this sieve? Solve the congruence x^2 = n (mod p) to find out.
		// Results in two solutions, so we do two sieve iterations for each prime in the factor base.
		uint32_t idxs[2];
		mpz_class temp = N % mpz_class(factor_base[p]);
		tonelli_shanks(temp.get_ui(), factor_base[p], idxs);

		temp = idxs[0] - sqrt_N;
		temp = ((temp % factor_base[p]) + factor_base[p]) % factor_base[p];
		fb_indexes[0][p] = temp.get_ui();

		temp = idxs[1] - sqrt_N;
		temp = ((temp % factor_base[p]) + factor_base[p]) % factor_base[p];
		fb_indexes[1][p] = temp.get_ui();
	}

	float last_estimate = 0;
	uint32_t next_estimate = 1;

	// Sieve new chunks until we have enough smooth numbers.
	while(smooth.size() < (factor_base.size() + 20)) {
		// Generate our Y vector for the sieve, containing log approximations that fit in machine words.
		for(uint32_t t = 1; t < SIEVE_CHUNK; ++t) {
			// Calculating a log estimate is expensive, so don't do it for every Y[t].
			if(next_estimate <= (t + min_x)) {
				mpz_class y = (sqrt_N + t + min_x) * (sqrt_N + t + min_x) - N;

				// To estimate the 2 logarithm, just count the number of bits that v takes up.
				last_estimate = mpz_sizeinbase(y.get_mpz_t(), 2);

				// The higher t gets, the less the logarithm of Y[t] changes.
				next_estimate = next_estimate * 1.8 + 1;
			}

			Y[t] = last_estimate;
		}

		// Perform the actual sieve.
		for(uint32_t p = 0; p < factor_base.size(); ++p) {
			float lg = log(factor_base[p]) / log(2);

			for(uint32_t t = 0; t < 2; ++t) {
				while(fb_indexes[t][p] < max_x) {
					Y[fb_indexes[t][p] - min_x] -= lg;
					fb_indexes[t][p] += factor_base[p];
				}

				// p = 2 only has one modular root.
				if(factor_base[p] == 2)
					break;
			}
		}

		// Factor all values whose logarithms were reduced to approximately zero using trial division.
		{
			float threshold = log(factor_base.back()) / log(2);
			for(uint32_t i = 0; i < SIEVE_CHUNK; ++i) {
				if(fabs(Y[i]) < threshold) {
					mpz_class y = (sqrt_N + i + min_x) * (sqrt_N + i + min_x) - N;
					smooth.push_back(std::vector<uint32_t>());

					for(uint32_t p = 0; p < factor_base.size(); ++p) {
						while(mpz_divisible_ui_p(y.get_mpz_t(), factor_base[p])) {
							mpz_divexact_ui(y.get_mpz_t(), y.get_mpz_t(), factor_base[p]);
							smooth.back().push_back(p);
						}
					}

					if(y == 1) {
						// This V was indeed B-smooth.
						X.push_back(i + min_x);
						
						// Break out of trial division loop if we've found enou	gh smooth numbers.
						if(smooth.size() >= (factor_base.size() + 20))
							break;
					} else {
						// This V was apparently not B-smooth, remove it.
						smooth.pop_back();
						++fails;
					}
				}
			}
		}

		min_x += SIEVE_CHUNK;
		max_x += SIEVE_CHUNK;
	}

	uint64_t **matrix = new uint64_t*[factor_base.size()];

	// The amount of words needed to accomodate a row in the augmented matrix.
	int row_words = (smooth.size() + sizeof(uint64_t)) / sizeof(uint64_t);

	for(uint32_t i = 0; i < factor_base.size(); ++i) {
		matrix[i] = new uint64_t[row_words];
		memset(matrix[i], 0, row_words * sizeof(uint64_t));
	}

	for(uint32_t s = 0; s < smooth.size(); ++s) {
		// For each factor in the smooth number, add the factor to the corresponding element in the matrix.
		for(uint32_t p = 0; p < smooth[s].size(); ++p)
			toggle_bit(s, matrix[smooth[s][p]]);
	}

	// Gauss elimination. The dimension of the augmented matrix is factor_base.size() x (smooth.size() + 1).
	{
		uint32_t i = 0, j = 0;
		while(i < factor_base.size() && j < (smooth.size() + 1)) {
			uint32_t maxi = i;

			// Find pivot element.
			for(uint32_t k = i + 1; k < factor_base.size(); ++k) {
				if(get_bit(j, matrix[k]) == 1) {
					maxi = k;
					break;
				}
			}
			if(get_bit(j, matrix[maxi]) == 1) {
				std::swap(matrix[i], matrix[maxi]);
				
				for(uint32_t u = i + 1; u < factor_base.size(); ++u) {
					if(get_bit(j, matrix[u]) == 1) {
						for(int32_t w = 0; w < row_words; ++w)
							matrix[u][w] ^= matrix[i][w];
					}
				}
				++i;
			}
			++j;
		}
	}

	mpz_class a;
	mpz_class b;

	// A copy of matrix that we'll perform back-substitution on.
	uint64_t **back_matrix = new uint64_t*[factor_base.size()];
	for(uint32_t i = 0; i < factor_base.size(); ++i)
		back_matrix[i] = new uint64_t[row_words];

	uint32_t *x = new uint32_t[smooth.size()];

	uint32_t *combination = new uint32_t[factor_base.size()];

	// Loop until we've found a non-trivial factor.
	do {
		// Copy the gauss eliminated matrix.
		for(uint32_t i = 0; i < factor_base.size(); ++i)
			memcpy(back_matrix[i], matrix[i], row_words * sizeof(uint64_t));

		// Clear the x vector.
		memset(x, 0, smooth.size() * sizeof(uint32_t));

		// Perform back-substitution on our matrix that's now in row echelon form to get x.
		{
			int32_t i = factor_base.size() - 1;

			while(i >= 0) {
				// Count non-zero elements in current row.
				int32_t count = 0;
				int32_t current = -1;
				for(uint32_t c = 0; c < smooth.size(); ++c) {
					count += get_bit(c, back_matrix[i]);
					current = get_bit(c, back_matrix[i]) ? c : current;
				}

				// Empty row, advance to next.
				if(count == 0) {
					--i;
					continue;
				}

				// The system is underdetermined and we can choose x[current] freely.
				// To avoid the trivial solution we avoid always setting it to 0.
				uint32_t val = count > 1 ? rand() % 2 : get_bit(smooth.size(), back_matrix[i]);

				x[current] = val;

				for(int32_t u = 0; u <= i; ++u) {
					if(get_bit(current, back_matrix[u]) == 1) {
						if(val == 1)
							toggle_bit(smooth.size(), back_matrix[u]);
						unset_bit(current, back_matrix[u]);
					}
				}

				if(count == 1)
					--i;
			}
		}

		a = 1;
		b = 1;

		// The way to combine the factor base to get our square.
		memset(combination, 0, sizeof(uint32_t) * factor_base.size());
		for(uint32_t i = 0; i < smooth.size(); ++i) {
			if(x[i] == 1) {
				for(uint32_t p = 0; p < smooth[i].size(); ++p)
					++combination[smooth[i][p]];
				b *= (X[i] + sqrt_N);
			}
		}

		for(uint32_t p = 0; p < factor_base.size(); ++p) {
			for(uint32_t i = 0; i < (combination[p] / 2); ++i)
				a *= factor_base[p];
		}

		// If a = +/- b (mod N) we found a trivial factor, run the loop again to find a new a and b.
	} while(a % N == b % N || a % N == (- b) % N + N);

	b -= a;

	mpz_class factor;
	mpz_gcd(factor.get_mpz_t(), b.get_mpz_t(), N.get_mpz_t());

	for(uint32_t i = 0; i < factor_base.size(); ++i) {
		delete[] matrix[i];
		delete[] back_matrix[i];
	}

	delete[] combination;
	delete[] Y;
	delete[] fb_indexes[0];
	delete[] fb_indexes[1];
	delete[] fb_indexes;
	delete[] matrix;
	delete[] back_matrix;
	delete[] x;

	return factor;
}
Ejemplo n.º 9
0
/* sqrtmod_prime */
static int sqrtmod_prime(void *n, void *prime, void *ret)
{
   int res, legendre, i;
   mpz_t t1, C, Q, S, Z, M, T, R, two;

   LTC_ARGCHK(n     != NULL);
   LTC_ARGCHK(prime != NULL);
   LTC_ARGCHK(ret   != NULL);

   /* first handle the simple cases */
   if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) {
      mpz_set_ui(ret, 0);
      return CRYPT_OK;
   }
   if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0)     return CRYPT_ERROR; /* prime must be odd */
   legendre = mpz_legendre(n, prime);
   if (legendre == -1)                                  return CRYPT_ERROR; /* quadratic non-residue mod prime */

   mpz_init(t1); mpz_init(C); mpz_init(Q);
   mpz_init(S);  mpz_init(Z); mpz_init(M);
   mpz_init(T);  mpz_init(R); mpz_init(two);

   /* SPECIAL CASE: if prime mod 4 == 3
    * compute directly: res = n^(prime+1)/4 mod prime
    * Handbook of Applied Cryptography algorithm 3.36
    */
   i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */
   if (i == 3) {
      mpz_add_ui(t1, prime, 1);
      mpz_fdiv_q_2exp(t1, t1, 2);
      mpz_powm(ret, n, t1, prime);
      res = CRYPT_OK;
      goto cleanup;
   }

   /* NOW: Tonelli-Shanks algorithm */

   /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */
   mpz_set(Q, prime);
   mpz_sub_ui(Q, Q, 1);
   /* Q = prime - 1 */
   mpz_set_ui(S, 0);
   /* S = 0 */
   while (mpz_even_p(Q)) {
      mpz_fdiv_q_2exp(Q, Q, 1);
      /* Q = Q / 2 */
      mpz_add_ui(S, S, 1);
      /* S = S + 1 */
   }

   /* find a Z such that the Legendre symbol (Z|prime) == -1 */
   mpz_set_ui(Z, 2);
   /* Z = 2 */
   while(1) {
      legendre = mpz_legendre(Z, prime);
      if (legendre == -1) break;
      mpz_add_ui(Z, Z, 1);
      /* Z = Z + 1 */
   }

   mpz_powm(C, Z, Q, prime);
   /* C = Z ^ Q mod prime */
   mpz_add_ui(t1, Q, 1);
   mpz_fdiv_q_2exp(t1, t1, 1);
   /* t1 = (Q + 1) / 2 */
   mpz_powm(R, n, t1, prime);
   /* R = n ^ ((Q + 1) / 2) mod prime */
   mpz_powm(T, n, Q, prime);
   /* T = n ^ Q mod prime */
   mpz_set(M, S);
   /* M = S */
   mpz_set_ui(two, 2);

   while (1) {
      mpz_set(t1, T);
      i = 0;
      while (1) {
         if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break;
         mpz_powm(t1, t1, two, prime);
         i++;
      }
      if (i == 0) {
         mpz_set(ret, R);
         res = CRYPT_OK;
         goto cleanup;
      }
      mpz_sub_ui(t1, M, i);
      mpz_sub_ui(t1, t1, 1);
      mpz_powm(t1, two, t1, prime);
      /* t1 = 2 ^ (M - i - 1) */
      mpz_powm(t1, C, t1, prime);
      /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
      mpz_mul(C, t1, t1);
      mpz_mod(C, C, prime);
      /* C = (t1 * t1) mod prime */
      mpz_mul(R, R, t1);
      mpz_mod(R, R, prime);
      /* R = (R * t1) mod prime */
      mpz_mul(T, T, C);
      mpz_mod(T, T, prime);
      /* T = (T * C) mod prime */
      mpz_set_ui(M, i);
      /* M = i */
   }

cleanup:
   mpz_clear(t1); mpz_clear(C); mpz_clear(Q);
   mpz_clear(S);  mpz_clear(Z); mpz_clear(M);
   mpz_clear(T);  mpz_clear(R); mpz_clear(two);
   return res;
}
Ejemplo n.º 10
0
/*
 * Compute the Rabin signature and the useful value of f.
 */
int rs_sign_rabin(mpz_t res,	        /* mpz to store signature */
		  int* f,	        /* f value chosen */
		  const mpz_t hash,	/* MD5 hash of app */
		  int rootnum,		/* root number (0, 1, 2, 3) */
		  RSKey* key)		/* key structure */
{
  mpz_t mm;
  int mLp, mLq;
  int pm8, qm8;

  if (!mpz_sgn(key->n)) {
    rs_error(key, NULL, "unable to sign: public key missing");
    return RS_ERR_MISSING_PUBLIC_KEY;
  }

  if (!mpz_sgn(key->p) || !mpz_sgn(key->q)) {
    rs_error(key, NULL, "unable to sign: private key missing");
    return RS_ERR_MISSING_PRIVATE_KEY;
  }

  mpz_init(mm);

  /* Calculate q^-1 if necessary */

  if (!mpz_sgn(key->qinv)) {
#ifndef USE_MPZ_GCDEXT
    mpz_sub_ui(mm, key->p, 2);
    mpz_powm(key->qinv, key->q, mm, key->p);
#else
    mpz_gcdext(mm, key->qinv, NULL, key->q, key->p);
    if (mpz_cmp_ui(mm, 1)) {
      mpz_clear(mm);
      rs_error(key, NULL, "unable to sign: unsuitable key");
      return RS_ERR_UNSUITABLE_RABIN_KEY;
    }
#endif
  }

  applyf(mm, hash, key->n, 2);

  mLp = mpz_legendre(mm, key->p);
  mLq = mpz_legendre(mm, key->q);

  pm8 = mpz_get_ui(key->p) % 8;
  qm8 = mpz_get_ui(key->q) % 8;

  if (pm8 == 1 || qm8 == 1 || (pm8 % 2) == 0 || (qm8 % 2) == 0) {
    mpz_clear(mm);
    rs_error(key, NULL, "unable to sign: unsuitable key");
    return RS_ERR_UNSUITABLE_RABIN_KEY;
  }

  *f = ftab[(mLp == 1 ? 0 : 1) +
	    (mLq == 1 ? 0 : 2) +
	    (((qm8 - 3) / 2) * 4) +
	    (((pm8 - 3) / 2) * 12)];

  if (*f == 99) {
    mpz_clear(mm);
    rs_error(key, NULL, "unable to sign: unsuitable key");
    return RS_ERR_UNSUITABLE_RABIN_KEY;
  }

  rabsigf(res, hash, key->n, key->p, key->q, key->qinv, *f, rootnum);
  mpz_clear(mm);
  return RS_SUCCESS;
}
Ejemplo n.º 11
0
/* See Cohen section 1.5.
 * See http://www.math.vt.edu/people/brown/doc/sqrts.pdf
 */
int sqrtmod(mpz_t x, mpz_t a, mpz_t p,
            mpz_t t, mpz_t q, mpz_t b, mpz_t z) /* 4 temp variables */
{
    int r, e, m;

    /* Easy cases from page 31 (or Menezes 3.36, 3.37) */
    if (mpz_congruent_ui_p(p, 3, 4)) {
        mpz_add_ui(t, p, 1);
        mpz_tdiv_q_2exp(t, t, 2);
        mpz_powm(x, a, t, p);
        return verify_sqrt(x, a, p, t, q);
    }

    if (mpz_congruent_ui_p(p, 5, 8)) {
        mpz_sub_ui(t, p, 1);
        mpz_tdiv_q_2exp(t, t, 2);
        mpz_powm(q, a, t, p);
        if (mpz_cmp_si(q, 1) == 0) { /* s = a^((p+3)/8) mod p */
            mpz_add_ui(t, p, 3);
            mpz_tdiv_q_2exp(t, t, 3);
            mpz_powm(x, a, t, p);
        } else {                      /* s = 2a * (4a)^((p-5)/8) mod p */
            mpz_sub_ui(t, p, 5);
            mpz_tdiv_q_2exp(t, t, 3);
            mpz_mul_ui(q, a, 4);
            mpz_powm(x, q, t, p);
            mpz_mul_ui(x, x, 2);
            mpz_mulmod(x, x, a, p, x);
        }
        return verify_sqrt(x, a, p, t, q);
    }

    if (mpz_kronecker(a, p) != 1) {
        /* Possible no solution exists.  Check Euler criterion. */
        mpz_sub_ui(t, p, 1);
        mpz_tdiv_q_2exp(t, t, 1);
        mpz_powm(x, a, t, p);
        if (mpz_cmp_si(x, 1) != 0) {
            mpz_set_ui(x, 0);
            return 0;
        }
    }

    mpz_sub_ui(q, p, 1);
    e = mpz_scan1(q, 0);              /* Remove 2^e from q */
    mpz_tdiv_q_2exp(q, q, e);
    mpz_set_ui(t, 2);
    while (mpz_legendre(t, p) != -1)  /* choose t "at random" */
        mpz_add_ui(t, t, 1);
    mpz_powm(z, t, q, p);                     /* Step 1 complete */
    r = e;

    mpz_powm(b, a, q, p);
    mpz_add_ui(q, q, 1);
    mpz_divexact_ui(q, q, 2);
    mpz_powm(x, a, q, p);   /* Done with q, will use it for y now */

    while (mpz_cmp_ui(b, 1)) {
        /* calculate how many times b^2 mod p == 1 */
        mpz_set(t, b);
        m = 0;
        do {
            mpz_powm_ui(t, t, 2, p);
            m++;
        } while (m < r && mpz_cmp_ui(t, 1));
        if (m >= r) break;
        mpz_ui_pow_ui(t, 2, r-m-1);
        mpz_powm(t, z, t, p);
        mpz_mulmod(x, x, t, p, x);
        mpz_powm_ui(z, t, 2, p);
        mpz_mulmod(b, b, z, p, b);
        r = m;
    }
    return verify_sqrt(x, a, p, t, q);
}
Ejemplo n.º 12
0
int quadratic_residue(mpz_t x,mpz_t q,mpz_t n)
{
    int                        leg;
    mpz_t                        tmp,ofac,nr,t,r,c,b;
    unsigned int            mod4;
    mp_bitcnt_t                twofac=0,m,i,ix;

    mod4=mpz_tstbit(n,0);
    if(!mod4) // must be odd
        return 0;

    mod4+=2*mpz_tstbit(n,1);

    leg=mpz_legendre(q,n);
    if(leg!=1)
        return leg;

    mpz_init_set(tmp,n);
	
    if(mod4==3) // directly, x = q^(n+1)/4 mod n
        {
	printf("diretamente\n\n");
        mpz_add_ui(tmp,tmp,1UL);
        mpz_tdiv_q_2exp(tmp,tmp,2);
        mpz_powm(x,q,tmp,n);
	gmp_printf("NUMERO X %Zd \n\n",x);
        mpz_clear(tmp);
        }
    else // Tonelli-Shanks
        {
	printf("Tonelli shanks!!!\n");
        mpz_inits(ofac,t,r,c,b,NULL);

        // split n - 1 into odd number times power of 2 ofac*2^twofac
        mpz_sub_ui(tmp,tmp,1UL);
        twofac=mpz_scan1(tmp,twofac); // largest power of 2 divisor
        if(twofac)
            mpz_tdiv_q_2exp(ofac,tmp,twofac); // shift right

        // look for non-residue
        mpz_init_set_ui(nr,2UL);
        while(mpz_legendre(nr,n)!=-1)
            mpz_add_ui(nr,nr,1UL);

        mpz_powm(c,nr,ofac,n); // c = nr^ofac mod n

        mpz_add_ui(tmp,ofac,1UL);
        mpz_tdiv_q_2exp(tmp,tmp,1);
        mpz_powm(r,q,tmp,n); // r = q^(ofac+1)/2 mod n

        mpz_powm(t,q,ofac,n);
        mpz_mod(t,t,n); // t = q^ofac mod n

        if(mpz_cmp_ui(t,1UL)!=0) // if t = 1 mod n we're done
            {
            m=twofac;
            do
                {
                i=2;
                ix=1;
                while(ix<m)
                    {
                    // find lowest 0 < ix < m | t^2^ix = 1 mod n
                    mpz_powm_ui(tmp,t,i,n); // repeatedly square t
                    if(mpz_cmp_ui(tmp,1UL)==0)
                        break;
                    i<<=1; // i = 2, 4, 8, ...
                    ix++; // ix is log2 i
                    }
                mpz_powm_ui(b,c,1<<(m-ix-1),n); // b = c^2^(m-ix-1) mod n
                mpz_mul(r,r,b);
                mpz_mod(r,r,n); // r = r*b mod n
                mpz_mul(c,b,b);
                mpz_mod(c,c,n); // c = b^2 mod n
                mpz_mul(t,t,c);
                mpz_mod(t,t,n); // t = t b^2 mod n
                m=ix;
                }while(mpz_cmp_ui(t,1UL)!=0); // while t mod n != 1
            }
        mpz_set(x,r);
        mpz_clears(tmp,ofac,nr,t,r,c,b,NULL);
        }

    return 1;
}