public ECDomainParameters(
            ECCurve     curve,
            ECPoint     g,
            BigInteger  n)
			: this(curve, g, n, BigInteger.One)
        {
        }
		private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k,
			ECPoint Q, BigInteger l)
		{
			int m = System.Math.Max(k.BitLength, l.BitLength);
			ECPoint Z = P.Add(Q);
			ECPoint R = P.Curve.Infinity;

			for (int i = m - 1; i >= 0; --i)
			{
				R = R.Twice();

				if (k.TestBit(i))
				{
					if (l.TestBit(i))
					{
						R = R.Add(Z);
					}
					else
					{
						R = R.Add(P);
					}
				}
				else
				{
					if (l.TestBit(i))
					{
						R = R.Add(Q);
					}
				}
			}

			return R;
		}
        public ECDomainParameters(
            ECCurve     curve,
            ECPoint     g,
            BigInteger  n,
            BigInteger  h)
			: this(curve, g, n, h, null)
		{
        }
		/*
		* "Shamir's Trick", originally due to E. G. Straus
		* (Addition chains of vectors. American Mathematical Monthly,
		* 71(7):806-808, Aug./Sept. 1964)
		*  
		* Input: The points P, Q, scalar k = (km?, ... , k1, k0)
		* and scalar l = (lm?, ... , l1, l0).
		* Output: R = k * P + l * Q.
		* 1: Z <- P + Q
		* 2: R <- O
		* 3: for i from m-1 down to 0 do
		* 4:        R <- R + R        {point doubling}
		* 5:        if (ki = 1) and (li = 0) then R <- R + P end if
		* 6:        if (ki = 0) and (li = 1) then R <- R + Q end if
		* 7:        if (ki = 1) and (li = 1) then R <- R + Z end if
		* 8: end for
		* 9: return R
		*/
		public static ECPoint ShamirsTrick(
			ECPoint		P,
			BigInteger	k,
			ECPoint		Q,
			BigInteger	l)
		{
			if (!P.Curve.Equals(Q.Curve))
				throw new ArgumentException("P and Q must be on same curve");

			return ImplShamirsTrick(P, k, Q, l);
		}
		public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a,
			ECPoint Q, BigInteger b)
		{
			ECCurve c = P.Curve;
			if (!c.Equals(Q.Curve))
				throw new ArgumentException("P and Q must be on same curve");

/*
            // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
			if (c is F2mCurve)
			{
				F2mCurve f2mCurve = (F2mCurve) c;
				if (f2mCurve.IsKoblitz)
				{
					return P.Multiply(a).Add(Q.Multiply(b));
				}
			}
*/
			return ImplShamirsTrick(P, a, Q, b);
		}
		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());
        }
Example #7
0
		// D.3.2 pg 102 (see Note:)
		public override ECPoint Subtract(
			ECPoint b)
		{
			if (b.IsInfinity)
				return this;

			// Add -b
			return Add(b.Negate());
		}
Example #8
0
		// B.3 pg 62
		public override ECPoint Add(
			ECPoint b)
		{
			if (this.IsInfinity)
				return b;

			if (b.IsInfinity)
				return this;

			// Check if b = this or b = -this
			if (this.x.Equals(b.x))
			{
				if (this.y.Equals(b.y))
				{
					// this = b, i.e. this must be doubled
					return this.Twice();
				}

				Debug.Assert(this.y.Equals(b.y.Negate()));

				// this = -b, i.e. the result is the point at infinity
				return this.curve.Infinity;
			}

			ECFieldElement gamma = b.y.Subtract(this.y).Divide(b.x.Subtract(this.x));

			ECFieldElement x3 = gamma.Square().Subtract(this.x).Subtract(b.x);
			ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y);

			return new FpPoint(curve, x3, y3);
		}
Example #9
0
		public abstract ECPoint Subtract(ECPoint b);
Example #10
0
		public abstract ECPoint Add(ECPoint b);
		/**
		* Multiplies <code>this</code> by an integer <code>k</code> using the
		* Window NAF method.
		* @param k The integer by which <code>this</code> is multiplied.
		* @return A new <code>ECPoint</code> which equals <code>this</code>
		* multiplied by <code>k</code>.
		*/
		public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
		{
			WNafPreCompInfo wnafPreCompInfo;

			if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
			{
				wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
			}
			else
			{
				// Ignore empty PreCompInfo or PreCompInfo of incorrect type
				wnafPreCompInfo = new WNafPreCompInfo();
			}

			// floor(log2(k))
			int m = k.BitLength;

			// width of the Window NAF
			sbyte width;

			// Required length of precomputation array
			int reqPreCompLen;

			// Determine optimal width and corresponding length of precomputation
			// array based on literature values
			if (m < 13)
			{
				width = 2;
				reqPreCompLen = 1;
			}
			else
			{
				if (m < 41)
				{
					width = 3;
					reqPreCompLen = 2;
				}
				else
				{
					if (m < 121)
					{
						width = 4;
						reqPreCompLen = 4;
					}
					else
					{
						if (m < 337)
						{
							width = 5;
							reqPreCompLen = 8;
						}
						else
						{
							if (m < 897)
							{
								width = 6;
								reqPreCompLen = 16;
							}
							else
							{
								if (m < 2305)
								{
									width = 7;
									reqPreCompLen = 32;
								}
								else 
								{
									width = 8;
									reqPreCompLen = 127;
								}
							}
						}
					}
				}
			}

			// The length of the precomputation array
			int preCompLen = 1;

			ECPoint[] preComp = wnafPreCompInfo.GetPreComp();
			ECPoint twiceP = wnafPreCompInfo.GetTwiceP();

			// Check if the precomputed ECPoints already exist
			if (preComp == null)
			{
				// Precomputation must be performed from scratch, create an empty
				// precomputation array of desired length
				preComp = new ECPoint[]{ p };
			}
			else
			{
				// Take the already precomputed ECPoints to start with
				preCompLen = preComp.Length;
			}

			if (twiceP == null)
			{
				// Compute twice(p)
				twiceP = p.Twice();
			}

			if (preCompLen < reqPreCompLen)
			{
				// Precomputation array must be made bigger, copy existing preComp
				// array into the larger new preComp array
				ECPoint[] oldPreComp = preComp;
				preComp = new ECPoint[reqPreCompLen];
				Array.Copy(oldPreComp, 0, preComp, 0, preCompLen);

				for (int i = preCompLen; i < reqPreCompLen; i++)
				{
					// Compute the new ECPoints for the precomputation array.
					// The values 1, 3, 5, ..., 2^(width-1)-1 times p are
					// computed
					preComp[i] = twiceP.Add(preComp[i - 1]);
				}            
			}

			// Compute the Window NAF of the desired width
			sbyte[] wnaf = WindowNaf(width, k);
			int l = wnaf.Length;

			// Apply the Window NAF to p using the precomputed ECPoint values.
			ECPoint q = p.Curve.Infinity;
			for (int i = l - 1; i >= 0; i--)
			{
				q = q.Twice();

				if (wnaf[i] != 0)
				{
					if (wnaf[i] > 0)
					{
						q = q.Add(preComp[(wnaf[i] - 1)/2]);
					}
					else
					{
						// wnaf[i] < 0
						q = q.Subtract(preComp[(-wnaf[i] - 1)/2]);
					}
				}
			}

			// Set PreCompInfo in ECPoint, such that it is available for next
			// multiplication.
			wnafPreCompInfo.SetPreComp(preComp);
			wnafPreCompInfo.SetTwiceP(twiceP);
			p.SetPreCompInfo(wnafPreCompInfo);
			return q;
		}
Example #12
0
        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));
            }
            }
        }
Example #13
0
        // 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");
            }
            }
        }
Example #14
0
 public virtual ECPoint TwicePlus(ECPoint b)
 {
     return(Twice().Add(b));
 }
Example #15
0
 public abstract ECPoint Subtract(ECPoint b);
Example #16
0
 public abstract ECPoint Add(ECPoint b);