PointGFp multi_exponentiate(const PointGFp& p1, const BigInt& z1, const PointGFp& p2, const BigInt& z2) { const PointGFp p3 = p1 + p2; PointGFp H(p1.get_curve()); // create as zero size_t bits_left = std::max(z1.bits(), z2.bits()); std::vector<BigInt> ws(9); while(bits_left) { H.mult2(ws); const bool z1_b = z1.get_bit(bits_left - 1); const bool z2_b = z2.get_bit(bits_left - 1); if(z1_b == true && z2_b == true) H.add(p3, ws); else if(z1_b) H.add(p1, ws); else if(z2_b) H.add(p2, ws); --bits_left; } if(z1.is_negative() != z2.is_negative()) H.negate(); return H; }
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]; }
bool PointGFp::operator==(const PointGFp& other) const { if(get_curve() != other.get_curve()) return false; // If this is zero, only equal if other is also zero if(is_zero()) return other.is_zero(); return (get_affine_x() == other.get_affine_x() && get_affine_y() == other.get_affine_y()); }
// encoding and decoding secure_vector<uint8_t> EC2OSP(const PointGFp& point, uint8_t format) { if(point.is_zero()) return secure_vector<uint8_t>(1); // single 0 byte const size_t p_bytes = point.get_curve().get_p().bytes(); BigInt x = point.get_affine_x(); BigInt y = point.get_affine_y(); secure_vector<uint8_t> bX = BigInt::encode_1363(x, p_bytes); secure_vector<uint8_t> bY = BigInt::encode_1363(y, p_bytes); if(format == PointGFp::UNCOMPRESSED) { secure_vector<uint8_t> result; result.push_back(0x04); result += bX; result += bY; return result; } else if(format == PointGFp::COMPRESSED) { secure_vector<uint8_t> result; result.push_back(0x02 | static_cast<uint8_t>(y.get_bit(0))); result += bX; return result; } else if(format == PointGFp::HYBRID) { secure_vector<uint8_t> result; result.push_back(0x06 | static_cast<uint8_t>(y.get_bit(0))); result += bX; result += bY; return result; } else throw Invalid_Argument("EC2OSP illegal point encoding"); }
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]; }
Blinded_Point_Multiply::Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h) : m_h(h > 0 ? h : 4), m_order(order), m_ws(9) { // Upper bound is a sanity check rather than hard limit if(m_h < 1 || m_h > 8) throw std::invalid_argument("Blinded_Point_Multiply invalid h param"); const CurveGFp& curve = base.get_curve(); #if BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER const PointGFp inv = -base; m_U.resize(6*m_h + 3); m_U[3*m_h+0] = inv; m_U[3*m_h+1] = PointGFp::zero_of(curve); m_U[3*m_h+2] = base; for(size_t i = 1; i <= 3 * m_h + 1; ++i) { m_U[3*m_h+1+i] = m_U[3*m_h+i]; m_U[3*m_h+1+i].add(base, m_ws); m_U[3*m_h+1-i] = m_U[3*m_h+2-i]; m_U[3*m_h+1-i].add(inv, m_ws); } #else m_U.resize(1 << m_h); m_U[0] = PointGFp::zero_of(curve); m_U[1] = base; for(size_t i = 2; i < m_U.size(); ++i) { m_U[i] = m_U[i-1]; m_U[i].add(base, m_ws); } #endif }
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 }