Ejemplo n.º 1
0
PointGFp multi_exponentiate(const PointGFp& x, const BigInt& z1,
                            const PointGFp& y, const BigInt& z2)
   {
   const size_t z_bits = round_up(std::max(z1.bits(), z2.bits()), 2);

   std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);

   PointGFp x2 = x;
   x2.mult2(ws);

   const PointGFp x3(x2.plus(x, ws));

   PointGFp y2 = y;
   y2.mult2(ws);

   const PointGFp y3(y2.plus(y, ws));

   const PointGFp M[16] = {
      x.zero(),        // 0000
      x,               // 0001
      x2,              // 0010
      x3,              // 0011
      y,               // 0100
      y.plus(x, ws),   // 0101
      y.plus(x2, ws),  // 0110
      y.plus(x3, ws),  // 0111
      y2,              // 1000
      y2.plus(x, ws),  // 1001
      y2.plus(x2, ws), // 1010
      y2.plus(x3, ws), // 1011
      y3,              // 1100
      y3.plus(x, ws),  // 1101
      y3.plus(x2, ws), // 1110
      y3.plus(x3, ws), // 1111
   };

   PointGFp H = x.zero();

   for(size_t i = 0; i != z_bits; i += 2)
      {
      if(i > 0)
         {
         H.mult2(ws);
         H.mult2(ws);
         }

      const uint8_t z1_b = z1.get_substring(z_bits - i - 2, 2);
      const uint8_t z2_b = z2.get_substring(z_bits - i - 2, 2);

      const uint8_t z12 = (4*z2_b) + z1_b;

      H.add(M[z12], ws);
      }

   if(z1.is_negative() != z2.is_negative())
      H.negate();

   return H;
   }
Ejemplo n.º 2
0
PointGFp operator*(const BigInt& scalar, const PointGFp& point)
   {
   //BOTAN_ASSERT(point.on_the_curve(), "Input is on the curve");

   const CurveGFp& curve = point.get_curve();

   const size_t scalar_bits = scalar.bits();

   std::vector<BigInt> ws(9);

   if(scalar_bits <= 2)
      {
      const byte abs_val = scalar.byte_at(0);

      if(abs_val == 0)
         return PointGFp::zero_of(curve);

      PointGFp result = point;

      if(abs_val == 2)
         result.mult2(ws);

      if(scalar.is_negative())
         result.negate();

      return result;
      }

   PointGFp R[2] = { PointGFp(curve), point };

   for(size_t i = scalar_bits; i > 0; i--)
      {
      const size_t b = scalar.get_bit(i - 1);
      R[b ^ 1].add(R[b], ws);
      R[b].mult2(ws);
      }

   if(scalar.is_negative())
      R[0].negate();

   //BOTAN_ASSERT(R[0].on_the_curve(), "Output is on the curve");

   return R[0];
   }
Ejemplo n.º 3
0
PointGFp operator*(const BigInt& scalar, const PointGFp& point)
   {
   const CurveGFp& curve = point.get_curve();

   if(scalar.is_zero())
      return PointGFp(curve); // zero point

   std::vector<BigInt> ws(9);

   if(scalar.abs() <= 2) // special cases for small values
      {
      byte value = scalar.abs().byte_at(0);

      PointGFp result = point;

      if(value == 2)
         result.mult2(ws);

      if(scalar.is_negative())
         result.negate();

      return result;
      }

   const size_t scalar_bits = scalar.bits();

#if 0

   PointGFp x1 = PointGFp(curve);
   PointGFp x2 = point;

   size_t bits_left = scalar_bits;

   // Montgomery Ladder
   while(bits_left)
      {
      const bool bit_set = scalar.get_bit(bits_left - 1);

      if(bit_set)
         {
         x1.add(x2, ws);
         x2.mult2(ws);
         }
      else
         {
         x2.add(x1, ws);
         x1.mult2(ws);
         }

      --bits_left;
      }

   if(scalar.is_negative())
      x1.negate();

   return x1;

#else
   const size_t window_size = 4;

   std::vector<PointGFp> Ps(1 << window_size);
   Ps[0] = PointGFp(curve);
   Ps[1] = point;

   for(size_t i = 2; i != Ps.size(); ++i)
      {
      Ps[i] = Ps[i-1];
      Ps[i].add(point, ws);
      }

   PointGFp H(curve); // create as zero
   size_t bits_left = scalar_bits;

   while(bits_left >= window_size)
      {
      for(size_t i = 0; i != window_size; ++i)
         H.mult2(ws);

      const u32bit nibble = scalar.get_substring(bits_left - window_size,
                                                 window_size);

      H.add(Ps[nibble], ws);

      bits_left -= window_size;
      }

   while(bits_left)
      {
      H.mult2(ws);
      if(scalar.get_bit(bits_left-1))
         H.add(point, ws);

      --bits_left;
      }

   if(scalar.is_negative())
      H.negate();

   return H;
#endif
   }
Ejemplo n.º 4
0
PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in,
                                                  RandomNumberGenerator& rng)
   {
   if(scalar_in.is_negative())
      throw std::invalid_argument("Blinded_Point_Multiply scalar must be positive");

#if BOTAN_POINTGFP_SCALAR_BLINDING_BITS > 0
   // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure)
   const BigInt mask(rng, BOTAN_POINTGFP_SCALAR_BLINDING_BITS, false);
   const BigInt scalar = scalar_in + m_order * mask;
#else
   const BigInt& scalar = scalar_in;
#endif

   const size_t scalar_bits = scalar.bits();

   // Randomize each point representation (Coron's 3rd countermeasure)
   for(size_t i = 0; i != m_U.size(); ++i)
      m_U[i].randomize_repr(rng);

#if BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER
   PointGFp R = m_U.at(3*m_h + 2); // base point
   int32_t alpha = 0;

   R.randomize_repr(rng);

   /*
   Algorithm 7 from "Randomizing the Montgomery Powering Ladder"
   Duc-Phong Le, Chik How Tan and Michael Tunstall
   http://eprint.iacr.org/2015/657

   It takes a random walk through (a subset of) the set of addition
   chains that end in k.
   */
   for(size_t i = scalar_bits; i > 0; i--)
      {
      const int32_t ki = scalar.get_bit(i);

      // choose gamma from -h,...,h
      const int32_t gamma = static_cast<int32_t>((rng.next_byte() % (2*m_h))) - m_h;
      const int32_t l = gamma - 2*alpha + ki - (ki ^ 1);

      R.mult2(m_ws);
      R.add(m_U.at(3*m_h + 1 + l), m_ws);
      alpha = gamma;
      }

   const int32_t k0 = scalar.get_bit(0);
   R.add(m_U[3*m_h + 1 - alpha - (k0 ^ 1)], m_ws);

#else

   // N-bit windowing exponentiation:

   size_t windows = round_up(scalar_bits, m_h) / m_h;

   PointGFp R = m_U[0];

   if(windows > 0)
      {
      windows--;
      const u32bit nibble = scalar.get_substring(windows*m_h, m_h);
      R.add(m_U[nibble], m_ws);

      /*
      Randomize after adding the first nibble as before the addition R
      is zero, and we cannot effectively randomize the point
      representation of the zero point.
      */
      R.randomize_repr(rng);

      while(windows)
         {
         for(size_t i = 0; i != m_h; ++i)
            R.mult2(m_ws);

         const u32bit nibble = scalar.get_substring((windows-1)*m_h, m_h);
         R.add(m_U[nibble], m_ws);
         windows--;
         }
      }
#endif

   //BOTAN_ASSERT(R.on_the_curve(), "Output is on the curve");

   return R;
   }