Ejemplo n.º 1
0
GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
                                         const secure_vector<byte>& key_bits)
   {
   OID ecc_param_id;

   // The parameters also includes hash and cipher OIDs
   BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);

   domain_params = EC_Group(ecc_param_id);

   secure_vector<byte> bits;
   BER_Decoder(key_bits).decode(bits, OCTET_STRING);

   const size_t part_size = bits.size() / 2;

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   BigInt x(bits.data(), part_size);
   BigInt y(&bits[part_size], part_size);

   public_key = PointGFp(domain().get_curve(), x, y);

   BOTAN_ASSERT(public_key.on_the_curve(),
                "Loaded GOST 34.10 public key is on the curve");
   }
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);

   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& PointGFp::operator-=(const PointGFp& rhs)
   {
   PointGFp minus_rhs = PointGFp(rhs).negate();

   if(is_zero())
      *this = minus_rhs;
   else
      *this += minus_rhs;

   return *this;
   }
Ejemplo n.º 4
0
PointGFp OS2ECP(const byte data[], size_t data_len,
                const CurveGFp& curve)
   {
   if(data_len <= 1)
      return PointGFp(curve); // return zero

   const byte pc = data[0];

   BigInt x, y;

   if(pc == 2 || pc == 3)
      {
      //compressed form
      x = BigInt::decode(&data[1], data_len - 1);

      const bool y_mod_2 = ((pc & 0x01) == 1);
      y = decompress_point(y_mod_2, x, curve);
      }
   else if(pc == 4)
      {
      const size_t l = (data_len - 1) / 2;

      // uncompressed form
      x = BigInt::decode(&data[1], l);
      y = BigInt::decode(&data[l+1], l);
      }
   else if(pc == 6 || pc == 7)
      {
      const size_t l = (data_len - 1) / 2;

      // hybrid form
      x = BigInt::decode(&data[1], l);
      y = BigInt::decode(&data[l+1], l);

      const bool y_mod_2 = ((pc & 0x01) == 1);

      if(decompress_point(y_mod_2, x, curve) != y)
         throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
      }
   else
      throw Invalid_Argument("OS2ECP: Unknown format type");

   PointGFp result(curve, x, y);

   if(!result.on_the_curve())
      throw Illegal_Point("OS2ECP: Decoded point was not on the curve");

   return result;
   }
Ejemplo n.º 5
0
PointGFp OS2ECP(const uint8_t data[], size_t data_len,
                const CurveGFp& curve)
   {
   // Should we really be doing this?
   if(data_len <= 1)
      return PointGFp(curve); // return zero

   std::pair<BigInt, BigInt> xy = OS2ECP(data, data_len, curve.get_p(), curve.get_a(), curve.get_b());

   PointGFp point(curve, xy.first, xy.second);

   if(!point.on_the_curve())
      throw Illegal_Point("OS2ECP: Decoded point was not on the curve");

   return point;
   }
Ejemplo n.º 6
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.º 7
0
// *this *= 2
void PointGFp::mult2(std::vector<BigInt>& ws_bn)
   {
   if(is_zero())
      return;

   if(m_coord_y.is_zero())
      {
      *this = PointGFp(m_curve); // setting myself to zero
      return;
      }

   /*
   https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
   */

   const size_t cap_size = 2*m_curve.get_p_words() + 2;
   for(size_t i = 0; i != ws_bn.size(); ++i)
      ws_bn[i].ensure_capacity(cap_size);

   const BigInt& p = m_curve.get_p();

   BigInt& y_2 = ws_bn[0];
   BigInt& S = ws_bn[1];
   BigInt& tmp = ws_bn[2];
   BigInt& a_z4 = ws_bn[3];
   BigInt& M = ws_bn[4];
   BigInt& U = ws_bn[5];
   BigInt& x = ws_bn[6];
   BigInt& y = ws_bn[7];
   BigInt& z = ws_bn[8];

   secure_vector<word>& monty_ws = ws_bn[9].get_word_vector();

   m_curve.sqr(y_2, m_coord_y, monty_ws);

   m_curve.mul(S, m_coord_x, y_2, monty_ws);
   S <<= 2; // * 4
   while(S >= p)
      S -= p;

   m_curve.sqr(a_z4, m_coord_z, monty_ws); // z^2
   m_curve.sqr(tmp, a_z4, monty_ws); // z^4
   m_curve.mul(a_z4, m_curve.get_a_rep(), tmp, monty_ws);

   m_curve.sqr(M, m_coord_x, monty_ws);
   M *= 3;
   M += a_z4;
   while(M >= p)
      M -= p;

   m_curve.sqr(x, M, monty_ws);
   x -= (S << 1);
   while(x.is_negative())
      x += p;

   m_curve.sqr(U, y_2, monty_ws);
   U <<= 3;
   while(U >= p)
      U -= p;

   S -= x;
   while(S.is_negative())
      S += p;

   m_curve.mul(y, M, S, monty_ws);
   y -= U;
   if(y.is_negative())
      y += p;

   m_curve.mul(z, m_coord_y, m_coord_z, monty_ws);
   z <<= 1;
   if(z >= p)
      z -= p;

   m_coord_x = x;
   m_coord_y = y;
   m_coord_z = z;
   }
Ejemplo n.º 8
0
// Point addition
void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn)
   {
   if(is_zero())
      {
      coord_x = rhs.coord_x;
      coord_y = rhs.coord_y;
      coord_z = rhs.coord_z;
      return;
      }
   else if(rhs.is_zero())
      return;

   const BigInt& p = curve.get_p();

   BigInt& rhs_z2 = ws_bn[0];
   BigInt& U1 = ws_bn[1];
   BigInt& S1 = ws_bn[2];

   BigInt& lhs_z2 = ws_bn[3];
   BigInt& U2 = ws_bn[4];
   BigInt& S2 = ws_bn[5];

   BigInt& H = ws_bn[6];
   BigInt& r = ws_bn[7];

   monty_sqr(rhs_z2, rhs.coord_z);
   monty_mult(U1, coord_x, rhs_z2);
   monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2));

   monty_sqr(lhs_z2, coord_z);
   monty_mult(U2, rhs.coord_x, lhs_z2);
   monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2));

   H = U2;
   H -= U1;
   if(H.is_negative())
      H += p;

   r = S2;
   r -= S1;
   if(r.is_negative())
      r += p;

   if(H.is_zero())
      {
      if(r.is_zero())
         {
         mult2(ws_bn);
         return;
         }

      *this = PointGFp(curve); // setting myself to zero
      return;
      }

   monty_sqr(U2, H);

   monty_mult(S2, U2, H);

   U2 = monty_mult(U1, U2);

   monty_sqr(coord_x, r);
   coord_x -= S2;
   coord_x -= (U2 << 1);
   while(coord_x.is_negative())
      coord_x += p;

   U2 -= coord_x;
   if(U2.is_negative())
      U2 += p;

   monty_mult(coord_y, r, U2);
   coord_y -= monty_mult(S1, S2);
   if(coord_y.is_negative())
      coord_y += p;

   monty_mult(coord_z, monty_mult(coord_z, rhs.coord_z), H);
   }
Ejemplo n.º 9
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.º 10
0
// *this *= 2
void PointGFp::mult2(std::vector<BigInt>& ws_bn)
   {
   if(is_zero())
      return;
   else if(coord_y.is_zero())
      {
      *this = PointGFp(curve); // setting myself to zero
      return;
      }

   const BigInt& p = curve.get_p();

   BigInt& y_2 = ws_bn[0];
   BigInt& S = ws_bn[1];
   BigInt& z4 = ws_bn[2];
   BigInt& a_z4 = ws_bn[3];
   BigInt& M = ws_bn[4];
   BigInt& U = ws_bn[5];
   BigInt& x = ws_bn[6];
   BigInt& y = ws_bn[7];
   BigInt& z = ws_bn[8];

   monty_sqr(y_2, coord_y);

   monty_mult(S, coord_x, y_2);
   S <<= 2; // * 4
   while(S >= p)
      S -= p;

   monty_sqr(z4, monty_sqr(coord_z));
   monty_mult(a_z4, curve.get_a_r(), z4);

   M = 3 * monty_sqr(coord_x);
   M += a_z4;
   while(M >= p)
      M -= p;

   monty_sqr(x, M);
   x -= (S << 1);
   while(x.is_negative())
      x += p;

   monty_sqr(U, y_2);
   U <<= 3;
   while(U >= p)
      U -= p;

   S -= x;
   while(S.is_negative())
      S += p;

   monty_mult(y, M, S);
   y -= U;
   if(y.is_negative())
      y += p;

   monty_mult(z, coord_y, coord_z);
   z <<= 1;
   if(z >= p)
      z -= p;

   coord_x = x;
   coord_y = y;
   coord_z = z;
   }
Ejemplo n.º 11
0
// *this *= 2
void PointGFp::mult2(std::vector<BigInt>& ws_bn)
   {
   if(is_zero())
      return;
   else if(m_coord_y.is_zero())
      {
      *this = PointGFp(m_curve); // setting myself to zero
      return;
      }

   /*
   http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
   */

   const BigInt& p = m_curve.get_p();

   BigInt& y_2 = ws_bn[0];
   BigInt& S = ws_bn[1];
   BigInt& z4 = ws_bn[2];
   BigInt& a_z4 = ws_bn[3];
   BigInt& M = ws_bn[4];
   BigInt& U = ws_bn[5];
   BigInt& x = ws_bn[6];
   BigInt& y = ws_bn[7];
   BigInt& z = ws_bn[8];

   curve_sqr(y_2, m_coord_y);

   curve_mult(S, m_coord_x, y_2);
   S <<= 2; // * 4
   while(S >= p)
      S -= p;

   curve_sqr(z4, curve_sqr(m_coord_z));
   curve_mult(a_z4, m_curve.get_a_rep(), z4);

   M = curve_sqr(m_coord_x);
   M *= 3;
   M += a_z4;
   while(M >= p)
      M -= p;

   curve_sqr(x, M);
   x -= (S << 1);
   while(x.is_negative())
      x += p;

   curve_sqr(U, y_2);
   U <<= 3;
   while(U >= p)
      U -= p;

   S -= x;
   while(S.is_negative())
      S += p;

   curve_mult(y, M, S);
   y -= U;
   if(y.is_negative())
      y += p;

   curve_mult(z, m_coord_y, m_coord_z);
   z <<= 1;
   if(z >= p)
      z -= p;

   m_coord_x = x;
   m_coord_y = y;
   m_coord_z = z;
   }