/** * Subtracts another <code>ECPoints.F2m</code> from <code>this</code> * without checking if both points are on the same curve. Used by * multiplication algorithms, because there all points are a multiple * of the same point and hence the checks can be omitted. * @param b The other <code>ECPoints.F2m</code> to subtract from * <code>this</code>. * @return <code>this - b</code> */ internal F2mPoint SubtractSimple( F2mPoint b) { if (b.IsInfinity) return this; // Add -b return AddSimple((F2mPoint) b.Negate()); }
protected F2mCurve(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) : base(m, k1, k2, k3) { this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; this.m_order = order; this.m_cofactor = cofactor; this.m_infinity = new F2mPoint(this, null, null); this.m_a = a; this.m_b = b; this.m_coord = F2M_DEFAULT_COORDS; }
/** * Adds another <code>ECPoints.F2m</code> to <code>this</code> without * checking if both points are on the same curve. Used by multiplication * algorithms, because there all points are a multiple of the same point * and hence the checks can be omitted. * @param b The other <code>ECPoints.F2m</code> to add to * <code>this</code>. * @return <code>this + b</code> */ internal F2mPoint AddSimple(F2mPoint b) { if (this.IsInfinity) return b; if (b.IsInfinity) return this; ECCurve curve = this.Curve; int coord = curve.CoordinateSystem; ECFieldElement X1 = this.RawXCoord; ECFieldElement X2 = b.RawXCoord; switch (coord) { case ECCurve.COORD_AFFINE: { ECFieldElement Y1 = this.RawYCoord; ECFieldElement Y2 = b.RawYCoord; ECFieldElement dx = X1.Add(X2), dy = Y1.Add(Y2); if (dx.IsZero) { if (dy.IsZero) { return (F2mPoint)Twice(); } return (F2mPoint)curve.Infinity; } ECFieldElement L = dy.Divide(dx); ECFieldElement X3 = L.Square().Add(L).Add(dx).Add(curve.A); ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); return new F2mPoint(curve, X3, Y3, IsCompressed); } case ECCurve.COORD_HOMOGENEOUS: { ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; ECFieldElement Y2 = b.RawYCoord, Z2 = b.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; ECFieldElement U1 = Y2, V1 = X2; if (!Z1IsOne) { U1 = U1.Multiply(Z1); V1 = V1.Multiply(Z1); } bool Z2IsOne = Z2.IsOne; ECFieldElement U2 = Y1, V2 = X1; if (!Z2IsOne) { U2 = U2.Multiply(Z2); V2 = V2.Multiply(Z2); } ECFieldElement U = U1.Add(U2); ECFieldElement V = V1.Add(V2); if (V.IsZero) { if (U.IsZero) { return (F2mPoint)Twice(); } return (F2mPoint)curve.Infinity; } ECFieldElement VSq = V.Square(); ECFieldElement VCu = VSq.Multiply(V); ECFieldElement W = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2); ECFieldElement uv = U.Add(V); ECFieldElement A = uv.MultiplyPlusProduct(U, VSq, curve.A).Multiply(W).Add(VCu); ECFieldElement X3 = V.Multiply(A); ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.Multiply(Z2); ECFieldElement Y3 = U.MultiplyPlusProduct(X1, V, Y1).MultiplyPlusProduct(VSqZ2, uv, A); ECFieldElement Z3 = VCu.Multiply(W); return new F2mPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); } case ECCurve.COORD_LAMBDA_PROJECTIVE: { if (X1.IsZero) { if (X2.IsZero) return (F2mPoint)curve.Infinity; return b.AddSimple(this); } ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; ECFieldElement U2 = X2, S2 = L2; if (!Z1IsOne) { U2 = U2.Multiply(Z1); S2 = S2.Multiply(Z1); } bool Z2IsOne = Z2.IsOne; ECFieldElement U1 = X1, S1 = L1; if (!Z2IsOne) { U1 = U1.Multiply(Z2); S1 = S1.Multiply(Z2); } ECFieldElement A = S1.Add(S2); ECFieldElement B = U1.Add(U2); if (B.IsZero) { if (A.IsZero) { return (F2mPoint)Twice(); } return (F2mPoint)curve.Infinity; } ECFieldElement X3, L3, Z3; if (X2.IsZero) { // TODO This can probably be optimized quite a bit ECPoint p = this.Normalize(); X1 = p.RawXCoord; ECFieldElement Y1 = p.YCoord; ECFieldElement Y2 = L2; ECFieldElement L = Y1.Add(Y2).Divide(X1); X3 = L.Square().Add(L).Add(X1).Add(curve.A); if (X3.IsZero) { return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed); } ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); L3 = Y3.Divide(X3).Add(X3); Z3 = curve.FromBigInteger(BigInteger.One); } else { B = B.Square(); ECFieldElement AU1 = A.Multiply(U1); ECFieldElement AU2 = A.Multiply(U2); X3 = AU1.Multiply(AU2); if (X3.IsZero) { return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed); } ECFieldElement ABZ2 = A.Multiply(B); if (!Z2IsOne) { ABZ2 = ABZ2.Multiply(Z2); } L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); Z3 = ABZ2; if (!Z1IsOne) { Z3 = Z3.Multiply(Z1); } } return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); } default: { throw new InvalidOperationException("unsupported coordinate system"); } } }
/** * Constructor for Pentanomial Polynomial Basis (PPB). * @param m The exponent <code>m</code> of * <code>F<sub>2<sup>m</sup></sub></code>. * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> * represents the reduction polynomial <code>f(z)</code>. * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> * represents the reduction polynomial <code>f(z)</code>. * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> * represents the reduction polynomial <code>f(z)</code>. * @param a The coefficient <code>a</code> in the Weierstrass equation * for non-supersingular elliptic curves over * <code>F<sub>2<sup>m</sup></sub></code>. * @param b The coefficient <code>b</code> in the Weierstrass equation * for non-supersingular elliptic curves over * <code>F<sub>2<sup>m</sup></sub></code>. * @param order The order of the main subgroup of the elliptic curve. * @param cofactor The cofactor of the elliptic curve, i.e. * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. */ public F2mCurve( int m, int k1, int k2, int k3, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor) : base(m, k1, k2, k3) { this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; this.m_order = order; this.m_cofactor = cofactor; this.m_infinity = new F2mPoint(this, null, null); if (k1 == 0) throw new ArgumentException("k1 must be > 0"); if (k2 == 0) { if (k3 != 0) throw new ArgumentException("k3 must be 0 if k2 == 0"); } else { if (k2 <= k1) throw new ArgumentException("k2 must be > k1"); if (k3 <= k2) throw new ArgumentException("k3 must be > k2"); } this.m_a = FromBigInteger(a); this.m_b = FromBigInteger(b); this.m_coord = F2M_DEFAULT_COORDS; }