Пример #1
0
/*
* PKCS1 Pad Operation
*/
secure_vector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
                                     size_t olen,
                                     RandomNumberGenerator& rng) const
   {
   olen /= 8;

   if(olen < 10)
      throw Encoding_Error("PKCS1: Output space too small");
   if(inlen > olen - 10)
      throw Encoding_Error("PKCS1: Input is too large");

   secure_vector<byte> out(olen);

   out[0] = 0x02;
   for(size_t j = 1; j != olen - inlen - 1; ++j)
      while(out[j] == 0)
         out[j] = rng.next_byte();
   buffer_insert(out, olen - inlen, in, inlen);

   return out;
   }
Пример #2
0
/*
* Generate a random prime
*/
BigInt random_prime(RandomNumberGenerator& rng,
                    u32bit bits, const BigInt& coprime,
                    u32bit equiv, u32bit modulo)
{
    if(bits <= 1)
        throw Invalid_Argument("random_prime: Can't make a prime of " +
                               to_string(bits) + " bits");
    else if(bits == 2)
        return ((rng.next_byte() % 2) ? 2 : 3);
    else if(bits == 3)
        return ((rng.next_byte() % 2) ? 5 : 7);
    else if(bits == 4)
        return ((rng.next_byte() % 2) ? 11 : 13);

    if(coprime <= 0)
        throw Invalid_Argument("random_prime: coprime must be > 0");
    if(modulo % 2 == 1 || modulo == 0)
        throw Invalid_Argument("random_prime: Invalid modulo value");
    if(equiv >= modulo || equiv % 2 == 0)
        throw Invalid_Argument("random_prime: equiv must be < modulo, and odd");

    while(true)
    {
        BigInt p(rng, bits);
        p.set_bit(bits - 2);
        p.set_bit(0);

        if(p % modulo != equiv)
            p += (modulo - p % modulo) + equiv;

        const u32bit sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
        SecureVector<u32bit> sieve(sieve_size);

        for(u32bit j = 0; j != sieve.size(); ++j)
            sieve[j] = p % PRIMES[j];

        u32bit counter = 0;
        while(true)
        {
            if(counter == 4096 || p.bits() > bits)
                break;

            bool passes_sieve = true;
            ++counter;
            p += modulo;

            if(p.bits() > bits)
                break;

            for(u32bit j = 0; j != sieve.size(); ++j)
            {
                sieve[j] = (sieve[j] + modulo) % PRIMES[j];
                if(sieve[j] == 0)
                    passes_sieve = false;
            }

            if(!passes_sieve || gcd(p - 1, coprime) != 1)
                continue;
            if(passes_mr_tests(rng, p))
                return p;
        }
    }
}
Пример #3
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;
   }