The Bouncy Castle source code (Java edition) has a ECPoint.normalize()
function. It seems to calculate the modular inverse of a coordinate of a point on the curve. Without it point compression - for instance - seems to fail.
It seems that usually this normalization is performed as part of Elliptic Curve calculations automatically when other libraries are concerned.
So I've got the following questions:
- After which operations is normalization required for elliptic curves?
- What's this normalization about, is it just calculating the coordinates with a "positive" Y value on the curve?
- Could leaving out the normalization of points trigger invalid calculations, or is this just about the representation of the point on the curve?
If there is any reference material available then I'd be interested to know about it.
For reference, the Java source code of Bouncy Castle:
/**
* Normalization ensures that any projective coordinate is 1, and therefore that the x, y
* coordinates reflect those of the equivalent point in an affine coordinate system.
*
* @return a new ECPoint instance representing the same point, but with normalized coordinates
*/
public ECPoint normalize()
{
if (this.isInfinity())
{
return this;
}
switch (this.getCurveCoordinateSystem())
{
case ECCurve.COORD_AFFINE:
case ECCurve.COORD_LAMBDA_AFFINE:
{
return this;
}
default:
{
ECFieldElement Z1 = getZCoord(0);
if (Z1.isOne())
{
return this;
}
return normalize(Z1.invert());
}
}
}
ECPoint normalize(ECFieldElement zInv)
{
switch (this.getCurveCoordinateSystem())
{
case ECCurve.COORD_HOMOGENEOUS:
case ECCurve.COORD_LAMBDA_PROJECTIVE:
{
return createScaledPoint(zInv, zInv);
}
case ECCurve.COORD_JACOBIAN:
case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
case ECCurve.COORD_JACOBIAN_MODIFIED:
{
ECFieldElement zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
return createScaledPoint(zInv2, zInv3);
}
default:
{
throw new IllegalStateException("not a projective coordinate system");
}
}
}
protected ECPoint createScaledPoint(ECFieldElement sx, ECFieldElement sy)
{
return this.getCurve().createRawPoint(getRawXCoord().multiply(sx), getRawYCoord().multiply(sy), this.withCompression);
}