// extendedToBigAffine converts projective x, y, and z field elements into // affine x and y coordinates, and returns whether or not the x value // returned is negative. func (curve *TwistedEdwardsCurve) extendedToBigAffine(xi, yi, zi *edwards25519.FieldElement) (*big.Int, *big.Int, bool) { var recip, x, y edwards25519.FieldElement // Normalize to Z=1. edwards25519.FeInvert(&recip, zi) edwards25519.FeMul(&x, xi, &recip) edwards25519.FeMul(&y, yi, &recip) isNegative := edwards25519.FeIsNegative(&x) == 1 return FieldElementToBigInt(&x), FieldElementToBigInt(&y), isNegative }
// BigIntPointToEncodedBytes converts an affine point to a compressed // 32 byte integer representation. func BigIntPointToEncodedBytes(x *big.Int, y *big.Int) *[32]byte { s := BigIntToEncodedBytes(y) xB := BigIntToEncodedBytes(x) xFE := new(edwards25519.FieldElement) edwards25519.FeFromBytes(xFE, xB) isNegative := edwards25519.FeIsNegative(xFE) == 1 if isNegative { s[31] |= (1 << 7) } else { s[31] &^= (1 << 7) } return s }
// RecoverXFieldElement recovers the X value for some Y value, for a coordinate // on the Ed25519 curve given as a field element. Y value. Probably the fastest // way to get your respective X from Y. func (curve *TwistedEdwardsCurve) RecoverXFieldElement(xIsNeg bool, y *edwards25519.FieldElement) *edwards25519.FieldElement { // (y^2 - 1) l := new(edwards25519.FieldElement) edwards25519.FeSquare(l, y) edwards25519.FeSub(l, l, &feOne) // inv(d*y^2+1) r := new(edwards25519.FieldElement) edwards25519.FeSquare(r, y) edwards25519.FeMul(r, r, &fed) edwards25519.FeAdd(r, r, &feOne) edwards25519.FeInvert(r, r) x2 := new(edwards25519.FieldElement) edwards25519.FeMul(x2, r, l) // Get a big int so we can do the exponentiation. x2Big := FieldElementToBigInt(x2) // x = exp(x^2,(P+3)/8, P) qp3 := new(big.Int).Add(curve.P, three) qp3.Div(qp3, eight) // /= curve.H xBig := new(big.Int).Exp(x2Big, qp3, curve.P) // Convert back to a field element and do // the rest. x := BigIntToFieldElement(xBig) // check (x^2 - x2) % q != 0 x22 := new(edwards25519.FieldElement) edwards25519.FeSquare(x22, x) xsub := new(edwards25519.FieldElement) edwards25519.FeSub(xsub, x22, x2) xsubBig := FieldElementToBigInt(xsub) xsubBig.Mod(xsubBig, curve.P) if xsubBig.Cmp(zero) != 0 { xi := new(edwards25519.FieldElement) edwards25519.FeMul(xi, x, &feI) xiModBig := FieldElementToBigInt(xi) xiModBig.Mod(xiModBig, curve.P) xiMod := BigIntToFieldElement(xiModBig) x = xiMod } xBig = FieldElementToBigInt(x) xmod2 := new(big.Int).Mod(xBig, two) if xmod2.Cmp(zero) != 0 { // TODO replace this with FeSub xBig.Sub(curve.P, xBig) x = BigIntToFieldElement(xBig) } // We got the wrong x, negate it to get the right one. isNegative := edwards25519.FeIsNegative(x) == 1 if xIsNeg != isNegative { edwards25519.FeNeg(x, x) } return x }