protected virtual ECFieldElement CalculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared) { ECFieldElement a4 = this.Curve.A; if (a4.IsZero) { return(a4); } if (ZSquared == null) { ZSquared = Z.Square(); } ECFieldElement W = ZSquared.Square(); ECFieldElement a4Neg = a4.Negate(); if (a4Neg.BitLength < a4.BitLength) { W = W.Multiply(a4Neg).Negate(); } else { W = W.Multiply(a4); } return(W); }
protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) { ECFieldElement x = FromBigInteger(X1); ECFieldElement alpha = x.Square().Add(m_a).Multiply(x).Add(m_b); ECFieldElement beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the // curve - run! // if (beta == null) { throw new ArithmeticException("Invalid point compression"); } if (beta.TestBitZero() != (yTilde == 1)) { // Use the other root beta = beta.Negate(); } return(new FpPoint(this, x, beta, true)); }
// B.3 pg 62 public override ECPoint Twice() { if (this.IsInfinity) { return(this); } ECCurve curve = this.Curve; ECFieldElement Y1 = this.RawYCoord; if (Y1.IsZero) { return(curve.Infinity); } int coord = curve.CoordinateSystem; ECFieldElement X1 = this.RawXCoord; switch (coord) { case ECCurve.COORD_AFFINE: { ECFieldElement X1Squared = X1.Square(); ECFieldElement gamma = Three(X1Squared).Add(this.Curve.A).Divide(Two(Y1)); ECFieldElement X3 = gamma.Square().Subtract(Two(X1)); ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1); return(new FpPoint(Curve, X3, Y3, IsCompressed)); } case ECCurve.COORD_HOMOGENEOUS: { ECFieldElement Z1 = this.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; // TODO Optimize for small negative a4 and -3 ECFieldElement w = curve.A; if (!w.IsZero && !Z1IsOne) { w = w.Multiply(Z1.Square()); } w = w.Add(Three(X1.Square())); ECFieldElement s = Z1IsOne ? Y1 : Y1.Multiply(Z1); ECFieldElement t = Z1IsOne ? Y1.Square() : s.Multiply(Y1); ECFieldElement B = X1.Multiply(t); ECFieldElement _4B = Four(B); ECFieldElement h = w.Square().Subtract(Two(_4B)); ECFieldElement _2s = Two(s); ECFieldElement X3 = h.Multiply(_2s); ECFieldElement _2t = Two(t); ECFieldElement Y3 = _4B.Subtract(h).Multiply(w).Subtract(Two(_2t.Square())); ECFieldElement _4sSquared = Z1IsOne ? Two(_2t) : _2s.Square(); ECFieldElement Z3 = Two(_4sSquared).Multiply(s); return(new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed)); } case ECCurve.COORD_JACOBIAN: { ECFieldElement Z1 = this.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; ECFieldElement Y1Squared = Y1.Square(); ECFieldElement T = Y1Squared.Square(); ECFieldElement a4 = curve.A; ECFieldElement a4Neg = a4.Negate(); ECFieldElement M, S; if (a4Neg.ToBigInteger().Equals(BigInteger.ValueOf(3))) { ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square(); M = Three(X1.Add(Z1Squared).Multiply(X1.Subtract(Z1Squared))); S = Four(Y1Squared.Multiply(X1)); } else { ECFieldElement X1Squared = X1.Square(); M = Three(X1Squared); if (Z1IsOne) { M = M.Add(a4); } else if (!a4.IsZero) { ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square(); ECFieldElement Z1Pow4 = Z1Squared.Square(); if (a4Neg.BitLength < a4.BitLength) { M = M.Subtract(Z1Pow4.Multiply(a4Neg)); } else { M = M.Add(Z1Pow4.Multiply(a4)); } } //S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T)); S = Four(X1.Multiply(Y1Squared)); } ECFieldElement X3 = M.Square().Subtract(Two(S)); ECFieldElement Y3 = S.Subtract(X3).Multiply(M).Subtract(Eight(T)); ECFieldElement Z3 = Two(Y1); if (!Z1IsOne) { Z3 = Z3.Multiply(Z1); } // Alternative calculation of Z3 using fast square //ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared); return(new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed)); } case ECCurve.COORD_JACOBIAN_MODIFIED: { return(TwiceJacobianModified(true)); } default: { throw new InvalidOperationException("unsupported coordinate system"); } } }