/*-------------------------------------------------------------------------*/
void
sieve_xy_run_deg5(root_sieve_t *rs, uint64 lattice_size,
		double line_min, double line_max)
{
	uint32 i, j;
	sieve_xy_t *xy = &rs->xydata;
	hit_t hitlist[MAX_CRT_FACTORS];
	uint32 num_lattice_primes;
	uint32 num_lattices;
	uint32 y_blocks;
	int64 curr_y;
	double direction[3] = {0, 1, 0};

	xy->lattice_size = lattice_size;
	xy->dbl_lattice_size = (double)lattice_size;
	uint64_2gmp(lattice_size, xy->mp_lattice_size);

	mpz_set_d(xy->y_base, line_min / lattice_size - 1);
	mpz_mul(xy->y_base, xy->y_base, xy->mp_lattice_size);

	y_blocks = (line_max - line_min) / lattice_size + 1;
	if (y_blocks > xy->y_blocks) {
		xy->x_line_min = (double *)xrealloc(xy->x_line_min,
						y_blocks * sizeof(double));
		xy->x_line_max = (double *)xrealloc(xy->x_line_max,
						y_blocks * sizeof(double));
	}
	xy->y_blocks = y_blocks;

	xy->num_lattices = 0;
	if (lattice_size == 1) {
		num_lattice_primes = xy->num_lattice_primes = 0;
		num_lattices = 1;
		if (num_lattices > xy->num_lattices) {
			xy->lattices = (lattice_t *)xrealloc(xy->lattices,
					num_lattices * sizeof(lattice_t));
		}
		memset(xy->lattices, 0, sizeof(lattice_t));
	}
	else {
		num_lattice_primes = xy->num_lattice_primes = 
				find_lattice_primes(rs->primes, 
						rs->num_primes, lattice_size, 
						xy->lattice_primes);

		find_hits(xy->lattice_primes, num_lattice_primes, hitlist);

		for (i = 0, num_lattices = 1; i < num_lattice_primes; i++) {
			num_lattices *= hitlist[i].num_roots;
		}

		if (num_lattices > xy->num_lattices) {
			xy->lattices = (lattice_t *)xrealloc(xy->lattices,
					num_lattices * sizeof(lattice_t));
		}

		compute_lattices(hitlist, num_lattice_primes, xy->lattices,
				lattice_size, num_lattices, 2);

	}
	xy->num_lattices = num_lattices;

	line_min = -10000;
	line_max = 10000;
	direction[0] = 1;
	direction[1] = 0;
	direction[2] = 0;
	curr_y = gmp2int64(xy->y_base);
	for (i = 0; i < y_blocks; i++) {
		dpoly_t apoly = rs->apoly;

		apoly.coeff[2] += rs->dbl_p * curr_y;
		apoly.coeff[1] -= rs->dbl_d * curr_y;

		compute_line_size(rs->max_norm, &apoly,
			rs->dbl_p, rs->dbl_d, direction,
			line_min, line_max, &line_min, &line_max);

		if (line_min >= line_max) {
			xy->x_line_min[i] = 0;
			xy->x_line_max[i] = 0;
			line_min = -10000;
			line_max = 10000;
		}
		else {
			xy->x_line_min[i] = line_min;
			xy->x_line_max[i] = line_max;
		}

		curr_y += lattice_size;
	}

	for (i = y_blocks; i; i--) {
		if (xy->x_line_min[i-1] != xy->x_line_max[i-1])
			break;
	}
	y_blocks = i;
	for (i = 0; i < y_blocks; i++) {
		if (xy->x_line_min[i] != xy->x_line_max[i])
			break;
	}
	mpz_addmul_ui(xy->y_base, xy->mp_lattice_size, i);
	y_blocks -= i;
	if (i > 0) {
		for (j = 0; j < y_blocks; j++) {
			xy->x_line_min[j] = xy->x_line_min[j+i];
			xy->x_line_max[j] = xy->x_line_max[j+i];
		}
	}
	xy->y_blocks = y_blocks;

#if 0
	printf("\n%.0lf %u %u\n", (double)lattice_size, 
			y_blocks, num_lattices);
#endif

	sieve_x_run_deg5(rs);
}
Ejemplo n.º 2
0
Archivo: ecpp.c Proyecto: xcvii/gkecpp
int ecpp_test(unsigned long n)
{
  mpz_t a, b,
        x0, y0,
        xt, yt,
        tmp;
  int z;
  int is_prime = 0;

  if (n <= USHRT_MAX)
  {
    return sieve_test(n);
  }

  mpz_init(a);
  mpz_init(b);
  mpz_init(x0);
  mpz_init(y0);
  mpz_init(xt);
  mpz_init(yt);
  mpz_init(tmp);

#ifdef DEBUG
  gmp_fprintf(stderr, "\nTesting %d with ECPP...\n", n);
#endif /* DEBUG */

  for (;;) /* keep trying while the curve order factoring fails */
  {
    for (;;) /* keep trying while n divides curve discriminant */
    {
      /* initialise a random point P = (x0, y0)
       * and a random elliptic curve E(a, b): y^2 = x^3 + a*x + b
       * with b expressed in terms of (a, x0, y0) so the point lies on the curve
       */

      mpz_set_ui(a, rand() % n);
      mpz_set_ui(x0, rand() % n);
      mpz_set_ui(y0, rand() % n);
      mpz_init(b);

      mpz_mul(b, y0, y0);
      mpz_mul(tmp, x0, x0);
      mpz_submul(b, tmp, x0);
      mpz_submul(b, a, x0);
      mpz_mod_ui(b, b, n);

#ifdef DEBUG
      gmp_fprintf(stderr, "\n\tn = %d\n", n);
      gmp_fprintf(stderr, "\tE: y^2 = x^3 + %Zd * x + %Zd\n", a, b);
      gmp_fprintf(stderr, "\tP = (%Zd,%Zd,1)\n", x0, y0);
#endif /* DEBUG */

      /* the discriminant of the curve and n are required to be coprimes
       * -- if not, then either
       *   A) n divides the discriminant -- a new curve must be generated
       *   B) n is composite and a proper factor is found -- the algorithm can
       *      terminate
       */

      ec_discriminant(tmp, a, b);

#ifdef DEBUG
      mpz_mod_ui(tmp, tmp, n);
      gmp_fprintf(stderr, "\tdelta(E/GF(n)) = %Zd\n", tmp);
#endif /* DEBUG */

      mpz_gcd_ui(tmp, tmp, n);

#ifdef DEBUG
      gmp_fprintf(stderr, "\tgcd(delta, n) = %Zd\n", tmp);
#endif /* DEBUG */

      if (0 == mpz_cmp_ui(tmp, 1))
      {
        break;
      }
      else if (0 != mpz_cmp_ui(tmp, n))
      {
#ifdef DEBUG
        gmp_fprintf(stderr, "\tfound a proper factor, %d is composite\n", n);
#endif /* DEBUG */
        is_prime = 0;
        goto cleanup_and_return;
      }
    }

    /* P + P != 0, or a new curve is generated
     */
    z = ec_add(xt, yt, x0, y0, 1, x0, y0, 1, n, a);

#ifdef DEBUG
    gmp_fprintf(stderr, "\t2 * P = (%Zd,%Zd,%d)\n", xt, yt, z);
#endif /* DEBUG */

    if (0 == z)
    {
      continue;
    }

    /* the curve order algorithm failing indicates n is composite
     */
    if (!(ec_order(tmp, a, b, n)))
    {
#ifdef DEBUG
      gmp_fprintf(stderr,
          "\tcurve order algorithm failed, %d must be composite\n", n);
#endif /* DEBUG */

      is_prime = 0;
      break;
    }

#ifdef DEBUG
    gmp_fprintf(stderr, "\t|E/GF(n)| = %Zd\n", tmp);
#endif /* DEBUG */

    /* the curve order should be the multiple of 2 and a "probable prime" n --
     * if the order is not even, a new curve is generated
     */
    if (!mpz_even_p(tmp))
    {
#ifdef DEBUG
      gmp_fprintf(stderr, "\t|E/GF(n)| is odd, generating new curve...\n");
#endif /* DEBUG */
      continue;
    }

    /* order * P = 0, or n is composite
     */
    z = ec_times(xt, yt, x0, y0, 1, tmp, n, a);

#ifdef DEBUG
    gmp_fprintf(stderr, "\t|E| * P = (%Zd,%Zd,%d)\n", xt, yt, z);
#endif /* DEBUG */

    if (0 != z)
    {
#ifdef DEBUG
      gmp_fprintf(stderr, "\t|E| * P is non-zero, %d is composite\n", n);
#endif /* DEBUG */
      is_prime = 0;
      break;
    }

    /* at this point, order/2 being a prime implies n is a prime --
     * a recursive call to ecpp_test is used to test order/2 for primality
     */
    mpz_div_ui(tmp, tmp, 2);
    if (ecpp_test(mpz_get_ui(tmp)))
    {
      is_prime = 1;
      break;
    }
  }

cleanup_and_return:
  mpz_clear(a);
  mpz_clear(b);
  mpz_clear(x0);
  mpz_clear(y0);
  mpz_clear(xt);
  mpz_clear(yt);
  mpz_clear(tmp);

  return is_prime;
}
Ejemplo n.º 3
0
static PyObject *
GMPy_MPZ_is_aprcl_prime(PyObject *self, PyObject *other)
{
  mpz_t N;
  s64_t T, U;
  int i, j, H, I, J, K, P, Q, W, X;
  int IV, InvX, LEVELnow, NP, PK, PL, PM, SW, VK, TestedQs, TestingQs;
  int QQ, T1, T3, U1, U3, V1, V3;
  int break_this = 0;
  MPZ_Object *tempx;

  if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
    TYPE_ERROR("is_aprcl_prime() requires 'mpz' argument");
    return NULL;
  }

  mpz_init(N);
  mpz_set(N, tempx->z);
  Py_DECREF(tempx);

  /* make sure the input is >= 2 and odd */
  if (mpz_cmp_ui(N, 2) < 0)
    Py_RETURN_FALSE;

  if (mpz_divisible_ui_p(N, 2)) {
    if (mpz_cmp_ui(N, 2) == 0)
      Py_RETURN_TRUE;
    else
      Py_RETURN_FALSE;
  }

  /* only three small exceptions for this implementation */
  /* with this set of P and Q primes */
  if (mpz_cmp_ui(N, 3) == 0)
    Py_RETURN_TRUE;
  if (mpz_cmp_ui(N, 7) == 0)
    Py_RETURN_TRUE;
  if (mpz_cmp_ui(N, 11) == 0)
    Py_RETURN_TRUE;

  /* If the input number is larger than 7000 decimal digits
     we will just return whether it is a BPSW (probable) prime */
  NumberLength = mpz_sizeinbase(N, 10);
  if (NumberLength > 7000) {
      VALUE_ERROR("value too large to test");
      return NULL;
  }

  allocate_vars();

  mpz_set(TestNbr, N);
  mpz_set_si(biS, 0);

  j = PK = PL = PM = 0;
  for (J = 0; J < PWmax; J++) {
    /* aiJX[J] = 0; */
    mpz_set_ui(aiJX[J], 0);
  }
  break_this = 0;
/* GetPrimes2Test : */
  for (i = 0; i < LEVELmax; i++) {
    /* biS[0] = 2; */
    mpz_set_ui(biS, 2);

    for (j = 0; j < aiNQ[i]; j++) {
      Q = aiQ[j];
      if (aiT[i]%(Q-1) != 0)
        continue;
      U = aiT[i] * Q;
      do {
        U /= Q;
        /* MultBigNbrByLong(biS, Q, biS, NumberLength); */
        mpz_mul_ui(biS, biS, Q);
      } while (U % Q == 0);

      // Exit loop if S^2 > N.
      if (CompareSquare(biS, TestNbr) > 0) {
        /* break GetPrimes2Test; */
        break_this = 1;
        break;
      }
    } /* End for j */

    if (break_this) break;
  } /* End for i */

  if (i == LEVELmax)
  { /* too big */
    free_vars();
    VALUE_ERROR("value too large to test");
    return NULL;
  }
  LEVELnow = i;
  TestingQs = j;
  T = aiT[LEVELnow];
  NP = aiNP[LEVELnow];

MainStart:
  for (;;)
  {
    for (i = 0; i < NP; i++)
    {
      P = aiP[i];
      if (T%P != 0) continue;

      SW = TestedQs = 0;
      /* Q = W = (int) BigNbrModLong(TestNbr, P * P); */
      Q = W = mpz_fdiv_ui(TestNbr, P * P);
      for (J = P - 2; J > 0; J--)
      {
        W = (W * Q) % (P * P);
      }
      if (P > 2 && W != 1)
      {
        SW = 1;
      }
      for (;;)
      {
        for (j = TestedQs; j <= TestingQs; j++)
        {
          Q = aiQ[j] - 1;
          /* G = aiG[j]; */
          K = 0;
          while (Q % P == 0)
          {
            K++;
            Q /= P;
          }
          Q = aiQ[j];
          if (K == 0)
          {
            continue;
          }

          PM = 1;
          for (I = 1; I < K; I++)
          {
            PM = PM * P;
          }
          PL = (P - 1) * PM;
          PK = P * PM;
          for (I = 0; I < PK; I++)
          {
            /* aiJ0[I] = aiJ1[I] = 0; */
            mpz_set_ui(aiJ0[I], 0);
            mpz_set_ui(aiJ1[I], 0);
          }
          if (P > 2)
          {
            JacobiSum(0, P, PL, Q);
          }
          else
          {
            if (K != 1)
            {
              JacobiSum(0, P, PL, Q);
              for (I = 0; I < PK; I++)
              {
                /* aiJW[I] = 0; */
                mpz_set_ui(aiJW[I], 0);
              }
              if (K != 2)
              {
                for (I = 0; I < PM; I++)
                {
                  /* aiJW[I] = aiJ0[I]; */
                  mpz_set(aiJW[I], aiJ0[I]);
                }
                JacobiSum(1, P, PL, Q);
                for (I = 0; I < PM; I++)
                {
                  /* aiJS[I] = aiJ0[I]; */
                  mpz_set(aiJS[I], aiJ0[I]);
                }
                JS_JW(PK, PL, PM, P);
                for (I = 0; I < PM; I++)
                {
                  /* aiJ1[I] = aiJS[I]; */
                  mpz_set(aiJ1[I], aiJS[I]);
                }
                JacobiSum(2, P, PL, Q);
                for (I = 0; I < PK; I++)
                {
                  /* aiJW[I] = 0; */
                  mpz_set_ui(aiJW[I], 0);
                }
                for (I = 0; I < PM; I++)
                {
                  /* aiJS[I] = aiJ0[I]; */
                  mpz_set(aiJS[I], aiJ0[I]);
                }
                JS_2(PK, PL, PM, P);
                for (I = 0; I < PM; I++)
                {
                  /* aiJ2[I] = aiJS[I]; */
                  mpz_set(aiJ2[I], aiJS[I]);
                }
              }
            }
          }
          /* aiJ00[0] = aiJ01[0] = 1; */
          mpz_set_ui(aiJ00[0], 1);
          mpz_set_ui(aiJ01[0], 1);
          for (I = 1; I < PK; I++)
          {
            /* aiJ00[I] = aiJ01[I] = 0; */
            mpz_set_ui(aiJ00[I], 0);
            mpz_set_ui(aiJ01[I], 0);
          }
          /* VK = (int) BigNbrModLong(TestNbr, PK); */
          VK = mpz_fdiv_ui(TestNbr, PK);
          for (I = 1; I < PK; I++)
          {
            if (I % P != 0)
            {
              U1 = 1;
              U3 = I;
              V1 = 0;
              V3 = PK;
              while (V3 != 0)
              {
                QQ = U3 / V3;
                T1 = U1 - V1 * QQ;
                T3 = U3 - V3 * QQ;
                U1 = V1;
                U3 = V3;
                V1 = T1;
                V3 = T3;
              }
              aiInv[I] = (U1 + PK) % PK;
            }
            else
            {
              aiInv[I] = 0;
            }
          }
          if (P != 2)
          {
            for (IV = 0; IV <= 1; IV++)
            {
              for (X = 1; X < PK; X++)
              {
                for (I = 0; I < PK; I++)
                {
                  /* aiJS[I] = aiJ0[I]; */
                  mpz_set(aiJS[I], aiJ0[I]);
                }
                if (X % P == 0)
                {
                  continue;
                }
                if (IV == 0)
                {
                  /* LongToBigNbr(X, biExp, NumberLength); */
                  mpz_set_ui(biExp, X);
                }
                else
                {
                  /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */
                  mpz_set_ui(biExp, (VK * X) / PK);
                  if ((VK * X) / PK == 0)
                  {
                    continue;
                  }
                }
                JS_E(PK, PL, PM, P);
                for (I = 0; I < PK; I++)
                {
                  /* aiJW[I] = 0; */
                  mpz_set_ui(aiJW[I], 0);
                }
                InvX = aiInv[X];
                for (I = 0; I < PK; I++)
                {
                  J = (I * InvX) % PK;
                  /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */
                  mpz_add(aiJW[J], aiJW[J], aiJS[I]);
                }
                NormalizeJW(PK, PL, PM, P);
                if (IV == 0)
                {
                  for (I = 0; I < PK; I++)
                  {
                    /* aiJS[I] = aiJ00[I]; */
                    mpz_set(aiJS[I], aiJ00[I]);
                  }
                }
                else
                {
                  for (I = 0; I < PK; I++)
                  {
                    /* aiJS[I] = aiJ01[I]; */
                    mpz_set(aiJS[I], aiJ01[I]);
                  }
                }
                JS_JW(PK, PL, PM, P);
                if (IV == 0)
                {
                  for (I = 0; I < PK; I++)
                  {
                    /* aiJ00[I] = aiJS[I]; */
                    mpz_set(aiJ00[I], aiJS[I]);
                  }
                }
                else
                {
                  for (I = 0; I < PK; I++)
                  {
                    /* aiJ01[I] = aiJS[I]; */
                    mpz_set(aiJ01[I], aiJS[I]);
                  }
                }
              } /* end for X */
            } /* end for IV */
          }
          else
          {
            if (K == 1)
            {
              /* MultBigNbrByLongModN(1, Q, aiJ00[0], TestNbr, NumberLength); */
              mpz_set_ui(aiJ00[0], Q);
              /* aiJ01[0] = 1; */
              mpz_set_ui(aiJ01[0], 1);
            }
            else
            {
              if (K == 2)
              {
                if (VK == 1)
                {
                  /* aiJ01[0] = 1; */
                  mpz_set_ui(aiJ01[0], 1);
                }
                /* aiJS[0] = aiJ0[0]; */
                /* aiJS[1] = aiJ0[1]; */
                mpz_set(aiJS[0], aiJ0[0]);
                mpz_set(aiJS[1], aiJ0[1]);
                JS_2(PK, PL, PM, P);
                if (VK == 3)
                {
                  /* aiJ01[0] = aiJS[0]; */
                  /* aiJ01[1] = aiJS[1]; */
                  mpz_set(aiJ01[0], aiJS[0]);
                  mpz_set(aiJ01[1], aiJS[1]);
                }
                /* MultBigNbrByLongModN(aiJS[0], Q, aiJ00[0], TestNbr, NumberLength); */
                mpz_mul_ui(aiJ00[0], aiJS[0], Q);
                /* MultBigNbrByLongModN(aiJS[1], Q, aiJ00[1], TestNbr, NumberLength); */
                mpz_mul_ui(aiJ00[1], aiJS[1], Q);
              }
              else
              {
                for (IV = 0; IV <= 1; IV++)
                {
                  for (X = 1; X < PK; X += 2)
                  {
                    for (I = 0; I <= PM; I++)
                    {
                      /* aiJS[I] = aiJ1[I]; */
                      mpz_set(aiJS[I], aiJ1[I]);
                    }
                    if (X % 8 == 5 || X % 8 == 7)
                    {
                      continue;
                    }
                    if (IV == 0)
                    {
                      /* LongToBigNbr(X, biExp, NumberLength); */
                      mpz_set_ui(biExp, X);
                    }
                    else
                    {
                      /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */
                      mpz_set_ui(biExp, VK * X / PK);
                      if (VK * X / PK == 0)
                      {
                        continue;
                      }
                    }
                    JS_E(PK, PL, PM, P);
                    for (I = 0; I < PK; I++)
                    {
                      /* aiJW[I] = 0; */
                      mpz_set_ui(aiJW[I], 0);
                    }
                    InvX = aiInv[X];
                    for (I = 0; I < PK; I++)
                    {
                      J = I * InvX % PK;
                      /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */
                      mpz_add(aiJW[J], aiJW[J], aiJS[I]);
                    }
                    NormalizeJW(PK, PL, PM, P);
                    if (IV == 0)
                    {
                      for (I = 0; I < PK; I++)
                      {
                        /* aiJS[I] = aiJ00[I]; */
                        mpz_set(aiJS[I], aiJ00[I]);
                      }
                    }
                    else
                    {
                      for (I = 0; I < PK; I++)
                      {
                        /* aiJS[I] = aiJ01[I]; */
                        mpz_set(aiJS[I], aiJ01[I]);
                      }
                    }
                    NormalizeJS(PK, PL, PM, P);
                    JS_JW(PK, PL, PM, P);
                    if (IV == 0)
                    {
                      for (I = 0; I < PK; I++)
                      {
                        /* aiJ00[I] = aiJS[I]; */
                        mpz_set(aiJ00[I], aiJS[I]);
                      }
                    }
                    else
                    {
                      for (I = 0; I < PK; I++)
                      {
                        /* aiJ01[I] = aiJS[I]; */
                        mpz_set(aiJ01[I], aiJS[I]);
                      }
                    }
                  } /* end for X */
                  if (IV == 0 || VK % 8 == 1 || VK % 8 == 3)
                  {
                    continue;
                  }
                  for (I = 0; I < PM; I++)
                  {
                    /* aiJW[I] = aiJ2[I]; */
                    /* aiJS[I] = aiJ01[I]; */
                    mpz_set(aiJW[I], aiJ2[I]);
                    mpz_set(aiJS[I], aiJ01[I]);
                  }
                  for (; I < PK; I++)
                  {
                    /* aiJW[I] = aiJS[I] = 0; */
                    mpz_set_ui(aiJW[I], 0);
                    mpz_set_ui(aiJS[I], 0);
                  }
                  JS_JW(PK, PL, PM, P);
                  for (I = 0; I < PM; I++)
                  {
                    /* aiJ01[I] = aiJS[I]; */
                    mpz_set(aiJ01[I], aiJS[I]);
                  }
                } /* end for IV */
              }
            }
          }
          for (I = 0; I < PL; I++)
          {
            /* aiJS[I] = aiJ00[I]; */
            mpz_set(aiJS[I], aiJ00[I]);
          }
          for (; I < PK; I++)
          {
            /* aiJS[I] = 0; */
            mpz_set_ui(aiJS[I], 0);
          }
          /* DivBigNbrByLong(TestNbr, PK, biExp, NumberLength); */
          mpz_fdiv_q_ui(biExp, TestNbr, PK);
          JS_E(PK, PL, PM, P);
          for (I = 0; I < PK; I++)
          {
            /* aiJW[I] = 0; */
            mpz_set_ui(aiJW[I], 0);
          }
          for (I = 0; I < PL; I++)
          {
            for (J = 0; J < PL; J++)
            {
              /* MontgomeryMult(aiJS[I], aiJ01[J], biTmp); */
              /* AddBigNbrModN(biTmp, aiJW[(I + J) % PK], aiJW[(I + J) % PK], TestNbr, NumberLength); */
              mpz_mul(biTmp, aiJS[I], aiJ01[J]);
              mpz_add(aiJW[(I + J) % PK], biTmp, aiJW[(I + J) % PK]);
            }
          }
          NormalizeJW(PK, PL, PM, P);
/* MatchingRoot : */
          do
          {
            H = -1;
            W = 0;
            for (I = 0; I < PL; I++)
            {
              if (mpz_cmp_ui(aiJW[I], 0) != 0)/* (!BigNbrIsZero(aiJW[I])) */
              {
                /* if (H == -1 && BigNbrAreEqual(aiJW[I], 1)) */
                if (H == -1 && (mpz_cmp_ui(aiJW[I], 1) == 0))
                {
                  H = I;
                }
                else
                {
                  H = -2;
                  /* AddBigNbrModN(aiJW[I], MontgomeryMultR1, biTmp, TestNbr, NumberLength); */
                  mpz_add_ui(biTmp, aiJW[I], 1);
                  mpz_mod(biTmp, biTmp, TestNbr);
                  if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */
                  {
                    W++;
                  }
                }
              }
            }
            if (H >= 0)
            {
              /* break MatchingRoot; */
              break;
            }
            if (W != P - 1)
            {
              /* Not prime */
              free_vars();
              Py_RETURN_FALSE;
            }
            for (I = 0; I < PM; I++)
            {
              /* AddBigNbrModN(aiJW[I], 1, biTmp, TestNbr, NumberLength); */
              mpz_add_ui(biTmp, aiJW[I], 1);
              mpz_mod(biTmp, biTmp, TestNbr);
              if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */
              {
                break;
              }
            }
            if (I == PM)
            {
              /* Not prime */
              free_vars();
              Py_RETURN_FALSE;
            }
            for (J = 1; J <= P - 2; J++)
            {
              /* AddBigNbrModN(aiJW[I + J * PM], 1, biTmp, TestNbr, NumberLength); */
              mpz_add_ui(biTmp, aiJW[I + J * PM], 1);
              mpz_mod(biTmp, biTmp, TestNbr);
              if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */
              {
                /* Not prime */
                free_vars();
                Py_RETURN_FALSE;
              }
            }
            H = I + PL;
          }
          while (0);

          if (SW == 1 || H % P == 0)
          {
            continue;
          }
          if (P != 2)
          {
            SW = 1;
            continue;
          }
          if (K == 1)
          {
            if ((mpz_get_ui(TestNbr) & 3) == 1)
            {
              SW = 1;
            }
            continue;
          }

          // if (Q^((N-1)/2) mod N != N-1), N is not prime.

          /* MultBigNbrByLongModN(1, Q, biTmp, TestNbr, NumberLength); */
          mpz_set_ui(biTmp, Q);
          mpz_mod(biTmp, biTmp, TestNbr);

          mpz_sub_ui(biT, TestNbr, 1); /* biT = n-1 */
          mpz_divexact_ui(biT, biT, 2); /* biT = (n-1)/2 */
          mpz_powm(biR, biTmp, biT, TestNbr); /* biR = Q^((n-1)/2) mod n */
          mpz_add_ui(biTmp, biR, 1);
          mpz_mod(biTmp, biTmp, TestNbr);

          if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */
          {
            /* Not prime */
            free_vars();
            Py_RETURN_FALSE;
          }
          SW = 1;
        } /* end for j */
        if (SW == 0)
        {
          TestedQs = TestingQs + 1;
          if (TestingQs < aiNQ[LEVELnow] - 1)
          {
            TestingQs++;
            Q = aiQ[TestingQs];
            U = T * Q;
            do
            {
              /* MultBigNbrByLong(biS, Q, biS, NumberLength); */
              mpz_mul_ui(biS, biS, Q);
              U /= Q;
            }
            while (U % Q == 0);

            continue; /* Retry */
          }
          LEVELnow++;
          if (LEVELnow == LEVELmax)
          {
            free_vars();
            // return mpz_bpsw_prp(N); /* Cannot tell */
            VALUE_ERROR("maximum levels reached");
            return NULL;
          }
          T = aiT[LEVELnow];
          NP = aiNP[LEVELnow];
          /* biS = 2; */
          mpz_set_ui(biS, 2);
          for (J = 0; J <= aiNQ[LEVELnow]; J++)
          {
            Q = aiQ[J];
            if (T%(Q-1) != 0) continue;
            U = T * Q;
            do
            {
              /* MultBigNbrByLong(biS, Q, biS, NumberLength); */
              mpz_mul_ui(biS, biS, Q);
              U /= Q;
            }
            while (U % Q == 0);
            if (CompareSquare(biS, TestNbr) > 0)
            {
              TestingQs = J;
              /* continue MainStart; */ /* Retry from the beginning */
              goto MainStart;
            }
          } /* end for J */
          free_vars();
          VALUE_ERROR("internal failure");
          return NULL;
        } /* end if */
        break;
      } /* end for (;;) */
    } /* end for i */

    // Final Test

    /* biR = 1 */
    mpz_set_ui(biR, 1);
    /* biN <- TestNbr mod biS */ /* Compute N mod S */
    mpz_fdiv_r(biN, TestNbr, biS);

    for (U = 1; U <= T; U++)
    {
      /* biR <- (biN * biR) mod biS */
      mpz_mul(biR, biN, biR);
      mpz_mod(biR, biR, biS);
      if (mpz_cmp_ui(biR, 1) == 0) /* biR == 1 */
      {
        /* Number is prime */
        free_vars();
        Py_RETURN_TRUE;
      }
      if (mpz_divisible_p(TestNbr, biR) && mpz_cmp(biR, TestNbr) < 0) /* biR < N and biR | TestNbr */
      {
        /* Number is composite */
        free_vars();
        Py_RETURN_FALSE;
      }
    } /* End for U */
    /* This should never be reached. */
    free_vars();
    SYSTEM_ERROR("Internal error: APR-CL error with final test.");
    return NULL;
  }
}
Ejemplo n.º 4
0
static void zp_mul_mpz(element_ptr n, element_ptr a, mpz_ptr z) {
  mpz_mul(n->data, a->data, z);
  mpz_mod(n->data, n->data, n->field->order);
}
Ejemplo n.º 5
0
void
mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
{
  mp_size_t asize, bsize;
  mp_ptr tmp_ap, tmp_bp;
  mp_size_t gsize, ssize, tmp_ssize;
  mp_ptr gp, tmp_gp, tmp_sp;
  TMP_DECL;

  /* mpn_gcdext requires that Usize >= Vsize.  Therefore, we often
     have to swap U and V.  The computed cofactor will be the
     "smallest" one, which is faster to produce.  The wanted one will
     be computed here; this is needed anyway when both are requested.  */

  asize = ABSIZ (a);
  bsize = ABSIZ (b);

  if (asize < bsize)
    {
      MPZ_SRCPTR_SWAP (a, b);
      MP_SIZE_T_SWAP (asize, bsize);
      MPZ_PTR_SWAP (s, t);
    }

  if (bsize == 0)
    {
      /* g = |a|, s = sgn(a), t = 0. */
      ssize = SIZ (a) >= 0 ? (asize != 0) : -1;

      gp = MPZ_REALLOC (g, asize);
      MPN_COPY (gp, PTR (a), asize);
      SIZ (g) = asize;

      if (t != NULL)
	SIZ (t) = 0;
      if (s != NULL)
	{
	  SIZ (s) = ssize;
	  PTR (s)[0] = 1;
	}
      return;
    }

  TMP_MARK;

  TMP_ALLOC_LIMBS_2 (tmp_ap, asize, tmp_bp, bsize);
  MPN_COPY (tmp_ap, PTR (a), asize);
  MPN_COPY (tmp_bp, PTR (b), bsize);

  TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, bsize + 1);

  gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize);

  ssize = ABS (tmp_ssize);
  tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize;

  if (t != NULL)
    {
      mpz_t x;
      __mpz_struct gtmp, stmp;

      PTR (&gtmp) = tmp_gp;
      SIZ (&gtmp) = gsize;

      PTR (&stmp) = tmp_sp;
      SIZ (&stmp) = tmp_ssize;

      MPZ_TMP_INIT (x, ssize + asize + 1);
      mpz_mul (x, &stmp, a);
      mpz_sub (x, &gtmp, x);
      mpz_divexact (t, x, b);
    }

  if (s != NULL)
    {
      mp_ptr sp;

      sp = MPZ_REALLOC (s, ssize);
      MPN_COPY (sp, tmp_sp, ssize);
      SIZ (s) = tmp_ssize;
    }

  gp = MPZ_REALLOC (g, gsize);
  MPN_COPY (gp, tmp_gp, gsize);
  SIZ (g) = gsize;

  TMP_FREE;
}
Ejemplo n.º 6
0
/* If x^y is exactly representable (with maybe a larger precision than z),
   round it in z and return the (mpc) inexact flag in [0, 10].

   If x^y is not exactly representable, return -1.

   If intermediate computations lead to numbers of more than maxprec bits,
   then abort and return -2 (in that case, to avoid loops, mpc_pow_exact
   should be called again with a larger value of maxprec).

   Assume one of Re(x) or Im(x) is non-zero, and y is non-zero (y is real).
*/
static int
mpc_pow_exact (mpc_ptr z, mpc_srcptr x, mpfr_srcptr y, mpc_rnd_t rnd,
               mp_prec_t maxprec)
{
  mp_exp_t ec, ed, ey, emin, emax;
  mpz_t my, a, b, c, d, u;
  unsigned long int t;
  int ret = -2;

  mpz_init (my);
  mpz_init (a);
  mpz_init (b);
  mpz_init (c);
  mpz_init (d);
  mpz_init (u);

  ey = mpfr_get_z_exp (my, y);
  /* normalize so that my is odd */
  t = mpz_scan1 (my, 0);
  ey += t;
  mpz_tdiv_q_2exp (my, my, t);

  if (mpfr_zero_p (MPC_RE(x)))
    {
      mpz_set_ui (c, 0);
      ec = 0;
    }
  else
    ec = mpfr_get_z_exp (c, MPC_RE(x));
  if (mpfr_zero_p (MPC_IM(x)))
    {
      mpz_set_ui (d, 0);
      ed = ec;
    }
  else
    {
      ed = mpfr_get_z_exp (d, MPC_IM(x));
      if (mpfr_zero_p (MPC_RE(x)))
        ec = ed;
    }
  /* x = c*2^ec + I * d*2^ed */
  /* equalize the exponents of x */
  if (ec < ed)
    {
      mpz_mul_2exp (d, d, ed - ec);
      if (mpz_sizeinbase (d, 2) > maxprec)
        goto end;
      ed = ec;
    }
  else if (ed < ec)
    {
      mpz_mul_2exp (c, c, ec - ed);
      if (mpz_sizeinbase (c, 2) > maxprec)
        goto end;
      ec = ed;
    }
  /* now ec=ed and x = (c + I * d) * 2^ec */

  /* divide by two if possible */
  if (mpz_cmp_ui (c, 0) == 0)
    {
      t = mpz_scan1 (d, 0);
      mpz_tdiv_q_2exp (d, d, t);
      ec += t;
    }
  else if (mpz_cmp_ui (d, 0) == 0)
    {
      t = mpz_scan1 (c, 0);
      mpz_tdiv_q_2exp (c, c, t);
      ec += t;
    }
  else /* neither c nor d is zero */
    {
      unsigned long v;
      t = mpz_scan1 (c, 0);
      v = mpz_scan1 (d, 0);
      if (v < t)
        t = v;
      mpz_tdiv_q_2exp (c, c, t);
      mpz_tdiv_q_2exp (d, d, t);
      ec += t;
    }

  /* now either one of c, d is odd */

  while (ey < 0)
    {
      /* check if x is a square */
      if (ec & 1)
        {
          mpz_mul_2exp (c, c, 1);
          mpz_mul_2exp (d, d, 1);
          ec --;
        }
      /* now ec is even */
      if (mpc_perfect_square_p (a, b, c, d) == 0)
        break;
      mpz_swap (a, c);
      mpz_swap (b, d);
      ec /= 2;
      ey ++;
    }

  if (ey < 0)
    {
      ret = -1; /* not representable */
      goto end;
    }

  /* Now ey >= 0, it thus suffices to check that x^my is representable.
     If my > 0, this is always true. If my < 0, we first try to invert
     (c+I*d)*2^ec.
  */
  if (mpz_cmp_ui (my, 0) < 0)
    {
      /* If my < 0, 1 / (c + I*d) = (c - I*d)/(c^2 + d^2), thus a sufficient
         condition is that c^2 + d^2 is a power of two, assuming |c| <> |d|.
         Assume a prime p <> 2 divides c^2 + d^2,
         then if p does not divide c or d, 1 / (c + I*d) cannot be exact.
         If p divides both c and d, then we can write c = p*c', d = p*d',
         and 1 / (c + I*d) = 1/p * 1/(c' + I*d'). This shows that if 1/(c+I*d)
         is exact, then 1/(c' + I*d') is exact too, and we are back to the
         previous case. In conclusion, a necessary and sufficient condition
         is that c^2 + d^2 is a power of two.
      */
      /* FIXME: we could first compute c^2+d^2 mod a limb for example */
      mpz_mul (a, c, c);
      mpz_addmul (a, d, d);
      t = mpz_scan1 (a, 0);
      if (mpz_sizeinbase (a, 2) != 1 + t) /* a is not a power of two */
        {
          ret = -1; /* not representable */
          goto end;
        }
      /* replace (c,d) by (c/(c^2+d^2), -d/(c^2+d^2)) */
      mpz_neg (d, d);
      ec = -ec - t;
      mpz_neg (my, my);
    }

  /* now ey >= 0 and my >= 0, and we want to compute
     [(c + I * d) * 2^ec] ^ (my * 2^ey).

     We first compute [(c + I * d) * 2^ec]^my, then square ey times. */
  t = mpz_sizeinbase (my, 2) - 1;
  mpz_set (a, c);
  mpz_set (b, d);
  ed = ec;
  /* invariant: (a + I*b) * 2^ed = ((c + I*d) * 2^ec)^trunc(my/2^t) */
  while (t-- > 0)
    {
      unsigned long v, w;
      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;
      if (mpz_tstbit (my, t)) /* multiply by c + I*d */
        {
          mpz_mul (u, a, c);
          mpz_submul (u, b, d); /* ac-bd */
          mpz_mul (b, b, c);
          mpz_addmul (b, a, d); /* bc+ad */
          mpz_swap (a, u);
          ed += ec;
        }
      /* remove powers of two in (a,b) */
      if (mpz_cmp_ui (a, 0) == 0)
        {
          w = mpz_scan1 (b, 0);
          mpz_tdiv_q_2exp (b, b, w);
          ed += w;
        }
      else if (mpz_cmp_ui (b, 0) == 0)
        {
          w = mpz_scan1 (a, 0);
          mpz_tdiv_q_2exp (a, a, w);
          ed += w;
        }
      else
        {
          w = mpz_scan1 (a, 0);
          v = mpz_scan1 (b, 0);
          if (v < w)
            w = v;
          mpz_tdiv_q_2exp (a, a, w);
          mpz_tdiv_q_2exp (b, b, w);
          ed += w;
        }
      if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }
  /* now a+I*b = (c+I*d)^my */

  while (ey-- > 0)
    {
      unsigned long sa, sb;

      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;

      /* divide by largest 2^n possible, to avoid many loops for e.g.,
         (2+2*I)^16777216 */
      sa = mpz_scan1 (a, 0);
      sb = mpz_scan1 (b, 0);
      sa = (sa <= sb) ? sa : sb;
      mpz_tdiv_q_2exp (a, a, sa);
      mpz_tdiv_q_2exp (b, b, sa);
      ed += sa;

      if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }

  /* save emin, emax */
  emin = mpfr_get_emin ();
  emax = mpfr_get_emax ();
  mpfr_set_emin (mpfr_get_emin_min ());
  mpfr_set_emax (mpfr_get_emax_max ());
  ret = mpfr_set_z (MPC_RE(z), a, MPC_RND_RE(rnd));
  ret = MPC_INEX(ret, mpfr_set_z (MPC_IM(z), b, MPC_RND_IM(rnd)));
  mpfr_mul_2si (MPC_RE(z), MPC_RE(z), ed, MPC_RND_RE(rnd));
  mpfr_mul_2si (MPC_IM(z), MPC_IM(z), ed, MPC_RND_IM(rnd));
  /* restore emin, emax */
  mpfr_set_emin (emin);
  mpfr_set_emax (emax);

 end:
  mpz_clear (my);
  mpz_clear (a);
  mpz_clear (b);
  mpz_clear (c);
  mpz_clear (d);
  mpz_clear (u);

  return ret;
}
Ejemplo n.º 7
0
int main(int argc, char *argv[])
{
	size_t i;
	unsigned int password_found;
	struct SRP_mitm_t mitm;
	struct server_t s;
	struct client_t c;
	mpz_t N, g, k, u, useless_u, x;
	mpz_t tmp_base, tmp_e, S;
	
	uint8_t buf[SHA256_HASH_SIZE];
	struct sha256nfo ctx;
	char *c_salt_str, *s_salt_str, *email, *candidate_p;
	
	mpz_init_set_str(N, NIST_N, 16 );
	mpz_init_set_str(g, NIST_g, 0 );
	mpz_init_set_str(k, NIST_k, 0 );

	// Init server
	server_init(&s, N, g, k, 1);
	server_add_entry(&s, "[email protected]", 16, "password123", 11);

	// Init client
	client_init(&c, N, g, k);

	// Init MITM
	server_init(&(mitm.s), N, g, k, 1);
	server_add_entry(&(mitm.s), "[email protected]", 16, "uselesspass", 11);
	client_init(&(mitm.c), N, g, k);

	/*
	 * MITM client pubkey interception	
	 *
	 *  S <--A--  MITM <--A--  C  
	 *     --u--> MITM  --u--> C 
	 */
	email = "[email protected]";
	c_salt_str = mitm_server_init_shared(&(mitm.s), email, strlen(email), c.srp.pubkey, &u);
	s_salt_str = server_init_shared(&s, email, strlen(email), mitm.c.srp.pubkey, &useless_u);
	
	if (NULL != c_salt_str)
	{
		c.salt_str = malloc(strlen(c_salt_str)*sizeof(char));
		if (NULL != c.salt_str)
		{
			/* 
			 * The MITM attacker does not know the client private DH key 'a'.
			 * However sending B == g cirumvent this unknown, since :
			 *   S = B**(a + ux) % n <==> S = (g**a).(g**ux) %n
			 * 						 <==> S =   A.g**ux %n
			 */
			c.salt_len = strlen(c_salt_str);
			memcpy(c.salt_str, c_salt_str, strlen(c_salt_str));
			client_init_shared(&c, "password123", strlen("password123") , mitm.s.srp.pubkey , u);


			/*
	 		 * MITM offline dictionnary attack
	 		 */
			i = 0x00;			
			password_found = 0x00;
			candidate_p = weak_passwords[0];

			while (NULL != candidate_p && !password_found)
			{
				srp_utils_gen_x(&x, candidate_p, strlen(candidate_p),c_salt_str, strlen(c_salt_str));

				// g**(u.x)
				mpz_init(tmp_base);
				mpz_init_set(tmp_e, u);
				mpz_mul(tmp_e, tmp_e, x );
				mpz_powm(tmp_base, g, tmp_e, N);

				mpz_init(S);
				mpz_mul(S, mitm.c.srp.pubkey, tmp_base );
				mpz_mod(S, S, N);

				srp_utils_gen_shared_key(mitm.c.K, S);

				mpz_clear(tmp_base);
				mpz_clear(tmp_e);
				mpz_clear(S);
				mpz_clear(x);
				
				if (!memcmp(mitm.c.K, c.K, sizeof(c.K)))
				{
					printf("Password successfully infered : %s !\n", candidate_p);
					password_found = 0x01;
				}
				else
				{
					i++;
					candidate_p = weak_passwords[i];
				}
			}

			/*
			 * Final server validation
			 */
			if (password_found)
			{
				mitm.c.salt_len = strlen(s_salt_str);
				mitm.c.salt_str = malloc(strlen(s_salt_str)*sizeof(char));
				if (NULL == mitm.c.salt_str)
					return 0x01;
				
				memcpy(mitm.c.salt_str, s_salt_str, strlen(s_salt_str));
				client_init_shared(&(mitm.c), candidate_p, strlen(candidate_p) , s.srp.pubkey, useless_u);


				sha256_init_Hmac(&ctx, mitm.c.K, SHA256_HASH_SIZE);
				sha256_write(&ctx, (uint8_t*) mitm.c.salt_str, mitm.c.salt_len);
				sha256_result_Hmac(&ctx, buf);

				if (server_check_password(&s, email, strlen(email),  buf))
					printf("We have a valid user : %s !\n", email);
				else
					printf("The following user is not registered : %s !\n", email);
			}
			else
				printf("The following user is not registered : %s !\n", email);
		}
	}
	else
		printf("The following user is not registered : %s !\n", email);

	client_cleanup(&c);
	server_cleanup(&s);
	server_cleanup(&(mitm.s));
	client_cleanup(&(mitm.c));

	mpz_clear(N);
	mpz_clear(g);
	mpz_clear(k);
	

	return 0x00;
}
Ejemplo n.º 8
0
void zFermat(uint64 limit, uint32 mult, fact_obj_t *fobj)
{
	// Fermat's factorization method with a sieve-based improvement
	// provided by 'neonsignal'
	mpz_t a, b2, tmp, multN, a2;
	int i;
	int numChars;
	uint64 reportIt, reportInc;
	uint64 count;
	uint64 i64;
	FILE *flog = NULL;
	uint32 M = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 5 * 7 * 7; //176400u
	uint32 M1 = 11 * 17 * 23 * 31; //133331u
	uint32 M2 = 13 * 19 * 29 * 37; //265031u
	uint8 *sqr, *sqr1, *sqr2, *mod, *mod1, *mod2;
	uint16 *skip;
	uint32 m, mmn, s, d;
	uint8 masks[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
	uint8 nmasks[8];
	uint32 iM = 0, iM1 = 0, iM2 = 0;

	if (mpz_even_p(fobj->div_obj.gmp_n))
	{
		mpz_init(tmp);
		mpz_set_ui(tmp, 2);
		mpz_tdiv_q_2exp(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, 1);
		add_to_factor_list(fobj, tmp);
		mpz_clear(tmp);
		return;
	}

	if (mpz_perfect_square_p(fobj->div_obj.gmp_n))
	{
		//open the log file
		flog = fopen(fobj->flogname,"a");
		if (flog == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open %s for writing\n",fobj->flogname);
			return;
		}

		mpz_sqrt(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n);
		if (is_mpz_prp(fobj->div_obj.gmp_n))
		{			
			logprint(flog, "Fermat method found perfect square factorization:\n");
			logprint(flog,"prp%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
			logprint(flog,"prp%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
		}
		else
		{
			logprint(flog, "Fermat method found perfect square factorization:\n");
			logprint(flog,"c%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
			logprint(flog,"c%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
		}
		add_to_factor_list(fobj, fobj->div_obj.gmp_n);
		add_to_factor_list(fobj, fobj->div_obj.gmp_n);
		mpz_set_ui(fobj->div_obj.gmp_n, 1);
		fclose(flog);
		return;
	}

	mpz_init(a);
	mpz_init(b2);
	mpz_init(tmp);
	mpz_init(multN);
	mpz_init(a2);

	// apply the user supplied multiplier
	mpz_mul_ui(multN, fobj->div_obj.gmp_n, mult);
	
	// compute ceil(sqrt(multN))
	mpz_sqrt(a, multN);

	// form b^2
	mpz_mul(b2, a, a);
	mpz_sub(b2, b2, multN);

	// test successive 'a' values using a sieve-based approach.
	// the idea is that not all 'a' values allow a^2 or b^2 to be square.  
	// we pre-compute allowable 'a' values modulo various smooth numbers and 
	// build tables to allow us to quickly iterate over 'a' values that are 
	// more likely to produce squares.
	// init sieve structures
	sqr = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8));
	sqr1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8));
	sqr2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8));
	mod = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8));
	mod1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8));
	mod2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8));
	skip = (uint16 *)malloc(M * sizeof(uint16));

	// test it.  This will be good enough if |u*p-v*q| < 2 * N^(1/4), where
	// mult = u*v
	count = 0;
	if (mpz_perfect_square_p(b2))
		goto found;

	for (i=0; i<8; i++)
		nmasks[i] = ~masks[i];

	// marks locations where squares can occur mod M, M1, M2
	for (i64 = 0; i64 < M; ++i64)
		setbit(sqr, (i64*i64)%M);

	for (i64 = 0; i64 < M1; ++i64)
		setbit(sqr1, (i64*i64)%M1);

	for (i64 = 0; i64 < M2; ++i64)
		setbit(sqr2, (i64*i64)%M2);

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where
	// b^2 can be a square
	m = mpz_mod_ui(tmp, a, M);
	mmn = mpz_mod_ui(tmp, b2, M);
	for (i = 0; i < M; ++i)
	{
		if (getbit(sqr, mmn)) setbit(mod, i);
		mmn = (mmn+m+m+1)%M;
		m = (m+1)%M;
	}

	// we only consider locations where the modular sequence mod M can
	// be square, so compute the distance to the next square location
	// at each possible value of i mod M.
	s = 0;
	d = 0;
	for (i = 0; !getbit(mod,i); ++i)
		++s;
	for (i = M; i > 0;)
	{
		--i;
		++s;
		skip[i] = s;
		if (s > d) d = s;
		if (getbit(mod,i)) s = 0;
	}
	//printf("maxSkip = %u\n", d);

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where the
	// modular sequence can be a square mod M1.  These will
	// generally differ from the sequence mod M.
	m = mpz_mod_ui(tmp, a, M1);
	mmn = mpz_mod_ui(tmp, b2, M1);
	for (i = 0; i < M1; ++i)
	{
		if (getbit(sqr1, mmn)) setbit(mod1, i);
		mmn = (mmn+m+m+1)%M1;
		m = (m+1)%M1;
	}

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where the
	// modular sequence can be a square mod M2.  These will
	// generally differ from the sequence mod M or M1.
	m = mpz_mod_ui(tmp, a, M2);
	mmn = mpz_mod_ui(tmp, b2, M2);
	for (i = 0; i < M2; ++i)
	{
		if (getbit(sqr2, mmn)) setbit(mod2, i);
		mmn = (mmn+m+m+1)%M2;
		m = (m+1)%M2;
	}

	// loop, checking for perfect squares
	mpz_mul_2exp(a2, a, 1);
	count = 0;
	numChars = 0;
	reportIt = limit / 100;
	reportInc = reportIt;
	do
	{
		d = 0;
		i64 = 0;
		do
		{
			// skip to the next possible square residue of b*b mod M
			s = skip[iM];

			// remember how far we skipped
			d += s;

			// update the other residue indices
			if ((iM1 += s) >= M1) iM1 -= M1;
			if ((iM2 += s) >= M2) iM2 -= M2;
			if ((iM += s) >= M) iM -= M;

			// some multpliers can lead to infinite loops.  bail out 
			// if so.
			if (++i64 > M) goto done;

			// continue if either of the other residues indicates
			// non-square.
		} while (!getbit(mod1,iM1) || !getbit(mod2,iM2));

		// form b^2 by incrementing by many factors of 2*a+1
		mpz_add_ui(tmp, a2, d);
		mpz_mul_ui(tmp, tmp, d);
		mpz_add(b2, b2, tmp);

		// accumulate so that we can reset d 
		// (and thus keep it single precision)
		mpz_add_ui(a2, a2, d*2);

		count += d;
		if (count > limit)
			break;

		//progress report
		if ((count > reportIt) && (VFLAG > 1))
		{
			for (i=0; i< numChars; i++)
				printf("\b");
			numChars = printf("%" PRIu64 "%%",(uint64)((double)count / (double)limit * 100));
			fflush(stdout);
			reportIt += reportInc;
		}
	} while (!mpz_perfect_square_p(b2));


found:

	// 'count' is how far we had to scan 'a' to find a square b
	mpz_add_ui(a, a, count);
	//printf("count is %" PRIu64 "\n", count);

	if ((mpz_size(b2) > 0) && mpz_perfect_square_p(b2))
	{
		//printf("found square at count = %d: a = %s, b2 = %s",count,
		//	z2decstr(&a,&gstr1),z2decstr(&b2,&gstr2));
		mpz_sqrt(tmp, b2); 		
		mpz_add(tmp, a, tmp);
		mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp);

		flog = fopen(fobj->flogname,"a");
		if (flog == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open %s for writing\n",fobj->flogname);
			goto done;
		}
		logprint(flog, "Fermat method found factors:\n");

		add_to_factor_list(fobj, tmp);
		if (is_mpz_prp(tmp))
		{			
			logprint(flog,"prp%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}
		else
		{
			logprint(flog,"c%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}

		mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp);
		mpz_sqrt(tmp, b2);
		mpz_sub(tmp, a, tmp);
		mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp);

		add_to_factor_list(fobj, tmp);
		if (is_mpz_prp(tmp))
		{			
			logprint(flog,"prp%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}
		else
		{
			logprint(flog,"c%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}

		mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp);
	}

done:
	mpz_clear(tmp);
	mpz_clear(a);
	mpz_clear(b2);
	mpz_clear(multN);
	mpz_clear(a2);
	free(sqr);
	free(sqr1);
	free(sqr2);
	free(mod);
	free(mod1);
	free(mod2);
	free(skip);
	if (flog != NULL)
		fclose(flog);
	return;

}
Ejemplo n.º 9
0
void rsa_generate(unsigned int b_size) {

    mpz_t p, q, n, d, e, phi;
    mpz_t phi_p, phi_q, p_mod;
    int p_size = b_size/2, q_size = b_size - b_size/2;

    mpz_init(p);
    mpz_init(q);
    mpz_init(n);
    mpz_init(d);
    mpz_init(e);
    mpz_init(phi);
    mpz_init(phi_p);
    mpz_init(phi_q);
    mpz_init(p_mod);

    do {
        /* prvocisla p,q */
        do {

            do {
                /* p */
                gen_prime(p_size,p);

                /* q */
                gen_prime(q_size,q);

            } while(mpz_cmp(p,q) == 0);/* p a q sa nerovnaju */

            /* phi */
            mpz_sub_ui(phi_p,p,1);
            mpz_sub_ui(phi_q,q,1);
            mpz_mul(phi,phi_q,phi_p);

            /* e */
            if(mpz_cmp_ui(phi,65537) > 0) { /* phi > 65537 */
                mpz_set_ui(e,65537);
            } else if(mpz_cmp_ui(phi,17) > 0) { /* phi > 17 */
                mpz_set_ui(e,17);
            } else {
                mpz_set_ui(e,3);
            }


            mpz_mod(p_mod,p,e);
        } while(mpz_cmp_ui(p_mod,1) == 0);/* (p mod e) !=1 */

        /* modulus n */
        mpz_mul(n,p,q);

        /* d */
        modular_inverse(e,phi,d);
    } while(mpz_cmp_ui(d,0) == 0); /* dokial nenajdes spravne, pre ktore existuj inverzia */

#ifdef DEBUG
    gmp_printf("p: %Zd\nq: %Zd\nn: %Zd\nphi: %Zd\ne: %Zd\nd: %Zd\n",p,q,n,phi,e,d);
#endif

    gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n",p,q,n,e,d);

    mpz_clear(p);
    mpz_clear(q);
    mpz_clear(n);
    mpz_clear(d);
    mpz_clear(e);
    mpz_clear(phi);
    mpz_clear(phi_p);
    mpz_clear(phi_q);
    mpz_clear(p_mod);
}
Ejemplo n.º 10
0
void
ecn_mul(mpz_t t1, mpz_t t2, mpz_t s,
	mpz_t rx, mpz_t ry,
	mpz_t modulus, mpz_t a, mpz_t b,
	mpz_t x1, mpz_t y1,
	mpz_t x2, mpz_t y2) {

  /* If the first point is the unit element, then we copy the other
     point. */
  if (mpz_cmp_si(x1, -1) == 0) {
    mpz_set(rx, x2);
    mpz_set(ry, y2);
    return;
  }

  /* If the second point is the unit element, then we copy the other
     point. */
  if (mpz_cmp_si(x2, -1) == 0) {
    mpz_set(rx, x1);
    mpz_set(ry, y1);
    return;
  }

  /* If the second point is inverse of the first point, then we return
     the unit point. */
  mpz_add(t1, y1, y2);
  if (mpz_cmp(x1, x2) == 0 && mpz_cmp(t1, modulus) == 0) {
    mpz_set_si(rx, -1);
    mpz_set_si(ry, -1);
    return;
  }

  /* If the first and second points are identical, then we square it. */
  if (mpz_cmp(x1, x2) == 0 && mpz_cmp(y1, y2) == 0) {
    ecn_square(t1, t2, s, rx, ry, modulus, a, b, x1, x2);
    return;
  }

  /* s = (y1 - y2) / (x1 - x2) */
  mpz_sub(t1, y1, y2);
  mpz_sub(t2, x1, x2);
  mpz_invert(t2, t2, modulus);
  mpz_mul(s, t1, t2);

  /* rx = s^2 - (x1 + x2) */
  mpz_mul(t1, s, s);
  mpz_sub(t1, t1, x1);
  mpz_sub(t1, t1, x2);

  /* ry = s(x1 - rx) - y1 */
  mpz_sub(t2, x1, t1);
  mpz_mul(t2, s, t2);
  mpz_sub(t2, t2, y1);

  /* We assign the destination parameters in the end to allow them to
     be identical to the inputs. */
  mpz_mod(rx, t1, modulus);
  mpz_mod(ry, t2, modulus);

  return;
}
Ejemplo n.º 11
0
int
main (int argc, char **argv)
{
  mpz_t base, exp, mod;
  mpz_t r1, r2, base2;
  mp_size_t base_size, exp_size, mod_size;
  unsigned long int exp2;
  int i;
  int reps = 100;
  gmp_randstate_ptr rands;
  mpz_t bs;
  unsigned long bsi, size_range;

  tests_start ();
  rands = RANDS;

  mpz_init (bs);

  if (argc == 2)
     reps = atoi (argv[1]);

  mpz_init (base);
  mpz_init (exp);
  mpz_init (mod);
  mpz_init (r1);
  mpz_init (r2);
  mpz_init (base2);

  for (i = 0; i < reps; i++)
    {
      mpz_urandomb (bs, rands, 32);
      size_range = mpz_get_ui (bs) % 18 + 2;

      do  /* Loop until mathematically well-defined.  */
	{
	  mpz_urandomb (bs, rands, size_range);
	  base_size = mpz_get_ui (bs);
	  mpz_rrandomb (base, rands, base_size);

	  mpz_urandomb (bs, rands, 6L);
	  exp_size = mpz_get_ui (bs);
	  mpz_rrandomb (exp, rands, exp_size);
	  exp2 = mpz_getlimbn (exp, (mp_size_t) 0);
	}
      while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0);

      do
        {
	  mpz_urandomb (bs, rands, size_range);
	  mod_size = mpz_get_ui (bs);
	  mpz_rrandomb (mod, rands, mod_size);
	}
      while (mpz_cmp_ui (mod, 0) == 0);

      mpz_urandomb (bs, rands, 2);
      bsi = mpz_get_ui (bs);
      if ((bsi & 1) != 0)
	mpz_neg (base, base);

      /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */

#if 0
      putc ('\n', stderr);
      debug_mp (base, -16);
      debug_mp (mod, -16);
#endif

      mpz_powm_ui (r1, base, exp2, mod);
      MPZ_CHECK_FORMAT (r1);

      mpz_set_ui (r2, 1);
      mpz_set (base2, base);

      mpz_mod (r2, r2, mod);	/* needed when exp==0 and mod==1 */
      while (exp2 != 0)
	{
	  if (exp2 % 2 != 0)
	    {
	      mpz_mul (r2, r2, base2);
	      mpz_mod (r2, r2, mod);
	    }
	  mpz_mul (base2, base2, base2);
	  mpz_mod (base2, base2, mod);
	  exp2 = exp2 / 2;
	}

#if 0
      debug_mp (r1, -16);
      debug_mp (r2, -16);
#endif

      if (mpz_cmp (r1, r2) != 0)
	{
	  fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i);
	  debug_mp (base, -16);
	  debug_mp (exp, -16);
	  debug_mp (mod, -16);
	  fprintf (stderr, "mpz_powm_ui result:\n");
	  debug_mp (r1, -16);
	  fprintf (stderr, "reference result:\n");
	  debug_mp (r2, -16);
	  abort ();
	}
    }

  mpz_clear (bs);
  mpz_clear (base);
  mpz_clear (exp);
  mpz_clear (mod);
  mpz_clear (r1);
  mpz_clear (r2);
  mpz_clear (base2);

  tests_end ();
  exit (0);
}
Ejemplo n.º 12
0
Archivo: t-tdiv.c Proyecto: HRF92/mpir
int
main (int argc, char **argv)
{
  mpz_t dividend, divisor;
  mpz_t quotient, remainder;
  mpz_t quotient2, remainder2;
  mpz_t temp;
  mp_size_t dividend_size, divisor_size;
  int i;
  int reps = 1000;
  gmp_randstate_t rands;
  mpz_t bs;
  unsigned long bsi, size_range;

  tests_start ();

  special_tests();

  gmp_randinit_default(rands);

  mpz_init (bs);

  if (argc == 2)
     reps = atoi (argv[1]);

  mpz_init (dividend);
  mpz_init (divisor);
  mpz_init (quotient);
  mpz_init (remainder);
  mpz_init (quotient2);
  mpz_init (remainder2);
  mpz_init (temp);

  for (i = 0; i < reps; i++)
    {
      mpz_urandomb (bs, rands, 32);
      size_range = mpz_get_ui (bs) % 16 + 2; /* 0..131071 bit operands */

      do
	{
	  mpz_urandomb (bs, rands, size_range);
	  divisor_size = mpz_get_ui (bs);
	  mpz_rrandomb (divisor, rands, divisor_size);
	}
      while (mpz_sgn (divisor) == 0);

      mpz_urandomb (bs, rands, size_range);
      dividend_size = mpz_get_ui (bs) + divisor_size;
      mpz_rrandomb (dividend, rands, dividend_size);

      mpz_urandomb (bs, rands, 2);
      bsi = mpz_get_ui (bs);
      if ((bsi & 1) != 0)
	mpz_neg (dividend, dividend);
      if ((bsi & 2) != 0)
	mpz_neg (divisor, divisor);

      /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */

      mpz_tdiv_qr (quotient, remainder, dividend, divisor);
      mpz_tdiv_q (quotient2, dividend, divisor);
      mpz_tdiv_r (remainder2, dividend, divisor);

      /* First determine that the quotients and remainders computed
	 with different functions are equal.  */
      if (mpz_cmp (quotient, quotient2) != 0)
   dump_abort (dividend, divisor);
      if (mpz_cmp (remainder, remainder2) != 0)
	dump_abort (dividend, divisor);

      /* Check if the sign of the quotient is correct.  */
      if (mpz_cmp_ui (quotient, 0) != 0)
	if ((mpz_cmp_ui (quotient, 0) < 0)
	    != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
	dump_abort (dividend, divisor);

      /* Check if the remainder has the same sign as the dividend
	 (quotient rounded towards 0).  */
      if (mpz_cmp_ui (remainder, 0) != 0)
	if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
	  dump_abort (dividend, divisor);

      mpz_mul (temp, quotient, divisor);
      mpz_add (temp, temp, remainder);
      if (mpz_cmp (temp, dividend) != 0)
	dump_abort (dividend, divisor);

      mpz_abs (temp, divisor);
      mpz_abs (remainder, remainder);
      if (mpz_cmp (remainder, temp) >= 0)
	dump_abort (dividend, divisor);
    }

  mpz_clear (bs);
  mpz_clear (dividend);
  mpz_clear (divisor);
  mpz_clear (quotient);
  mpz_clear (remainder);
  mpz_clear (quotient2);
  mpz_clear (remainder2);
  mpz_clear (temp);
  gmp_randclear(rands);
  tests_end ();
  exit (0);
}
Ejemplo n.º 13
0
void
spectral_test (mpf_t rop[], unsigned int T, mpz_t a, mpz_t m)
{
  /* Knuth "Seminumerical Algorithms, Third Edition", section 3.3.4
     (pp. 101-103). */

  /* v[t] = min { sqrt (x[1]^2 + ... + x[t]^2) |
     x[1] + a*x[2] + ... + pow (a, t-1) * x[t] is congruent to 0 (mod m) } */


  /* Variables. */
  unsigned int ui_t;
  unsigned int ui_i, ui_j, ui_k, ui_l;
  mpf_t f_tmp1, f_tmp2;
  mpz_t tmp1, tmp2, tmp3;
  mpz_t U[GMP_SPECT_MAXT][GMP_SPECT_MAXT],
    V[GMP_SPECT_MAXT][GMP_SPECT_MAXT],
    X[GMP_SPECT_MAXT],
    Y[GMP_SPECT_MAXT],
    Z[GMP_SPECT_MAXT];
  mpz_t h, hp, r, s, p, pp, q, u, v;

  /* GMP inits. */
  mpf_init (f_tmp1);
  mpf_init (f_tmp2);
  for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++)
    {
      for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++)
	{
	  mpz_init_set_ui (U[ui_i][ui_j], 0);
	  mpz_init_set_ui (V[ui_i][ui_j], 0);
	}
      mpz_init_set_ui (X[ui_i], 0);
      mpz_init_set_ui (Y[ui_i], 0);
      mpz_init (Z[ui_i]);
    }
  mpz_init (tmp1);
  mpz_init (tmp2);
  mpz_init (tmp3);
  mpz_init (h);
  mpz_init (hp);
  mpz_init (r);
  mpz_init (s);
  mpz_init (p);
  mpz_init (pp);
  mpz_init (q);
  mpz_init (u);
  mpz_init (v);

  /* Implementation inits. */
  if (T > GMP_SPECT_MAXT)
    T = GMP_SPECT_MAXT;			/* FIXME: Lazy. */

  /* S1 [Initialize.] */
  ui_t = 2 - 1;			/* NOTE: `t' in description == ui_t + 1
				   for easy indexing */
  mpz_set (h, a);
  mpz_set (hp, m);
  mpz_set_ui (p, 1);
  mpz_set_ui (pp, 0);
  mpz_set (r, a);
  mpz_pow_ui (s, a, 2);
  mpz_add_ui (s, s, 1);		/* s = 1 + a^2 */

  /* S2 [Euclidean step.] */
  while (1)
    {
      if (g_debug > DEBUG_1)
	{
	  mpz_mul (tmp1, h, pp);
	  mpz_mul (tmp2, hp, p);
	  mpz_sub (tmp1, tmp1, tmp2);
	  if (mpz_cmpabs (m, tmp1))
	    {
	      printf ("***BUG***: h*pp - hp*p = ");
	      mpz_out_str (stdout, 10, tmp1);
	      printf ("\n");
	    }
	}
      if (g_debug > DEBUG_2)
	{
	  printf ("hp = ");
	  mpz_out_str (stdout, 10, hp);
	  printf ("\nh = ");
	  mpz_out_str (stdout, 10, h);
	  printf ("\n");
	  fflush (stdout);
	}

      if (mpz_sgn (h))
	mpz_tdiv_q (q, hp, h);	/* q = floor(hp/h) */
      else
	mpz_set_ui (q, 1);

      if (g_debug > DEBUG_2)
	{
	  printf ("q = ");
	  mpz_out_str (stdout, 10, q);
	  printf ("\n");
	  fflush (stdout);
	}

      mpz_mul (tmp1, q, h);
      mpz_sub (u, hp, tmp1);	/* u = hp - q*h */

      mpz_mul (tmp1, q, p);
      mpz_sub (v, pp, tmp1);	/* v = pp - q*p */

      mpz_pow_ui (tmp1, u, 2);
      mpz_pow_ui (tmp2, v, 2);
      mpz_add (tmp1, tmp1, tmp2);
      if (mpz_cmp (tmp1, s) < 0)
	{
	  mpz_set (s, tmp1);	/* s = u^2 + v^2 */
	  mpz_set (hp, h);	/* hp = h */
	  mpz_set (h, u);	/* h = u */
	  mpz_set (pp, p);	/* pp = p */
	  mpz_set (p, v);	/* p = v */
	}
      else
	break;
    }

  /* S3 [Compute v2.] */
  mpz_sub (u, u, h);
  mpz_sub (v, v, p);

  mpz_pow_ui (tmp1, u, 2);
  mpz_pow_ui (tmp2, v, 2);
  mpz_add (tmp1, tmp1, tmp2);
  if (mpz_cmp (tmp1, s) < 0)
    {
      mpz_set (s, tmp1);	/* s = u^2 + v^2 */
      mpz_set (hp, u);
      mpz_set (pp, v);
    }
  mpf_set_z (f_tmp1, s);
  mpf_sqrt (rop[ui_t - 1], f_tmp1);

  /* S4 [Advance t.] */
  mpz_neg (U[0][0], h);
  mpz_set (U[0][1], p);
  mpz_neg (U[1][0], hp);
  mpz_set (U[1][1], pp);

  mpz_set (V[0][0], pp);
  mpz_set (V[0][1], hp);
  mpz_neg (V[1][0], p);
  mpz_neg (V[1][1], h);
  if (mpz_cmp_ui (pp, 0) > 0)
    {
      mpz_neg (V[0][0], V[0][0]);
      mpz_neg (V[0][1], V[0][1]);
      mpz_neg (V[1][0], V[1][0]);
      mpz_neg (V[1][1], V[1][1]);
    }

  while (ui_t + 1 != T)		/* S4 loop */
    {
      ui_t++;
      mpz_mul (r, a, r);
      mpz_mod (r, r, m);

      /* Add new row and column to U and V.  They are initialized with
	 all elements set to zero, so clearing is not necessary. */

      mpz_neg (U[ui_t][0], r); /* U: First col in new row. */
      mpz_set_ui (U[ui_t][ui_t], 1); /* U: Last col in new row. */

      mpz_set (V[ui_t][ui_t], m); /* V: Last col in new row. */

      /* "Finally, for 1 <= i < t,
	   set q = round (vi1 * r / m),
	   vit = vi1*r - q*m,
	   and Ut=Ut+q*Ui */

      for (ui_i = 0; ui_i < ui_t; ui_i++)
	{
	  mpz_mul (tmp1, V[ui_i][0], r); /* tmp1=vi1*r */
	  zdiv_round (q, tmp1, m); /* q=round(vi1*r/m) */
	  mpz_mul (tmp2, q, m);	/* tmp2=q*m */
	  mpz_sub (V[ui_i][ui_t], tmp1, tmp2);

	  for (ui_j = 0; ui_j <= ui_t; ui_j++) /* U[t] = U[t] + q*U[i] */
	    {
	      mpz_mul (tmp1, q, U[ui_i][ui_j]);	/* tmp=q*uij */
	      mpz_add (U[ui_t][ui_j], U[ui_t][ui_j], tmp1); /* utj = utj + q*uij */
	    }
	}

      /* s = min (s, zdot (U[t], U[t]) */
      vz_dot (tmp1, U[ui_t], U[ui_t], ui_t + 1);
      if (mpz_cmp (tmp1, s) < 0)
	mpz_set (s, tmp1);

      ui_k = ui_t;
      ui_j = 0;			/* WARNING: ui_j no longer a temp. */

      /* S5 [Transform.] */
      if (g_debug > DEBUG_2)
	printf ("(t, k, j, q1, q2, ...)\n");
      do
	{
	  if (g_debug > DEBUG_2)
	    printf ("(%u, %u, %u", ui_t + 1, ui_k + 1, ui_j + 1);

	  for (ui_i = 0; ui_i <= ui_t; ui_i++)
	    {
	      if (ui_i != ui_j)
		{
		  vz_dot (tmp1, V[ui_i], V[ui_j], ui_t + 1); /* tmp1=dot(Vi,Vj). */
		  mpz_abs (tmp2, tmp1);
		  mpz_mul_ui (tmp2, tmp2, 2); /* tmp2 = 2*abs(dot(Vi,Vj) */
		  vz_dot (tmp3, V[ui_j], V[ui_j], ui_t + 1); /* tmp3=dot(Vj,Vj). */

		  if (mpz_cmp (tmp2, tmp3) > 0)
		    {
		      zdiv_round (q, tmp1, tmp3); /* q=round(Vi.Vj/Vj.Vj) */
		      if (g_debug > DEBUG_2)
			{
			  printf (", ");
			  mpz_out_str (stdout, 10, q);
			}

		      for (ui_l = 0; ui_l <= ui_t; ui_l++)
			{
			  mpz_mul (tmp1, q, V[ui_j][ui_l]);
			  mpz_sub (V[ui_i][ui_l], V[ui_i][ui_l], tmp1); /* Vi=Vi-q*Vj */
			  mpz_mul (tmp1, q, U[ui_i][ui_l]);
			  mpz_add (U[ui_j][ui_l], U[ui_j][ui_l], tmp1); /* Uj=Uj+q*Ui */
			}

		      vz_dot (tmp1, U[ui_j], U[ui_j], ui_t + 1); /* tmp1=dot(Uj,Uj) */
		      if (mpz_cmp (tmp1, s) < 0) /* s = min(s,dot(Uj,Uj)) */
			mpz_set (s, tmp1);
		      ui_k = ui_j;
		    }
		  else if (g_debug > DEBUG_2)
		    printf (", #"); /* 2|Vi.Vj| <= Vj.Vj */
		}
	      else if (g_debug > DEBUG_2)
		printf (", *");	/* i == j */
	    }

	  if (g_debug > DEBUG_2)
	    printf (")\n");

	  /* S6 [Advance j.] */
	  if (ui_j == ui_t)
	    ui_j = 0;
	  else
	    ui_j++;
	}
      while (ui_j != ui_k);	/* S5 */

      /* From Knuth p. 104: "The exhaustive search in steps S8-S10
	 reduces the value of s only rarely." */
#ifdef DO_SEARCH
      /* S7 [Prepare for search.] */
      /* Find minimum in (x[1], ..., x[t]) satisfying condition
	 x[k]^2 <= f(y[1], ...,y[t]) * dot(V[k],V[k]) */

      ui_k = ui_t;
      if (g_debug > DEBUG_2)
	{
	  printf ("searching...");
	  /*for (f = 0; f < ui_t*/
	  fflush (stdout);
	}

      /* Z[i] = floor (sqrt (floor (dot(V[i],V[i]) * s / m^2))); */
      mpz_pow_ui (tmp1, m, 2);
      mpf_set_z (f_tmp1, tmp1);
      mpf_set_z (f_tmp2, s);
      mpf_div (f_tmp1, f_tmp2, f_tmp1);	/* f_tmp1 = s/m^2 */
      for (ui_i = 0; ui_i <= ui_t; ui_i++)
	{
	  vz_dot (tmp1, V[ui_i], V[ui_i], ui_t + 1);
	  mpf_set_z (f_tmp2, tmp1);
	  mpf_mul (f_tmp2, f_tmp2, f_tmp1);
	  f_floor (f_tmp2, f_tmp2);
	  mpf_sqrt (f_tmp2, f_tmp2);
	  mpz_set_f (Z[ui_i], f_tmp2);
	}

      /* S8 [Advance X[k].] */
      do
	{
	  if (g_debug > DEBUG_2)
	    {
	      printf ("X[%u] = ", ui_k);
	      mpz_out_str (stdout, 10, X[ui_k]);
	      printf ("\tZ[%u] = ", ui_k);
	      mpz_out_str (stdout, 10, Z[ui_k]);
	      printf ("\n");
	      fflush (stdout);
	    }

	  if (mpz_cmp (X[ui_k], Z[ui_k]))
	    {
	      mpz_add_ui (X[ui_k], X[ui_k], 1);
	      for (ui_i = 0; ui_i <= ui_t; ui_i++)
		mpz_add (Y[ui_i], Y[ui_i], U[ui_k][ui_i]);

	      /* S9 [Advance k.] */
	      while (++ui_k <= ui_t)
		{
		  mpz_neg (X[ui_k], Z[ui_k]);
		  mpz_mul_ui (tmp1, Z[ui_k], 2);
		  for (ui_i = 0; ui_i <= ui_t; ui_i++)
		    {
		      mpz_mul (tmp2, tmp1, U[ui_k][ui_i]);
		      mpz_sub (Y[ui_i], Y[ui_i], tmp2);
		    }
		}
	      vz_dot (tmp1, Y, Y, ui_t + 1);
	      if (mpz_cmp (tmp1, s) < 0)
		mpz_set (s, tmp1);
	    }
	}
      while (--ui_k);
#endif /* DO_SEARCH */
      mpf_set_z (f_tmp1, s);
      mpf_sqrt (rop[ui_t - 1], f_tmp1);
#ifdef DO_SEARCH
      if (g_debug > DEBUG_2)
	printf ("done.\n");
#endif /* DO_SEARCH */
    } /* S4 loop */

  /* Clear GMP variables. */

  mpf_clear (f_tmp1);
  mpf_clear (f_tmp2);
  for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++)
    {
      for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++)
	{
	  mpz_clear (U[ui_i][ui_j]);
	  mpz_clear (V[ui_i][ui_j]);
	}
      mpz_clear (X[ui_i]);
      mpz_clear (Y[ui_i]);
      mpz_clear (Z[ui_i]);
    }
  mpz_clear (tmp1);
  mpz_clear (tmp2);
  mpz_clear (tmp3);
  mpz_clear (h);
  mpz_clear (hp);
  mpz_clear (r);
  mpz_clear (s);
  mpz_clear (p);
  mpz_clear (pp);
  mpz_clear (q);
  mpz_clear (u);
  mpz_clear (v);

  return;
}
Ejemplo n.º 14
0
Archivo: dive.c Proyecto: mahdiz/mpclib
int
main (int argc, char **argv)
{
  mpz_t op1, op2;
  mpz_t prod, quot;
  mp_size_t size;
  int i;
  int reps = 20000;
  gmp_randstate_ptr rands;
  mpz_t bs;
  unsigned long bsi, size_range;

  tests_start ();
  rands = RANDS;

  mp_trace_base = -16;

  mpz_init (bs);

  if (argc == 2)
     reps = atoi (argv[1]);

  mpz_init (op1);
  mpz_init (op2);
  mpz_init (prod);
  mpz_init (quot);

  for (i = 0; i < reps; i++)
    {
      mpz_urandomb (bs, rands, 32);
      size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */

      mpz_urandomb (bs, rands, size_range);
      size = mpz_get_ui (bs);
      mpz_rrandomb (op1, rands, size);

      do
	{
	  mpz_urandomb (bs, rands, size_range);
	  size = mpz_get_ui (bs);
	  mpz_rrandomb (op2, rands, size);
	}
      while (mpz_sgn (op2) == 0);

      mpz_urandomb (bs, rands, 2);
      bsi = mpz_get_ui (bs);
      if ((bsi & 1) != 0)
	mpz_neg (op1, op1);
      if ((bsi & 2) != 0)
	mpz_neg (op2, op2);

      mpz_mul (prod, op1, op2);

      mpz_divexact (quot, prod, op2);
      MPZ_CHECK_FORMAT (quot);

      if (mpz_cmp (quot, op1) != 0)
        {
          printf ("Wrong results:\n");
          mpz_trace ("  got     ", quot);
          mpz_trace ("  want    ", op1);
          mpz_trace ("  dividend", prod);
          mpz_trace ("  divisor ", op2);
          abort ();
        }
    }

  mpz_clear (bs);
  mpz_clear (op1);
  mpz_clear (op2);
  mpz_clear (prod);
  mpz_clear (quot);

  tests_end ();
  exit (0);
}
Ejemplo n.º 15
0
void mpz_sqrtmp_r
	(mpz_ptr root, mpz_srcptr a, mpz_srcptr p)
{
	/* ? a \neq 0 */
	if (mpz_get_ui(a) != 0)
	{
		/* ? p = 3 (mod 4) */
		if (mpz_congruent_ui_p(p, 3L, 4L))
		{
			mpz_t foo;
			mpz_init_set(foo, p);
			mpz_add_ui(foo, foo, 1L);
			mpz_fdiv_q_2exp(foo, foo, 2L);
			mpz_powm(root, a, foo, p);
			mpz_clear(foo);
			return;
		}
		/* ! p = 1 (mod 4) */
		else
		{
			/* ! s = (p-1)/4 */
			mpz_t s;
			mpz_init_set(s, p);
			mpz_sub_ui(s, s, 1L);
			mpz_fdiv_q_2exp(s, s, 2L);
			/* ? p = 5 (mod 8) */
			if (mpz_congruent_ui_p(p, 5L, 8L))
			{
				mpz_t foo, b;
				mpz_init(foo);
				mpz_powm(foo, a, s, p);
				mpz_init_set(b, p);
				mpz_add_ui(b, b, 3L);
				mpz_fdiv_q_2exp(b, b, 3L);
				mpz_powm(root, a, b, p);
				/* ? a^{(p-1)/4} = 1 (mod p) */
				if (mpz_cmp_ui(foo, 1L) == 0)
				{
					mpz_clear(foo), mpz_clear(s), mpz_clear(b);
					return;
				}
				/* ! a^{(p-1)/4} = -1 (mod p) */
				else
				{
					do
						mpz_wrandomm(b, p);
					while (mpz_jacobi(b, p) != -1);
					mpz_powm(b, b, s, p);
					mpz_mul(root, root, b);
					mpz_mod(root, root, p);
					mpz_clear(foo), mpz_clear(s), mpz_clear(b);
					return;
				}
			}
			/* ! p = 1 (mod 8) */
			else
			{
				mpz_t foo, bar, b, t;
				mpz_init(foo), mpz_init(bar);
				mpz_powm(foo, a, s, p);
				/* while a^s = 1 (mod p) */
				while (mpz_cmp_ui(foo, 1L) == 0)
				{
					/* ? s odd */
					if (mpz_odd_p(s))
					{
						mpz_add_ui(s, s, 1L);
						mpz_fdiv_q_2exp(s, s, 1L);
						mpz_powm(root, a, s, p);
						mpz_clear(foo), mpz_clear(s);
						return;
					}
					/* ! s even */
					else
					{
						mpz_fdiv_q_2exp(s, s, 1L);
					}
					mpz_powm(foo, a, s, p);
				}
				/* ! a^s = -1 (mod p) */
				mpz_init(b);
				do
					mpz_wrandomm(b, p);
				while (mpz_jacobi(b, p) != -1);
				mpz_init_set(t, p);
				mpz_sub_ui(t, t, 1L);
				mpz_fdiv_q_2exp(t, t, 1L);
				/* while s even */
				while (mpz_even_p(s))
				{
					mpz_fdiv_q_2exp(s, s, 1L);
					mpz_fdiv_q_2exp(t, t, 1L);
					mpz_powm(foo, a, s, p);
					mpz_powm(bar, b, t, p);
					mpz_mul(foo, foo, bar);
					mpz_mod(foo, foo, p);
					mpz_set_si(bar, -1L);
					/* ? a^s * b^t = -1 (mod p) */
					if (mpz_congruent_p(foo, bar, p))
					{
						mpz_set(bar, p);
						mpz_sub_ui(bar, bar, 1L);
						mpz_fdiv_q_2exp(bar, bar, 1L);
						mpz_add(t, t, bar);
					}
				}
				mpz_add_ui(s, s, 1L);
				mpz_fdiv_q_2exp(s, s, 1L);
				mpz_fdiv_q_2exp(t, t, 1L);
				mpz_powm(foo, a, s, p);
				mpz_powm(bar, b, t, p);
				mpz_mul(root, foo, bar);
				mpz_mod(root, root, p);
				mpz_clear(foo), mpz_clear(bar);
				mpz_clear(s), mpz_clear(b), mpz_clear(t);
				return;
			}
		}
	}
	/* error, return zero root */
	mpz_set_ui(root, 0L);
}
Ejemplo n.º 16
0
// set op to (op1 * op2) mod d, using tmp for the calculation
inline static void mpz_mulm(
	mpz_t op, const mpz_t op1, const mpz_t op2, const mpz_t d, mpz_t tmp)
{
	mpz_mul(tmp, op1, op2);
	mpz_mod(op, tmp, d);
}
Ejemplo n.º 17
0
/* NOTE: Assumes mpz_t's are initted in ku and kp */
void generate_keys(private_key* ku, public_key* kp)
{
    char buf[BUFFER_SIZE];
    int i;
    mpz_t phi; mpz_init(phi);
    mpz_t tmp1; mpz_init(tmp1);
    mpz_t tmp2; mpz_init(tmp2);

    srand(time(NULL));

    /* Insetead of selecting e st. gcd(phi, e) = 1; 1 < e < phi, lets choose e
     * first then pick p,q st. gcd(e, p-1) = gcd(e, q-1) = 1 */
    // We'll set e globally.  I've seen suggestions to use primes like 3, 17 or 
    // 65537, as they make coming calculations faster.  Lets use 3.
    mpz_set_ui(ku->e, 3); 

    /* Select p and q */
    /* Start with p */
    // Set the bits of tmp randomly
    for(i = 0; i < BUFFER_SIZE; i++)
        buf[i] = rand() % 0xFF; 
    // Set the top two bits to 1 to ensure int(tmp) is relatively large
    buf[0] |= 0xC0;
    // Set the bottom bit to 1 to ensure int(tmp) is odd (better for finding primes)
    buf[BUFFER_SIZE - 1] |= 0x01;
    // Interpret this char buffer as an int
    mpz_import(tmp1, BUFFER_SIZE, 1, sizeof(buf[0]), 0, 0, buf);
    // Pick the next prime starting from that random number
    mpz_nextprime(ku->p, tmp1);
    /* Make sure this is a good choice*/
    mpz_mod(tmp2, ku->p, ku->e);        /* If p mod e == 1, gcd(phi, e) != 1 */
    while(!mpz_cmp_ui(tmp2, 1))         
    {
        mpz_nextprime(ku->p, ku->p);    /* so choose the next prime */
        mpz_mod(tmp2, ku->p, ku->e);
    }

    /* Now select q */
    do {
        for(i = 0; i < BUFFER_SIZE; i++)
            buf[i] = rand() % 0xFF; 
        // Set the top two bits to 1 to ensure int(tmp) is relatively large
        buf[0] |= 0xC0;
        // Set the bottom bit to 1 to ensure int(tmp) is odd
        buf[BUFFER_SIZE - 1] |= 0x01;
        // Interpret this char buffer as an int
        mpz_import(tmp1, (BUFFER_SIZE), 1, sizeof(buf[0]), 0, 0, buf);
        // Pick the next prime starting from that random number
        mpz_nextprime(ku->q, tmp1);
        mpz_mod(tmp2, ku->q, ku->e);
        while(!mpz_cmp_ui(tmp2, 1))
        {
            mpz_nextprime(ku->q, ku->q);
            mpz_mod(tmp2, ku->q, ku->e);
        }
    } while(mpz_cmp(ku->p, ku->q) == 0); /* If we have identical primes (unlikely), try again */

    /* Calculate n = p x q */
    mpz_mul(ku->n, ku->p, ku->q);

    /* Compute phi(n) = (p-1)(q-1) */
    mpz_sub_ui(tmp1, ku->p, 1);
    mpz_sub_ui(tmp2, ku->q, 1);
    mpz_mul(phi, tmp1, tmp2);

    /* Calculate d (multiplicative inverse of e mod phi) */
    if(mpz_invert(ku->d, ku->e, phi) == 0)
    {
        mpz_gcd(tmp1, ku->e, phi);
        printf("gcd(e, phi) = [%s]\n", mpz_get_str(NULL, 16, tmp1));
        printf("Invert failed\n");
    }

    /* Set public key */
    mpz_set(kp->e, ku->e);
    mpz_set(kp->n, ku->n);

    return;
}
Ejemplo n.º 18
0
/* Output: bytes_M. Buffer length is SHA512_DIGEST_LENGTH */
void  srp_user_process_challenge(struct SRPUser *usr,
	const unsigned char *bytes_s, size_t len_s,
	const unsigned char *bytes_B, size_t len_B,
	unsigned char **bytes_M, size_t *len_M)
{
	mpz_t B; mpz_init(B); mpz_from_bin(bytes_B, len_B, B);
	mpz_t u; mpz_init(u);
	mpz_t x; mpz_init(x);
	mpz_t k; mpz_init(k);
	mpz_t v; mpz_init(v);
	mpz_t tmp1; mpz_init(tmp1);
	mpz_t tmp2; mpz_init(tmp2);
	mpz_t tmp3; mpz_init(tmp3);
	mpz_t tmp4; mpz_init(tmp4);
	// clang-format on

	*len_M = 0;
	*bytes_M = 0;

	if (!H_nn(u, usr->hash_alg, usr->ng->N, usr->A, B)) goto cleanup_and_exit;

	srp_dbg_num(u, "Client calculated u: ");

	if (!calculate_x(x, usr->hash_alg, bytes_s, len_s, usr->username_verifier,
			usr->password, usr->password_len))
		goto cleanup_and_exit;

	srp_dbg_num(x, "Client calculated x: ");

	if (!H_nn(k, usr->hash_alg, usr->ng->N, usr->ng->N, usr->ng->g))
		goto cleanup_and_exit;

	/* SRP-6a safety check */
	if (mpz_sgn(B) != 0 && mpz_sgn(u) != 0) {
		mpz_powm(v, usr->ng->g, x, usr->ng->N);

		srp_dbg_num(v, "Client calculated v: ");

		// clang-format off
		/* S = (B - k*(g^x)) ^ (a + ux) */
		mpz_mul(tmp1, u, x);
		mpz_add(tmp2, usr->a, tmp1);               /* tmp2 = (a + ux)      */
		mpz_powm(tmp1, usr->ng->g, x, usr->ng->N); /* tmp1 = g^x           */
		mpz_mulm(tmp3, k, tmp1, usr->ng->N, tmp4); /* tmp3 = k*(g^x)       */
		mpz_subm(tmp1, B, tmp3, usr->ng->N, tmp4); /* tmp1 = (B - K*(g^x)) */
		mpz_powm(usr->S, tmp1, tmp2, usr->ng->N);
		// clang-format on

		if (!hash_num(usr->hash_alg, usr->S, usr->session_key)) goto cleanup_and_exit;

		if (!calculate_M(usr->hash_alg, usr->ng, usr->M, usr->username, bytes_s, len_s,
				usr->A, B, usr->session_key))
			goto cleanup_and_exit;
		if (!calculate_H_AMK(usr->hash_alg, usr->H_AMK, usr->A, usr->M, usr->session_key))
			goto cleanup_and_exit;

		*bytes_M = usr->M;
		if (len_M) *len_M = hash_length(usr->hash_alg);
	} else {
		*bytes_M = NULL;
		if (len_M) *len_M = 0;
	}

cleanup_and_exit:
	mpz_clear(B);
	mpz_clear(u);
	mpz_clear(x);
	mpz_clear(k);
	mpz_clear(v);
	mpz_clear(tmp1);
	mpz_clear(tmp2);
	mpz_clear(tmp3);
	mpz_clear(tmp4);
}
Ejemplo n.º 19
0
static int
mpfr_rem1 (mpfr_ptr rem, long *quo, mpfr_rnd_t rnd_q,
           mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd)
{
  mpfr_exp_t ex, ey;
  int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x);
  mpz_t mx, my, r;
  int tiny = 0;

  MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y)))
    {
      if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x)
          || MPFR_IS_ZERO (y))
        {
          /* for remquo, quo is undefined */
          MPFR_SET_NAN (rem);
          MPFR_RET_NAN;
        }
      else                      /* either y is Inf and x is 0 or non-special,
                                   or x is 0 and y is non-special,
                                   in both cases the quotient is zero. */
        {
          if (quo)
            *quo = 0;
          return mpfr_set (rem, x, rnd);
        }
    }

  /* now neither x nor y is NaN, Inf or zero */

  mpz_init (mx);
  mpz_init (my);
  mpz_init (r);

  ex = mpfr_get_z_2exp (mx, x);  /* x = mx*2^ex */
  ey = mpfr_get_z_2exp (my, y);  /* y = my*2^ey */

  /* to get rid of sign problems, we compute it separately:
     quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y)
     quo(-x,y) = -quo(x,y), rem(-x,y)  = -rem(x,y)
     thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */
  sign = (signx == MPFR_SIGN (y)) ? 1 : -1;
  mpz_abs (mx, mx);
  mpz_abs (my, my);
  q_is_odd = 0;

  /* divide my by 2^k if possible to make operations mod my easier */
  {
    unsigned long k = mpz_scan1 (my, 0);
    ey += k;
    mpz_fdiv_q_2exp (my, my, k);
  }

  if (ex <= ey)
    {
      /* q = x/y = mx/(my*2^(ey-ex)) */

      /* First detect cases where q=0, to avoid creating a huge number
         my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy =
         mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and
         y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1
         the quotient is 0 */
      if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) <
          ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
        {
          tiny = 1;
          mpz_set (r, mx);
          mpz_set_ui (mx, 0);
        }
      else
        {
          mpz_mul_2exp (my, my, ey - ex);   /* divide mx by my*2^(ey-ex) */

          /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */
          mpz_tdiv_qr (mx, r, mx, my);
          /* 0 <= |r| <= |my|, r has the same sign as mx */
        }

      if (rnd_q == MPFR_RNDN)
        q_is_odd = mpz_tstbit (mx, 0);
      if (quo)                  /* mx is the quotient */
        {
          mpz_tdiv_r_2exp (mx, mx, WANTED_BITS);
          *quo = mpz_get_si (mx);
        }
    }
  else                          /* ex > ey */
    {
      if (quo) /* remquo case */
        /* for remquo, to get the low WANTED_BITS more bits of the quotient,
           we first compute R =  X mod Y*2^WANTED_BITS, where X and Y are
           defined below. Then the low WANTED_BITS of the quotient are
           floor(R/Y). */
        mpz_mul_2exp (my, my, WANTED_BITS);     /* 2^WANTED_BITS*Y */

      else if (rnd_q == MPFR_RNDN) /* remainder case */
        /* Let X = mx*2^(ex-ey) and Y = my. Then both X and Y are integers.
           Assume X = R mod Y, then x = X*2^ey = R*2^ey mod (Y*2^ey=y).
           To be able to perform the rounding, we need the least significant
           bit of the quotient, i.e., one more bit in the remainder,
           which is obtained by dividing by 2Y. */
        mpz_mul_2exp (my, my, 1);       /* 2Y */

      mpz_set_ui (r, 2);
      mpz_powm_ui (r, r, ex - ey, my);  /* 2^(ex-ey) mod my */
      mpz_mul (r, r, mx);
      mpz_mod (r, r, my);

      if (quo)                  /* now 0 <= r < 2^WANTED_BITS*Y */
        {
          mpz_fdiv_q_2exp (my, my, WANTED_BITS);   /* back to Y */
          mpz_tdiv_qr (mx, r, r, my);
          /* oldr = mx*my + newr */
          *quo = mpz_get_si (mx);
          q_is_odd = *quo & 1;
        }
      else if (rnd_q == MPFR_RNDN) /* now 0 <= r < 2Y in the remainder case */
        {
          mpz_fdiv_q_2exp (my, my, 1);     /* back to Y */
          /* least significant bit of q */
          q_is_odd = mpz_cmpabs (r, my) >= 0;
          if (q_is_odd)
            mpz_sub (r, r, my);
        }
      /* now 0 <= |r| < |my|, and if needed,
         q_is_odd is the least significant bit of q */
    }

  if (mpz_cmp_ui (r, 0) == 0)
    {
      inex = mpfr_set_ui (rem, 0, MPFR_RNDN);
      /* take into account sign of x */
      if (signx < 0)
        mpfr_neg (rem, rem, MPFR_RNDN);
    }
  else
    {
      if (rnd_q == MPFR_RNDN)
        {
          /* FIXME: the comparison 2*r < my could be done more efficiently
             at the mpn level */
          mpz_mul_2exp (r, r, 1);
          /* if tiny=1, we should compare r with my*2^(ey-ex) */
          if (tiny)
            {
              if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) <
                  ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
                compare = 0; /* r*2^ex < my*2^ey */
              else
                {
                  mpz_mul_2exp (my, my, ey - ex);
                  compare = mpz_cmpabs (r, my);
                }
            }
          else
            compare = mpz_cmpabs (r, my);
          mpz_fdiv_q_2exp (r, r, 1);
          compare = ((compare > 0) ||
                     ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd));
          /* if compare != 0, we need to subtract my to r, and add 1 to quo */
          if (compare)
            {
              mpz_sub (r, r, my);
              if (quo && (rnd_q == MPFR_RNDN))
                *quo += 1;
            }
        }
      /* take into account sign of x */
      if (signx < 0)
        mpz_neg (r, r);
      inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd);
    }

  if (quo)
    *quo *= sign;

  mpz_clear (mx);
  mpz_clear (my);
  mpz_clear (r);

  return inex;
}
Ejemplo n.º 20
0
// Algorithm 13.2 [PDF page 17](http://cr.yp.to/lineartime/dcba-20040404.pdf)
//
// See [appendcb test](test-appendcb.html) for basic usage.
void append_cb(mpz_array *out, const mpz_t a, const mpz_t b) {

	mpz_t r, g, h, c, c0, x, y, d, b1, b2, a1;
	unsigned long long n;

	/* gmp_printf("enter append_cb(%Zd, %Zd)\n", a, b); */

	// **Step 1**
	//
	// If `b == 1` and `a == 1` add `a` to the array. If `b == 1` return.
	// This is the break condition of the recursive function.
	if (mpz_cmp_ui(b, 1) == 0) {
		if (mpz_cmp_ui(a, 1) != 0)  {
			array_add(out, a);
		}
		return;
	}

	mpz_init(r);
	mpz_init(g);
	mpz_init(a1);

	// **Step 2**
	//
	// Store ppi in `a1` and ppo in `r`. Use `a1` and not `a` to keep the input `const`
	// and handle the case that one parameter is used twice.
	ppi_ppo(a1, r, a, b);

	// **Step 3**
	//
	// If `r` (ppo) is **not** one add it to the array.
	if (mpz_cmp_ui(r, 1) != 0) {
		array_add(out, r);
	}

	mpz_init(h);
	mpz_init(c);

	// **Step 4**
	//
	// Caluclate the gcd, ppg and pple.
	gcd_ppg_pple(g, h, c, a1, b);

	// **Step 5**
	//
	// Store pple in `c0` and `x`.
	mpz_init_set(c0, c);
	mpz_init_set(x, c0);

	// **Step 6**
	//
	// Set `n` to one.
	n = 1;

	mpz_init(b1);
	mpz_init(b2);
	mpz_init(d);
	mpz_init(y);

	// Start while loop to be able to return to step 7.
	while(1) {
		// **Step 7**
		//
		// Compute (g, h, c) ← (gcd,ppg,pple)(h,g^2)
		mpz_mul(b1, g, g);
		mpz_set(b2, h);
		gcd_ppg_pple(g, h, c, b2, b1);

		// **Step 8**
		//
		// Compute d ← gcd(c, b)
		mpz_gcd(d, c, b);

		// **Step 9**
		//
		// Set x ← xd
		mpz_mul(x, x, d);

		// **Sep 10**
		//
		// Compute y ← d^2^	n−1.
		mpz_set(y, d);
		two_power(y, n - 1);

		// **Sep 11**
		//
		// Recursively apply (c/y,d).
		mpz_fdiv_q(b1, c, y);

		/* gmp_printf("rec call append_cb(%Zd, %Zd)\n", b1, d); */

		append_cb(out, b1, d);

		// **Sep 12**
		//
		// If h is not 1: Set n ← n+1. Return to Step 7.
		if (mpz_cmp_ui(h, 1) == 0) break;
		n = n + 1;
	}

	// **Step 13**
	//
	// Recursively apply (b/x, c0).
	mpz_fdiv_q(b1, b, x);
	append_cb(out, b1, c0);

	// Free the memory.
	mpz_clear(r);
	mpz_clear(g);
	mpz_clear(h);
	mpz_clear(c);
	mpz_clear(c0);
	mpz_clear(x);
	mpz_clear(y);
	mpz_clear(d);
	mpz_clear(b1);
	mpz_clear(b2);
	mpz_clear(a1);
}
Ejemplo n.º 21
0
static void zp_mul(element_ptr n, element_ptr a, element_ptr b) {
  mpz_mul(n->data, a->data, b->data);
  mpz_mod(n->data, n->data, n->field->order);
}
Ejemplo n.º 22
0
// The result is stored in the parameter `mpz_t rot`.
// This parameter has to be **initialized** on invocation.
// The function operates on a single (input & output) integer.
//
// Algorithm 10.1 [PDF page 13](http://cr.yp.to/lineartime/dcba-20040404.pdf)
//
// See [twopower test](test-twopower.html) for basic usage.
void two_power(mpz_t rot, unsigned long long n) {
	while(n > 0) {
		mpz_mul(rot, rot, rot);
		n--;
	}
}
Ejemplo n.º 23
0
int main(int argc, char* argv[]) {
  int i;
  u8 ecount_buf[0x10], iv[0x10];
  size_t countp;
  int num;

  if(argc < 4) {
    printf("usage: %s input.elf output.self keytype keysuffix\n", argv[0]);
    return -1;
  }

  Elf64_Ehdr input_elf_header;
  FILE *input_elf_file = fopen(argv[1], "rb");

  fseek(input_elf_file, 0, SEEK_END);
  int nlen = ftell(input_elf_file);
  fseek(input_elf_file, 0, SEEK_SET);
  input_elf_data = (u8*)malloc(nlen);
  fread(input_elf_data, 1, nlen, input_elf_file);
  fclose(input_elf_file);

  memcpy(&input_elf_header, input_elf_data, sizeof(input_elf_header));


  FILE *output_self_file = fopen(argv[2], "wb");


  printf("ELF header size @ %x\n", get_u16(&(input_elf_header.e_ehsize)) );
  printf("%d program headers @ %64llX\n", get_u16(&(input_elf_header.e_phnum)), get_u64(&(input_elf_header.e_phoff)));
  printf("%d section headers @ %64llX\n", get_u16(&(input_elf_header.e_shnum)), get_u64(&(input_elf_header.e_shoff)));

  Self_Shdr output_self_header; memset(&output_self_header, 0, sizeof(output_self_header));
  Self_Ehdr output_extended_self_header; memset(&output_extended_self_header, 0, sizeof(output_extended_self_header));
  Self_Ihdr output_self_info_header; memset(&output_self_info_header, 0, sizeof(output_self_info_header));

  set_u32(&(output_self_header.s_magic), 0x53434500);
  set_u32(&(output_self_header.s_hdrversion), 2);
  set_u16(&(output_self_header.s_flags), 1);
  set_u16(&(output_self_header.s_hdrtype), 1);
  // header size and file size aren't known yet

  set_u64(&(output_extended_self_header.e_magic), 3);
  set_u64(&(output_extended_self_header.e_ihoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr));
  set_u64(&(output_extended_self_header.e_ehoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr));
  set_u64(&(output_extended_self_header.e_phoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)+get_u64(&(input_elf_header.e_phoff)));
  // section header offset unknown

  set_u64(&(output_self_info_header.i_authid), 0x1070000500000001LL);
  set_u32(&(output_self_info_header.i_magic), 0x01000002);
  set_u32(&(output_self_info_header.i_apptype), 4);
  set_u64(&(output_self_info_header.i_version), 0x0003000000000000LL);

// set static data
  int phnum = get_u16(&(input_elf_header.e_phnum));
  u32 phsize = (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); 

  Self_SDKversion sdkversion;
  Self_Cflags cflags;
  memcpy(&sdkversion, sdkversion_static, sizeof(Self_SDKversion));
  memcpy(&cflags, cflags_static, sizeof(Self_Cflags));

  int running_size = (sizeof(output_self_header)+sizeof(output_extended_self_header)+sizeof(output_self_info_header)+sizeof(input_elf_header)+phsize+0xF)&0xFFFFFFF0;

  set_u64(&(output_extended_self_header.e_pmoff), running_size); running_size += phnum*sizeof(Self_PMhdr);
  set_u64(&(output_extended_self_header.e_svoff), running_size); running_size += sizeof(Self_SDKversion);
  set_u64(&(output_extended_self_header.e_cfoff), running_size); running_size += sizeof(Self_Cflags);
  set_u64(&(output_extended_self_header.e_cfsize), sizeof(Self_Cflags));
  set_u32(&(output_self_header.s_esize), running_size - sizeof(output_self_header));

  printf("running size is %X\n", running_size);

  int maxsection = 6;

  running_size += sizeof(metadata_crypt_header)+sizeof(segment_certification_header)+maxsection*(sizeof(segment_certification_segment)+sizeof(segment_certification_crypt_encrypted))+sizeof(segment_certification_sign)+sizeof(nubpadding_static);

  printf("running size is %X\n", running_size);

  set_u64(&(output_self_header.s_shsize), running_size);

// init randomness
  gmp_randstate_t r_state;
  gmp_randinit_default(r_state);
  gmp_randseed_ui(r_state, time(NULL));

// loop through the sections

  segment_certification_header segment_header; memset(&segment_header, 0, sizeof(segment_header));
  Self_Section first_section;
  Self_Section* section_ptr = &first_section;

  set_u64(&(segment_header.signature_offset), running_size-sizeof(segment_certification_sign));
  set_u32(&(segment_header.unknown1), 1);
  set_u32(&(segment_header.segment_count), phnum);
  set_u32(&(segment_header.crypt_len), (phnum*sizeof(segment_certification_crypt_encrypted))/0x10);

  Elf64_Phdr* elf_segment = (Elf64_Phdr*)(&input_elf_data[get_u64(&(input_elf_header.e_phoff))]);

  for(i=0;i<phnum;i++) {
    memset(section_ptr, 0, sizeof(Self_Section));

    //set_u64(&(section_ptr->enc_segment.segment_offset), get_u64(&(elf_segment->p_vaddr)));
    set_u64(&(section_ptr->enc_segment.segment_offset), running_size);
    set_u64(&(section_ptr->enc_segment.segment_size), get_u64(&(elf_segment->p_filesz)));
    set_u32(&(section_ptr->enc_segment.segment_crypt_flag), 2);

    set_u32(&(section_ptr->enc_segment.segment_sha1_index), i*8);
    set_u32(&(section_ptr->enc_segment.segment_erk_index), i*8+6);
    set_u32(&(section_ptr->enc_segment.segment_riv_index), i*8+7);

    set_u32(&(section_ptr->enc_segment.segment_number), i);
    set_u32(&(section_ptr->enc_segment.unknown2), 2);
    set_u32(&(section_ptr->enc_segment.unknown3), 3);
    set_u32(&(section_ptr->enc_segment.unknown4), 2);

    set_u64(&(section_ptr->pmhdr.pm_offset), running_size);
    set_u64(&(section_ptr->pmhdr.pm_size), get_u64(&(elf_segment->p_filesz)));
    set_u32(&(section_ptr->pmhdr.pm_compressed), 1);
    set_u32(&(section_ptr->pmhdr.pm_encrypted), 1);

    mpz_t riv, erk, hmac;
    mpz_init(riv); mpz_init(erk); mpz_init(hmac);
    mpz_urandomb(erk, r_state, 128);
    mpz_urandomb(riv, r_state, 128);
    mpz_urandomb(hmac, r_state, 512);

    mpz_export(section_ptr->crypt_segment.erk, &countp, 1, 0x10, 1, 0, erk);
    mpz_export(section_ptr->crypt_segment.riv, &countp, 1, 0x10, 1, 0, riv);
    mpz_export(section_ptr->crypt_segment.hmac, &countp, 1, 0x40, 1, 0, hmac);

    section_ptr->rlen = get_u64(&(elf_segment->p_filesz));
    section_ptr->len = ((section_ptr->rlen)+0xF)&0xFFFFFFF0;
    section_ptr->data = (u8*)malloc(section_ptr->len);

    u32 in_data_offset = get_u64(&(elf_segment->p_offset)); // + get_u16(&(input_elf_header.e_ehsize)) + (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum)));
    u8* in_data = &input_elf_data[in_data_offset];

    printf("processing segment %d with len %x offset %x\n", i, section_ptr->len, in_data_offset);
    //hexdump((u8*)elf_segment, sizeof(Elf64_Phdr));


    /*SHA_CTX c;
    SHA1_ghetto_init(&c, section_ptr->crypt_segment.hmac);
    SHA1_Update(&c, in_data, section_ptr->rlen);
    SHA1_ghetto_final(section_ptr->crypt_segment.sha1, &c, section_ptr->crypt_segment.hmac);*/
    sha1_hmac(section_ptr->crypt_segment.hmac, in_data, section_ptr->rlen, section_ptr->crypt_segment.sha1);

    memset(ecount_buf, 0, 16); num=0;
    AES_set_encrypt_key(section_ptr->crypt_segment.erk, 128, &aes_key);
    memcpy(iv, section_ptr->crypt_segment.riv, 16);

    #ifdef NO_CRYPT
      memcpy(section_ptr->data, in_data, section_ptr->len);   
    #else
      //AES_ctr128_encrypt(in_data, section_ptr->data, section_ptr->len, &aes_key, iv, ecount_buf, &num);
      aes128ctr((u8*)&aes_key, iv, in_data, section_ptr->len, section_ptr->data);
    #endif

    running_size += section_ptr->len;

// next
    if(i != phnum-1) {
      section_ptr->next_section = malloc(sizeof(Self_Section));
    }
    elf_segment += 1;  // 1 is sizeof(Elf64_Phdr)
    section_ptr = section_ptr->next_section;
  }

  printf("segment processing done\n");


// section table offset
  set_u64(&(output_extended_self_header.e_shoff), running_size);

// lay out the metadata
  u8 metadata[0x2000]; memset(metadata, 0, 0x2000);
  u32 metadata_len = 0;

  memcpy(&metadata[metadata_len], &output_self_header, sizeof(output_self_header)); metadata_len += sizeof(output_self_header);
  memcpy(&metadata[metadata_len], &output_extended_self_header, sizeof(output_extended_self_header)); metadata_len += sizeof(output_extended_self_header);
  memcpy(&metadata[metadata_len], &output_self_info_header, sizeof(output_self_info_header)); metadata_len += sizeof(output_self_info_header);
  memcpy(&metadata[metadata_len], &input_elf_header, sizeof(input_elf_header)); metadata_len += sizeof(input_elf_header);
  memcpy(&metadata[metadata_len], &input_elf_data[get_u64(&(input_elf_header.e_phoff))], phsize); metadata_len += phsize;
  metadata_len = (metadata_len+0xF)&0xFFFFFFF0;

  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->pmhdr), sizeof(section_ptr->pmhdr)); metadata_len += sizeof(section_ptr->pmhdr);
    section_ptr = section_ptr->next_section;
  }

  memcpy(&metadata[metadata_len], &sdkversion, sizeof(sdkversion)); metadata_len += sizeof(sdkversion);
  memcpy(&metadata[metadata_len], &cflags, sizeof(cflags)); metadata_len += sizeof(cflags);

  printf("top half of metadata ready\n");

// generate metadata encryption keys
  mpz_t bigriv, bigerk;
  mpz_init(bigriv); mpz_init(bigerk);
  mpz_urandomb(bigerk, r_state, 128);
  mpz_urandomb(bigriv, r_state, 128);

  metadata_crypt_header md_header;

  mpz_export(md_header.erk, &countp, 1, 0x10, 1, 0, bigerk);
  mpz_export(md_header.riv, &countp, 1, 0x10, 1, 0, bigriv);

  memcpy(&metadata[metadata_len], &md_header, sizeof(md_header)); metadata_len += sizeof(md_header);
  memcpy(&metadata[metadata_len], &segment_header, sizeof(segment_header)); metadata_len += sizeof(segment_header);

// copy section data
  int csection;

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->enc_segment), sizeof(section_ptr->enc_segment)); metadata_len += sizeof(section_ptr->enc_segment);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != NULL) {
    memcpy(&metadata[metadata_len], &(section_ptr->crypt_segment), sizeof(section_ptr->crypt_segment)); metadata_len += sizeof(section_ptr->crypt_segment);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

// nubpadding time
  memcpy(&metadata[metadata_len], nubpadding_static, sizeof(nubpadding_static)); metadata_len += sizeof(nubpadding_static);

// sign shit
  u8 digest[0x14];
  sha1(metadata, metadata_len, digest);
  printf("metadata len is %X\n", metadata_len);
  //hexdump(metadata, metadata_len);
  //hexdump_nl(digest, 0x14);
  segment_certification_sign all_signed;
  memset(&all_signed, 0, sizeof(all_signed));

#ifdef GEOHOT_SIGN
  mpz_t n,k,da,kinv,r,cs,z;
  mpz_init(n); mpz_init(k); mpz_init(da); mpz_init(r); mpz_init(cs); mpz_init(z); mpz_init(kinv);
  mpz_import(r, 0x14, 1, 1, 0, 0, appold_R);
  mpz_import(n, 0x14, 1, 1, 0, 0, appold_n);
  mpz_import(k, 0x14, 1, 1, 0, 0, appold_K);
  mpz_import(da, 0x14, 1, 1, 0, 0, appold_Da);
  mpz_invert(kinv, k, n);

  mpz_import(z, 0x14, 1, 1, 0, 0, digest);

  mpz_mul(cs, r, da); mpz_mod(cs, cs, n);
  mpz_add(cs, cs, z); mpz_mod(cs, cs, n);
  mpz_mul(cs, cs, kinv); mpz_mod(cs, cs, n);

  mpz_export(all_signed.R, &countp, 1, 0x14, 1, 0, r);
  mpz_export(all_signed.S, &countp, 1, 0x14, 1, 0, cs);
#else
  get_keys(argv[3], argv[4]);
  //ecdsa_set_curve(appnew_ctype);
  //ecdsa_set_pub(appnew_pub);
  //ecdsa_set_priv(appnew_priv);
  //ecdsa_sign(digest, all_signed.R, all_signed.S);
#endif

  memcpy(&metadata[metadata_len], &all_signed, sizeof(all_signed)); metadata_len += sizeof(all_signed);

// encrypt metadata
  int metadata_offset = get_u32(&(output_self_header.s_esize)) + sizeof(Self_Shdr);

#ifndef NO_CRYPT
  /*memset(ecount_buf, 0, 16); num=0;
  AES_set_encrypt_key(&metadata[metadata_offset], 128, &aes_key);
  memcpy(iv, &metadata[metadata_offset+0x20], 16);
  //AES_ctr128_encrypt(&metadata[0x40+metadata_offset], &metadata[0x40+metadata_offset], metadata_len-metadata_offset-0x40, &aes_key, iv, ecount_buf, &num);
  aes128ctr(&metadata[0x20+metadata_offset], &metadata[0x40+metadata_offset], &metadata[0x60+metadata_offset], metadata_len-metadata_offset-0x60, &metadata[0x60+metadata_offset]);
  printf("encrypted metadata\n");

  //AES_set_encrypt_key(appold_erk, 256, &aes_key);
  //memcpy(iv, appold_riv, 16);
  AES_set_encrypt_key(appnew_erk, 256, &aes_key);
  memcpy(iv, appnew_riv, 16);
  //AES_cbc_encrypt(&metadata[metadata_offset], &metadata[metadata_offset], 0x40, &aes_key, iv, AES_ENCRYPT);
  aes256cbc_enc(appnew_erk, appnew_riv, &metadata[metadata_offset], 0x40, &metadata[metadata_offset]);

  printf("encrypted keys\n");*/
  //k.key = appnew_erk;
  //k.iv = appnew_riv;
  sce_encrypt_header(metadata, &ks);
#endif

// write the output self
  fwrite(metadata, 1, metadata_len, output_self_file);

  csection = 0;
  section_ptr = &first_section;
  while(section_ptr != 0) {
    printf("writing section with size %X\n", section_ptr->len);
    fwrite(section_ptr->data, 1, section_ptr->len, output_self_file);
    section_ptr = section_ptr->next_section;
    if((++csection) == maxsection) break;
  }

  fwrite(&input_elf_data[get_u64(&(input_elf_header.e_shoff))], sizeof(Elf64_Shdr), get_u16(&(input_elf_header.e_shnum)), output_self_file);

  fclose(output_self_file);
}
Ejemplo n.º 24
0
static PyObject *
GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args)
{
    /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
     * calculate v[k] (modulo n) of Lucas V sequence for p,q.
     * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
     */

    MPZ_Object *result = 0, *p, *q, *k, *n;

    size_t s = 0, j = 0;
    mpz_t vl, vh, ql, qh, tmp;

    if (PyTuple_Size(args) != 4) {
        TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
        return NULL;
    }

    mpz_init(vl);
    mpz_init(vh);
    mpz_init(ql);
    mpz_init(qh);
    mpz_init(tmp);

    p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
    q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
    k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
    n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL);
    if (!p || !q || !k || !n) {
        TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
        goto cleanup;
    }

    /* Check if p*p - 4*q == 0. */

    mpz_mul(tmp, p->z, p->z);
    mpz_mul_ui(qh, q->z, 4);
    mpz_sub(tmp, tmp, qh);
    if (mpz_sgn(tmp) == 0) {
        VALUE_ERROR("invalid values for p,q in lucasv_mod()");
        goto cleanup;
    }

    /* Check if k < 0. */

    if (mpz_sgn(k->z) < 0) {
        VALUE_ERROR("invalid value for k in lucasv_mod()");
        goto cleanup;
    }

    /* Check if n > 0. */

    if (mpz_sgn(n->z) <= 0) {
        VALUE_ERROR("invalid value for n in lucasv_mod()");
        goto cleanup;
    }

    mpz_set_si(vl, 2);
    mpz_set(vh, p->z);
    mpz_set_si(ql, 1);
    mpz_set_si(qh, 1);
    mpz_set_si(tmp,0);

    s = mpz_scan1(k->z, 0);
    for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
        /* ql = ql*qh (mod n) */
        mpz_mul(ql, ql, qh);
        mpz_mod(ql, ql, n->z);
        if (mpz_tstbit(k->z,j) == 1) {
            /* qh = ql*q */
            mpz_mul(qh, ql, q->z);

            /* vl = vh*vl - p*ql (mod n) */
            mpz_mul(vl, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vl, vl, tmp);
            mpz_mod(vl, vl, n->z);

            /* vh = vh*vh - 2*qh (mod n) */
            mpz_mul(vh, vh, vh);
            mpz_mul_si(tmp, qh, 2);
            mpz_sub(vh, vh, tmp);
            mpz_mod(vh, vh, n->z);
        }
        else {
            /* qh = ql */
            mpz_set(qh, ql);

            /* vh = vh*vl - p*ql (mod n) */
            mpz_mul(vh, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vh, vh, tmp);
            mpz_mod(vh, vh, n->z);

            /* vl = vl*vl - 2*ql (mod n) */
            mpz_mul(vl, vl, vl);
            mpz_mul_si(tmp, ql, 2);
            mpz_sub(vl, vl, tmp);
            mpz_mod(vl, vl, n->z);
        }
    }
    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    /* qh = ql*q */
    mpz_mul(qh, ql, q->z);

    /* vl = vh*vl - p*ql */
    mpz_mul(vl, vh, vl);
    mpz_mul(tmp, ql, p->z);
    mpz_sub(vl, vl, tmp);

    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    for (j = 1; j <= s; j++) {
        /* vl = vl*vl - 2*ql (mod n) */
        mpz_mul(vl, vl, vl);
        mpz_mul_si(tmp, ql, 2);
        mpz_sub(vl, vl, tmp);
        mpz_mod(vl, vl, n->z);

        /* ql = ql*ql (mod n) */
        mpz_mul(ql, ql, ql);
        mpz_mod(ql, ql, n->z);
    }

    if (!(result = GMPy_MPZ_New(NULL)))
        goto cleanup;

    /* vl contains our return value */
    mpz_mod(result->z, vl, n->z);

  cleanup:
    mpz_clear(vl);
    mpz_clear(vh);
    mpz_clear(ql);
    mpz_clear(qh);
    mpz_clear(tmp);
    Py_XDECREF((PyObject*)p);
    Py_XDECREF((PyObject*)q);
    Py_XDECREF((PyObject*)k);
    Py_XDECREF((PyObject*)n);

    return (PyObject*)result;
}
Ejemplo n.º 25
0
Archivo: ecpp.c Proyecto: xcvii/gkecpp
static int ec_add(mpz_t xr, mpz_t yr, mpz_t x1, mpz_t y1, int z1,
    mpz_t x2, mpz_t y2, int z2, unsigned long n, mpz_t a)
{
  /* add two points of an elliptic curve by matching an addition rule,
   * in non-trivial cases producing a secant connecting the points (or a
   * tangent in case of overlapping points), finding the third intersection
   * point and mirroring it to the x axis
   */

  if (0 == z1 && 0 == z2) /* 0 + 0 = 0 */
  {
    mpz_set_ui(xr, 0);
    mpz_set_ui(yr, 1);

    return 0;
  }
  else if (0 == z2) /* P + 0 = P */
  {
    mpz_set(xr, x1);
    mpz_set(yr, y1);

    return 1;
  }
  else if (0 == z1) /* 0 + Q = Q */
  {
    mpz_set(xr, x2);
    mpz_set(yr, y2);

    return 1;
  }
  else if (0 != mpz_cmp(x1, x2)) /* P + Q, P != Q */
  {
    /*   m = (y2 - y1) / (x2 - x1)
     *   xr = m^2 - x1 - x2
     *   yr = m * (x1 - x3) - y1
     */
    mpz_t xt, yt, tmp;

    mpz_init(xt);
    mpz_init(yt);
    mpz_init_set_ui(tmp, n);

    mpz_sub(yt, y2, y1);
    mpz_sub(xt, x2, x1);

    {
      /* multiplicative inverse over GF(n) using the Extended Euclidean
       * Algorithm
       *   1 = g = s * (x2 - x1) + t * n = s * (x2 - x1)
       */

      mpz_t s, t, g;

      mpz_init(s);
      mpz_init(t);
      mpz_init(g);

      mpz_gcdext(g, s, t, xt, tmp);
      mpz_mul(xt, s, yt);
      mpz_mod_ui(xt, xt, n);
      mpz_set(yt, xt);

      mpz_clear(s);
      mpz_clear(t);
      mpz_clear(g);
    }

    mpz_mul(xt, xt, xt);
    mpz_sub(xt, xt, x1);
    mpz_sub(xt, xt, x2);
    mpz_mod_ui(xt, xt, n);

    mpz_sub(tmp, x1, xt);
    mpz_mul(yt, yt, tmp);
    mpz_sub(yt, yt, y1);
    mpz_mod_ui(yt, yt, n);

    mpz_set(xr, xt);
    mpz_set(yr, yt);

    mpz_clear(xt);
    mpz_clear(yt);
    mpz_clear(tmp);

    return 1;
  }
  else if (0 != mpz_cmp(y1, y2)) /* P + (-P) = 0 */
  {
    mpz_set_ui(xr, 0);
    mpz_set_ui(yr, 1);

    return 0;
  }
  else /* P + P */
  {
    /*   m = (3 * x1^2 + a) / (2 * y1)
     *   xr = m^2 - 2 * x1
     *   yr = m * (x1 - x3) - y1
     */
    mpz_t xt, yt, tmp;

    mpz_init(xt);
    mpz_init(yt);

    mpz_init_set_ui(tmp, n);

    mpz_mul(xt, x1, x1);
    mpz_mul_ui(xt, xt, 3);
    mpz_add(xt, xt, a);
    mpz_add(yt, y1, y1);

    {
      /* multiplicative inverse over GF(n) using the Extended Euclidean
       * Algorithm
       *   1 = g = s * (2 * y1) + t * n = s * (2 * y1)
       */

      mpz_t s, t, g;

      mpz_init(s);
      mpz_init(t);
      mpz_init(g);

      mpz_gcdext(g, s, t, yt, tmp);
      mpz_mul(xt, s, xt);
      mpz_mod_ui(xt, xt, n);
      mpz_set(yt, xt);

      mpz_clear(s);
      mpz_clear(t);
      mpz_clear(g);
    }

    mpz_mul(xt, xt, xt);
    mpz_sub(xt, xt, x1);
    mpz_sub(xt, xt, x1);
    mpz_mod_ui(xt, xt, n);

    mpz_sub(tmp, x1, xt);
    mpz_mul(yt, yt, tmp);
    mpz_sub(yt, yt, y1);
    mpz_mod_ui(yt, yt, n);

    mpz_set(xr, xt);
    mpz_set(yr, yt);

    mpz_clear(xt);
    mpz_clear(yt);
    mpz_clear(tmp);

    return 1;
  }
}
Ejemplo n.º 26
0
int
rsa_generate_keypair(struct rsa_public_key *pub,
		     struct rsa_private_key *key,
		     void *random_ctx, nettle_random_func *random,
		     void *progress_ctx, nettle_progress_func *progress,
		     unsigned n_size,
		     unsigned e_size)
{
  mpz_t p1;
  mpz_t q1;
  mpz_t phi;
  mpz_t tmp;

  if (e_size)
    {
      /* We should choose e randomly. Is the size reasonable? */
      if ((e_size < 16) || (e_size >= n_size) )
	return 0;
    }
  else
    {
      /* We have a fixed e. Check that it makes sense */

      /* It must be odd */
      if (!mpz_tstbit(pub->e, 0))
	return 0;

      /* And 3 or larger */
      if (mpz_cmp_ui(pub->e, 3) < 0)
	return 0;

      /* And size less than n */
      if (mpz_sizeinbase(pub->e, 2) >= n_size)
	return 0;
    }

  if (n_size < RSA_MINIMUM_N_BITS)
    return 0;
  
  mpz_init(p1); mpz_init(q1); mpz_init(phi); mpz_init(tmp);

  /* Generate primes */
  for (;;)
    {
      /* Generate p, such that gcd(p-1, e) = 1 */
      for (;;)
	{
	  nettle_random_prime(key->p, (n_size+1)/2, 1,
			      random_ctx, random,
			      progress_ctx, progress);

	  mpz_sub_ui(p1, key->p, 1);
      
	  /* If e was given, we must chose p such that p-1 has no factors in
	   * common with e. */
	  if (e_size)
	    break;
	  
	  mpz_gcd(tmp, pub->e, p1);

	  if (mpz_cmp_ui(tmp, 1) == 0)
	    break;
	  else if (progress) progress(progress_ctx, 'c');
	} 

      if (progress)
	progress(progress_ctx, '\n');
      
      /* Generate q, such that gcd(q-1, e) = 1 */
      for (;;)
	{
	  nettle_random_prime(key->q, n_size/2, 1,
			      random_ctx, random,
			      progress_ctx, progress);

	  /* Very unlikely. */
	  if (mpz_cmp (key->q, key->p) == 0)
	    continue;

	  mpz_sub_ui(q1, key->q, 1);
      
	  /* If e was given, we must chose q such that q-1 has no factors in
	   * common with e. */
	  if (e_size)
	    break;
	  
	  mpz_gcd(tmp, pub->e, q1);

	  if (mpz_cmp_ui(tmp, 1) == 0)
	    break;
	  else if (progress) progress(progress_ctx, 'c');
	}

      /* Now we have the primes. Is the product of the right size? */
      mpz_mul(pub->n, key->p, key->q);

      assert (mpz_sizeinbase(pub->n, 2) == n_size);

      if (progress)
	progress(progress_ctx, '\n');

      /* c = q^{-1} (mod p) */
      if (mpz_invert(key->c, key->q, key->p))
	/* This should succeed everytime. But if it doesn't,
	 * we try again. */
	break;
      else if (progress) progress(progress_ctx, '?');
    }

  mpz_mul(phi, p1, q1);
  
  /* If we didn't have a given e, generate one now. */
  if (e_size)
    {
      int retried = 0;
      for (;;)
	{
	  nettle_mpz_random_size(pub->e,
				 random_ctx, random,
				 e_size);
	
	  /* Make sure it's odd and that the most significant bit is
	   * set */
	  mpz_setbit(pub->e, 0);
	  mpz_setbit(pub->e, e_size - 1);

	  /* Needs gmp-3, or inverse might be negative. */
	  if (mpz_invert(key->d, pub->e, phi))
	    break;

	  if (progress) progress(progress_ctx, 'e');
	  retried = 1;
	}
      if (retried && progress)
	progress(progress_ctx, '\n');	
    }
  else
    {
      /* Must always succeed, as we already that e
       * doesn't have any common factor with p-1 or q-1. */
      int res = mpz_invert(key->d, pub->e, phi);
      assert(res);
    }

  /* Done! Almost, we must compute the auxillary private values. */
  /* a = d % (p-1) */
  mpz_fdiv_r(key->a, key->d, p1);

  /* b = d % (q-1) */
  mpz_fdiv_r(key->b, key->d, q1);

  /* c was computed earlier */

  pub->size = key->size = (n_size + 7) / 8;
  assert(pub->size >= RSA_MINIMUM_N_OCTETS);
  
  mpz_clear(p1); mpz_clear(q1); mpz_clear(phi); mpz_clear(tmp);

  return 1;
}
Ejemplo n.º 27
0
void
test_rsa_key(struct rsa_public_key *pub,
	     struct rsa_private_key *key)
{
  mpz_t tmp;
  mpz_t phi;
  
  mpz_init(tmp); mpz_init(phi);
  
  if (verbose)
    {
      /* FIXME: Use gmp_printf */
      fprintf(stderr, "Public key: n=");
      mpz_out_str(stderr, 16, pub->n);
      fprintf(stderr, "\n    e=");
      mpz_out_str(stderr, 16, pub->e);

      fprintf(stderr, "\n\nPrivate key: d=");
      mpz_out_str(stderr, 16, key->d);
      fprintf(stderr, "\n    p=");
      mpz_out_str(stderr, 16, key->p);
      fprintf(stderr, "\n    q=");
      mpz_out_str(stderr, 16, key->q);
      fprintf(stderr, "\n    a=");
      mpz_out_str(stderr, 16, key->a);
      fprintf(stderr, "\n    b=");
      mpz_out_str(stderr, 16, key->b);
      fprintf(stderr, "\n    c=");
      mpz_out_str(stderr, 16, key->c);
      fprintf(stderr, "\n\n");
    }

  /* Check n = p q */
  mpz_mul(tmp, key->p, key->q);
  ASSERT (mpz_cmp(tmp, pub->n)== 0);

  /* Check c q = 1 mod p */
  mpz_mul(tmp, key->c, key->q);
  mpz_fdiv_r(tmp, tmp, key->p);
  ASSERT (mpz_cmp_ui(tmp, 1) == 0);

  /* Check ed = 1 (mod phi) */
  mpz_sub_ui(phi, key->p, 1);
  mpz_sub_ui(tmp, key->q, 1);

  mpz_mul(phi, phi, tmp);

  mpz_mul(tmp, pub->e, key->d);
  mpz_fdiv_r(tmp, tmp, phi);
  ASSERT (mpz_cmp_ui(tmp, 1) == 0);

  /* Check a e = 1 (mod (p-1) ) */
  mpz_sub_ui(phi, key->p, 1);
  mpz_mul(tmp, pub->e, key->a);
  mpz_fdiv_r(tmp, tmp, phi);
  ASSERT (mpz_cmp_ui(tmp, 1) == 0);
  
  /* Check b e = 1 (mod (q-1) ) */
  mpz_sub_ui(phi, key->q, 1);
  mpz_mul(tmp, pub->e, key->b);
  mpz_fdiv_r(tmp, tmp, phi);
  ASSERT (mpz_cmp_ui(tmp, 1) == 0);
  
  mpz_clear(tmp); mpz_clear(phi);
}
Ejemplo n.º 28
0
int
main(int argc, char *argv[])
{
    KryState state = STATE_BADARG;
    long mod_bits;

    if (argc == 3 && !strcmp(argv[1], "-g")) {
        // Key generation
        state = STATE_KEYGEN;
        mod_bits = strtol(argv[2], NULL, 10);
        if (mod_bits < 16) {
            state = STATE_BADARG;
            fprintf(stderr, "Too small key length\n");
        }
    } else if (argc == 5 && !strcmp(argv[1], "-e")) {
        // Encryption
        state = STATE_ENCRYPTION;
    } else if (argc == 5 && !strcmp(argv[1], "-d")) {
        // Decryption
        state = STATE_DECRYPTION;
    } else if (argc == 5 && !strcmp(argv[1], "-b")) {
        // RSA cracking
        state = STATE_CRACKING;
    }

    if (state == STATE_BADARG) {
        // Someting is messed up
        print_help(argv[0]);
        return EXIT_FAILURE;
    }

    // Prepare pseudo number generator stuff
    gmp_randstate_t randstate;
    gmp_randinit_default(randstate);
    //gmp_randseed_ui(randstate, 1);
    gmp_randseed_ui(randstate, time(NULL));

    int rc = EXIT_SUCCESS;
    mpz_t res;
    mpz_init(res);

    switch (state) {
        case STATE_KEYGEN: {
            mpz_t p, q, n, e;  // For d use res var
            mpz_init(p);
            mpz_init(q);
            mpz_init(n);
            mpz_init(e);
            rc = keygen(p, q, n, e, res, mod_bits, randstate);
            gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n", p, q, n, e, res);
            mpz_clear(p);
            mpz_clear(q);
            mpz_clear(n);
            mpz_clear(e);
            break;
        }

        case STATE_ENCRYPTION:
            // Argv: [2]=e; [3]=n; [4]=m;
            rc = encrypt(res, argv[2], argv[3], argv[4]);
            gmp_printf("0x%Zx\n", res);
            break;

        case STATE_DECRYPTION:
            // Argv: [2]=d; [3]=n; [4]=c;
            rc = decrypt(res, argv[2], argv[3], argv[4]);
            gmp_printf("0x%Zx\n", res);
            break;

        case STATE_CRACKING: {
            // Argv: [2]=e; [3]=n; [4]=c;
            mpz_t p, q, p_, q_, e, d;
            mpz_init(p);
            mpz_init(q);
            mpz_init(p_);
            mpz_init(q_);
            mpz_init(e);
            mpz_init(d);

            rc = factorization(p, q, argv[3]);
            if (rc != 0)
                goto cracking_cleanup;

            // phi = (p-1) * (q-1)
            mpz_sub_ui(p_, p, 1L);
            mpz_sub_ui(q_, q, 1L);
            mpz_mul(res, p_, q_);

            // d = e^1 mod phi
            mpz_set_str(e, argv[2], 0);
            modinv(d, e, res);

            rc = decrypt_mpz_d(res, d, argv[3], argv[4]);
            gmp_printf("0x%Zx 0x%Zx 0x%Zx\n", p, q, res);
        cracking_cleanup:
            mpz_clear(p);
            mpz_clear(q);
            mpz_clear(p_);
            mpz_clear(q_);
            mpz_clear(e);
            mpz_clear(d);
            break;
        }

        case STATE_BADARG:
            break;
    }

    mpz_clear(res);
    gmp_randclear(randstate);
    return rc;
}
Ejemplo n.º 29
0
void 
gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
		     mpz_t *offset_ret)
{
  int i;
  mpz_t delta;
  mpz_t tmp; 
  bool forwards;
  int cmp;

  for (i = 0; i < ar->dimen; i++)
    {
      if (ar->dimen_type[i] != DIMEN_RANGE)
	continue;

      if (ar->stride[i])
	{
	  mpz_add (section_index[i], section_index[i],
		   ar->stride[i]->value.integer);
	if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
	  forwards = true;
	else
	  forwards = false;
	}
      else
	{
	  mpz_add_ui (section_index[i], section_index[i], 1);
	  forwards = true;
	}
      
      if (ar->end[i])
	cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
      else
	cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);

      if ((cmp > 0 && forwards) || (cmp < 0 && !forwards))
	{
	  /* Reset index to start, then loop to advance the next index.  */
	  if (ar->start[i])
	    mpz_set (section_index[i], ar->start[i]->value.integer);
	  else
	    mpz_set (section_index[i], ar->as->lower[i]->value.integer);
	}
      else
	break;
    }

  mpz_set_si (*offset_ret, 0);
  mpz_init_set_si (delta, 1);
  mpz_init (tmp);
  for (i = 0; i < ar->dimen; i++)
    {
      mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer);
      mpz_mul (tmp, tmp, delta);
      mpz_add (*offset_ret, tmp, *offset_ret);

      mpz_sub (tmp, ar->as->upper[i]->value.integer, 
	       ar->as->lower[i]->value.integer);
      mpz_add_ui (tmp, tmp, 1);
      mpz_mul (delta, tmp, delta);
    }
  mpz_clear (tmp);
  mpz_clear (delta);
}
Ejemplo n.º 30
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;
}