public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n) : this(curve, g, n, BigInteger.One) { }
public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h) : this(curve, g, n, h, null) { }
protected internal ECPoint( ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) { if (curve == null) throw new ArgumentNullException("curve"); this.curve = curve; this.x = x; this.y = y; this.withCompression = withCompression; }
public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h, byte[] seed) { if (curve == null) throw new ArgumentNullException("curve"); if (g == null) throw new ArgumentNullException("g"); if (n == null) throw new ArgumentNullException("n"); if (h == null) throw new ArgumentNullException("h"); this.curve = curve; this.g = g; this.n = n; this.h = h; this.seed = (seed == null ? null : (byte[])seed.Clone()); }
/** * Create a point that encodes with or without point compresion. * * @param curve the curve to use * @param x affine x co-ordinate * @param y affine y co-ordinate * @param withCompression if true encode with point compression */ public FpPoint( ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) : base(curve, x, y, withCompression) { if ((x != null && y == null) || (x == null && y != null)) throw new ArgumentException("Exactly one of the field elements is null"); }
/** * Create a point which encodes with point compression. * * @param curve the curve to use * @param x affine x co-ordinate * @param y affine y co-ordinate */ public FpPoint( ECCurve curve, ECFieldElement x, ECFieldElement y) : this(curve, x, y, false) { }
protected internal ECPointBase( ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) : base(curve, x, y, withCompression) { }
/** * Create a point which encodes with point compression. * * @param curve the curve to use * @param x affine x co-ordinate * @param y affine y co-ordinate */ public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) : this(curve, x, y, false) { }
public static int GetByteLength( ECCurve c) { return((c.FieldSize + 7) / 8); }
public override ECPoint TwicePlus(ECPoint b) { if (this == b) { return(ThreeTimes()); } if (this.IsInfinity) { return(b); } if (b.IsInfinity) { return(Twice()); } ECFieldElement Y1 = this.RawYCoord; if (Y1.IsZero) { return(b); } ECCurve curve = this.Curve; int coord = curve.CoordinateSystem; switch (coord) { case ECCurve.COORD_AFFINE: { ECFieldElement X1 = this.RawXCoord; ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord; ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); if (dx.IsZero) { if (dy.IsZero) { // this == b i.e. the result is 3P return(ThreeTimes()); } // this == -b, i.e. the result is P return(this); } /* * Optimized calculation of 2P + Q, as described in "Trading Inversions for * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery. */ ECFieldElement X = dx.Square(), Y = dy.Square(); ECFieldElement d = X.Multiply(Two(X1).Add(X2)).Subtract(Y); if (d.IsZero) { return(Curve.Infinity); } ECFieldElement D = d.Multiply(dx); ECFieldElement I = D.Invert(); ECFieldElement L1 = d.Multiply(I).Multiply(dy); ECFieldElement L2 = Two(Y1).Multiply(X).Multiply(dx).Multiply(I).Subtract(L1); ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X2); ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1); return(new FpPoint(Curve, X4, Y4, IsCompressed)); } case ECCurve.COORD_JACOBIAN_MODIFIED: { return(TwiceJacobianModified(false).Add(b)); } default: { return(Twice().Add(b)); } } }
// 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"); } } }
protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) : this(curve, x, y, GetInitialZCoords(curve), withCompression) { }
// B.3 pg 62 public override ECPoint Add(ECPoint b) { if (this.IsInfinity) { return(b); } if (b.IsInfinity) { return(this); } if (this == b) { return(Twice()); } ECCurve curve = this.Curve; int coord = curve.CoordinateSystem; ECFieldElement X1 = this.RawXCoord, Y1 = this.RawYCoord; ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord; switch (coord) { case ECCurve.COORD_AFFINE: { ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); if (dx.IsZero) { if (dy.IsZero) { // this == b, i.e. this must be doubled return(Twice()); } // this == -b, i.e. the result is the point at infinity return(Curve.Infinity); } ECFieldElement gamma = dy.Divide(dx); ECFieldElement X3 = gamma.Square().Subtract(X1).Subtract(X2); 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]; ECFieldElement Z2 = b.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; bool Z2IsOne = Z2.IsOne; ECFieldElement u1 = Z1IsOne ? Y2 : Y2.Multiply(Z1); ECFieldElement u2 = Z2IsOne ? Y1 : Y1.Multiply(Z2); ECFieldElement u = u1.Subtract(u2); ECFieldElement v1 = Z1IsOne ? X2 : X2.Multiply(Z1); ECFieldElement v2 = Z2IsOne ? X1 : X1.Multiply(Z2); ECFieldElement v = v1.Subtract(v2); // Check if b == this or b == -this if (v.IsZero) { if (u.IsZero) { // this == b, i.e. this must be doubled return(this.Twice()); } // this == -b, i.e. the result is the point at infinity return(curve.Infinity); } // TODO Optimize for when w == 1 ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2); ECFieldElement vSquared = v.Square(); ECFieldElement vCubed = vSquared.Multiply(v); ECFieldElement vSquaredV2 = vSquared.Multiply(v2); ECFieldElement A = u.Square().Multiply(w).Subtract(vCubed).Subtract(Two(vSquaredV2)); ECFieldElement X3 = v.Multiply(A); ECFieldElement Y3 = vSquaredV2.Subtract(A).Multiply(u).Subtract(vCubed.Multiply(u2)); ECFieldElement Z3 = vCubed.Multiply(w); return(new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed)); } case ECCurve.COORD_JACOBIAN: case ECCurve.COORD_JACOBIAN_MODIFIED: { ECFieldElement Z1 = this.RawZCoords[0]; ECFieldElement Z2 = b.RawZCoords[0]; bool Z1IsOne = Z1.IsOne; ECFieldElement X3, Y3, Z3, Z3Squared = null; if (!Z1IsOne && Z1.Equals(Z2)) { // TODO Make this available as public method coZAdd? ECFieldElement dx = X1.Subtract(X2), dy = Y1.Subtract(Y2); if (dx.IsZero) { if (dy.IsZero) { return(Twice()); } return(curve.Infinity); } ECFieldElement C = dx.Square(); ECFieldElement W1 = X1.Multiply(C), W2 = X2.Multiply(C); ECFieldElement A1 = W1.Subtract(W2).Multiply(Y1); X3 = dy.Square().Subtract(W1).Subtract(W2); Y3 = W1.Subtract(X3).Multiply(dy).Subtract(A1); Z3 = dx; if (Z1IsOne) { Z3Squared = C; } else { Z3 = Z3.Multiply(Z1); } } else { ECFieldElement Z1Squared, U2, S2; if (Z1IsOne) { Z1Squared = Z1; U2 = X2; S2 = Y2; } else { Z1Squared = Z1.Square(); U2 = Z1Squared.Multiply(X2); ECFieldElement Z1Cubed = Z1Squared.Multiply(Z1); S2 = Z1Cubed.Multiply(Y2); } bool Z2IsOne = Z2.IsOne; ECFieldElement Z2Squared, U1, S1; if (Z2IsOne) { Z2Squared = Z2; U1 = X1; S1 = Y1; } else { Z2Squared = Z2.Square(); U1 = Z2Squared.Multiply(X1); ECFieldElement Z2Cubed = Z2Squared.Multiply(Z2); S1 = Z2Cubed.Multiply(Y1); } ECFieldElement H = U1.Subtract(U2); ECFieldElement R = S1.Subtract(S2); // Check if b == this or b == -this if (H.IsZero) { if (R.IsZero) { // this == b, i.e. this must be doubled return(this.Twice()); } // this == -b, i.e. the result is the point at infinity return(curve.Infinity); } ECFieldElement HSquared = H.Square(); ECFieldElement G = HSquared.Multiply(H); ECFieldElement V = HSquared.Multiply(U1); X3 = R.Square().Add(G).Subtract(Two(V)); Y3 = V.Subtract(X3).Multiply(R).Subtract(S1.Multiply(G)); Z3 = H; if (!Z1IsOne) { Z3 = Z3.Multiply(Z1); } if (!Z2IsOne) { Z3 = Z3.Multiply(Z2); } // Alternative calculation of Z3 using fast square //X3 = four(X3); //Y3 = eight(Y3); //Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).multiply(H); if (Z3 == H) { Z3Squared = HSquared; } } ECFieldElement[] zs; if (coord == ECCurve.COORD_JACOBIAN_MODIFIED) { // TODO If the result will only be used in a subsequent addition, we don't need W3 ECFieldElement W3 = CalculateJacobianModifiedW(Z3, Z3Squared); zs = new ECFieldElement[] { Z3, W3 }; } else { zs = new ECFieldElement[] { Z3 }; } return(new FpPoint(curve, X3, Y3, zs, IsCompressed)); } default: { throw new InvalidOperationException("unsupported coordinate system"); } } }
internal FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) : base(curve, x, y, zs, withCompression) { }
protected bool Equals( ECCurve other) { return a.Equals(other.a) && b.Equals(other.b); }
public static int GetByteLength( ECCurve c) { return (c.FieldSize + 7) / 8; }
protected internal ECPointBase(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) : base(curve, x, y, zs, withCompression) { }