* @returns {i32} 0 if `s` decodes to a valid point, else -1
*/
export function ge_frombytes_negate_vartime (h: ge_p3, s: StaticArray<u8>): i32 {
- fe_1(h.Z)
fe_frombytes(h.Y, s)
+ fe_1(h.Z)
// u = y²-1
// v = dy²+1
const ge_frombytes_p_root_check: FieldElement = fe()
const ge_frombytes_negx: FieldElement = fe()
const ge_frombytes_x_sqrtm1: FieldElement = fe()
+/**
+ * Constant-time point negation converted from byte representation.
+ *
+ * @returns {i32} 0 if `s` decodes to a valid point, else -1
+ */
export function ge_frombytes (h: ge_p3, s: StaticArray<u8>): i32 {
const u = ge_frombytes_u
const v = ge_frombytes_v
fe_frombytes(h.Y, s)
fe_1(h.Z)
+
+ // u = y²-1
+ // v = dy²+1
fe_sq(u, h.Y)
fe_mul(v, u, ed25519_d)
- fe_sub(u, u, h.Z) /* u = y^2-1 */
- fe_add(v, v, h.Z) /* v = dy^2+1 */
+ u[0] -= 1
+ v[0] += 1
+ /* x = u((uv)^((q-5)/8)) */
fe_mul(h.X, u, v)
fe_pow22523(h.X, h.X)
- fe_mul(h.X, u, h.X) /* u((uv)^((q-5)/8)) */
+ fe_mul(h.X, u, h.X)
+ // vxx = vx²
fe_sq(vxx, h.X)
fe_mul(vxx, vxx, v)
- fe_sub(m_root_check, vxx, u) /* vx^2-u */
- fe_add(p_root_check, vxx, u) /* vx^2+u */
+
+ // m = vx²-u
+ fe_sub(m_root_check, vxx, u)
has_m_root = fe_iszero(m_root_check)
+
+ // p = vx²+u
+ fe_add(p_root_check, vxx, u)
has_p_root = fe_iszero(p_root_check)
- fe_mul(x_sqrtm1, h.X, fe_sqrtm1) /* x*sqrt(-1) */
+
+ // x√-1
+ fe_mul(x_sqrtm1, h.X, fe_sqrtm1)
fe_cmov(h.X, x_sqrtm1, 1 - has_m_root)
fe_neg(negx, h.X)