bool PointGFp::on_the_curve() const { /* Is the point still on the curve?? (If everything is correct, the point is always on its curve; then the function will return true. If somehow the state is corrupted, which suggests a fault attack (or internal computational error), then return false. */ if(is_zero()) return true; const BigInt y2 = m_curve.from_rep(curve_sqr(m_coord_y), m_monty_ws); const BigInt x3 = curve_mult(m_coord_x, curve_sqr(m_coord_x)); const BigInt ax = curve_mult(m_coord_x, m_curve.get_a_rep()); const BigInt z2 = curve_sqr(m_coord_z); if(m_coord_z == z2) // Is z equal to 1 (in Montgomery form)? { if(y2 != m_curve.from_rep(x3 + ax + m_curve.get_b_rep(), m_monty_ws)) return false; } const BigInt z3 = curve_mult(m_coord_z, z2); const BigInt ax_z4 = curve_mult(ax, curve_sqr(z2)); const BigInt b_z6 = curve_mult(m_curve.get_b_rep(), curve_sqr(z3)); if(y2 != m_curve.from_rep(x3 + ax_z4 + b_z6, m_monty_ws)) return false; return true; }
BigInt PointGFp::get_affine_y() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); BigInt z3 = curve_mult(m_coord_z, curve_sqr(m_coord_z)); z3 = inverse_mod(z3, m_curve.get_p()); m_curve.to_rep(z3, m_monty_ws); return curve_mult(z3, m_coord_y); }
BigInt PointGFp::get_affine_x() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); BigInt z2 = curve_sqr(m_coord_z); m_curve.from_rep(z2, m_monty_ws); z2 = inverse_mod(z2, m_curve.get_p()); return curve_mult(z2, m_coord_x); }
// Point addition void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn) { if(is_zero()) { m_coord_x = rhs.m_coord_x; m_coord_y = rhs.m_coord_y; m_coord_z = rhs.m_coord_z; return; } else if(rhs.is_zero()) return; const BigInt& p = m_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]; /* http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2 */ curve_sqr(rhs_z2, rhs.m_coord_z); curve_mult(U1, m_coord_x, rhs_z2); curve_mult(S1, m_coord_y, curve_mult(rhs.m_coord_z, rhs_z2)); curve_sqr(lhs_z2, m_coord_z); curve_mult(U2, rhs.m_coord_x, lhs_z2); curve_mult(S2, rhs.m_coord_y, curve_mult(m_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; } // setting to zero: m_coord_x = 0; m_coord_y = 1; m_coord_z = 0; return; } curve_sqr(U2, H); curve_mult(S2, U2, H); U2 = curve_mult(U1, U2); curve_sqr(m_coord_x, r); m_coord_x -= S2; m_coord_x -= (U2 << 1); while(m_coord_x.is_negative()) m_coord_x += p; U2 -= m_coord_x; if(U2.is_negative()) U2 += p; curve_mult(m_coord_y, r, U2); m_coord_y -= curve_mult(S1, S2); if(m_coord_y.is_negative()) m_coord_y += p; curve_mult(m_coord_z, curve_mult(m_coord_z, rhs.m_coord_z), H); }
// *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; }