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;
		}
		/**
		* Computes the Window NAF (non-adjacent Form) of an integer.
		* @param width The width <code>w</code> of the Window NAF. The width is
		* defined as the minimal number <code>w</code>, such that for any
		* <code>w</code> consecutive digits in the resulting representation, at
		* most one is non-zero.
		* @param k The integer of which the Window NAF is computed.
		* @return The Window NAF of the given width, such that the following holds:
		* <code>k = &#8722;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
		* </code>, where the <code>k<sub>i</sub></code> denote the elements of the
		* returned <code>sbyte[]</code>.
		*/
		public sbyte[] WindowNaf(sbyte width, BigInteger k)
		{
			// The window NAF is at most 1 element longer than the binary
			// representation of the integer k. sbyte can be used instead of short or
			// int unless the window width is larger than 8. For larger width use
			// short or int. However, a width of more than 8 is not efficient for
			// m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
			// 1000 Bits are currently not used in practice.
			sbyte[] wnaf = new sbyte[k.BitLength + 1];

			// 2^width as short and BigInteger
			short pow2wB = (short)(1 << width);
			BigInteger pow2wBI = BigInteger.ValueOf(pow2wB);

			int i = 0;

			// The actual length of the WNAF
			int length = 0;

			// while k >= 1
			while (k.SignValue > 0)
			{
				// if k is odd
				if (k.TestBit(0))
				{
					// k Mod 2^width
					BigInteger remainder = k.Mod(pow2wBI);

					// if remainder > 2^(width - 1) - 1
					if (remainder.TestBit(width - 1))
					{
						wnaf[i] = (sbyte)(remainder.IntValue - pow2wB);
					}
					else
					{
						wnaf[i] = (sbyte)remainder.IntValue;
					}
					// wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]

					k = k.Subtract(BigInteger.ValueOf(wnaf[i]));
					length = i;
				}
				else
				{
					wnaf[i] = 0;
				}

				// k = k/2
				k = k.ShiftRight(1);
				i++;
			}

			length++;

			// Reduce the WNAF array to its actual length
			sbyte[] wnafShort = new sbyte[length];
			Array.Copy(wnaf, 0, wnafShort, 0, length);
			return wnafShort;
		}
        public ECDomainParameters(
            ECCurve     curve,
            ECPoint     g,
            BigInteger  n,
            BigInteger  h)
			: this(curve, g, n, h, null)
		{
        }
		public FpFieldElement(
			BigInteger	q,
			BigInteger	x)
		{
			if (x.CompareTo(q) >= 0)
				throw new ArgumentException("x value too large in field element");

			this.q = q;
			this.x = x;
		}
		/*
		* "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);
		}
Esempio n. 7
0
        /// <summary>
        /// BigInteger inverse with respect to addition.
        /// </summary>
        /// <param name="n">The BigInteger whose opposite is to be computed</param>
        /// <returns>The BigInteger inverse with respect to addition</returns>
        public static BigInteger Opposite(BigInteger n)
        {
            BigInteger result = n;

            if (result != Zero)
            {
                if (result.sign == -1)
                    result.sign = 1;
                else
                    result.sign = 1;
            }
            result.SetEven();
            return result;
        }
		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 static byte[] IntegerToBytes(
			BigInteger	s,
			int			qLength)
		{
			byte[] bytes = s.ToByteArrayUnsigned();

			if (qLength < bytes.Length)
			{
				byte[] tmp = new byte[qLength];
				Array.Copy(bytes, bytes.Length - tmp.Length, tmp, 0, tmp.Length);
				return tmp;
			}
			else if (qLength > bytes.Length)
			{
				byte[] tmp = new byte[qLength];
				Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
				return tmp;
			}

			return bytes;
		}
		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());
        }
		// D.1.4 91
		/**
		 * return a sqrt root - the routine verifies that the calculation
		 * returns the right value - if none exists it returns null.
		 */
		public override ECFieldElement Sqrt()
		{
			if (!q.TestBit(0))
				throw new NotImplementedException("even value of q");

			// p mod 4 == 3
			if (q.TestBit(1))
			{
				// TODO Can this be optimised (inline the Square?)
				// z = g^(u+1) + p, p = 4u + 3
				ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q));

				return z.Square().Equals(this) ? z : null;
			}

			// p mod 4 == 1
			BigInteger qMinusOne = q.Subtract(BigInteger.One);

			BigInteger legendreExponent = qMinusOne.ShiftRight(1);
			if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
				return null;

			BigInteger u = qMinusOne.ShiftRight(2);
			BigInteger k = u.ShiftLeft(1).Add(BigInteger.One);

			BigInteger Q = this.x;
			BigInteger fourQ = Q.ShiftLeft(2).Mod(q);

			BigInteger U, V;
			do
			{
				Random rand = new Random();
				BigInteger P;
				do
				{
					P = new BigInteger(q.BitLength, rand);
				}
				while (P.CompareTo(q) >= 0
					|| !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne)));

				BigInteger[] result = fastLucasSequence(q, P, Q, k);
				U = result[0];
				V = result[1];

				if (V.Multiply(V).Mod(q).Equals(fourQ))
				{
					// Integer division by 2, mod q
					if (V.TestBit(0))
					{
						V = V.Add(q);
					}

					V = V.ShiftRight(1);

					Debug.Assert(V.Multiply(V).Mod(q).Equals(x));

					return new FpFieldElement(q, V);
				}
			}
			while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));

			return null;


//			BigInteger qMinusOne = q.Subtract(BigInteger.One);
//
//			BigInteger legendreExponent = qMinusOne.ShiftRight(1);
//			if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
//				return null;
//
//			Random rand = new Random();
//			BigInteger fourX = x.ShiftLeft(2);
//
//			BigInteger r;
//			do
//			{
//				r = new BigInteger(q.BitLength, rand);
//			}
//			while (r.CompareTo(q) >= 0
//				|| !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne)));
//
//			BigInteger n1 = qMinusOne.ShiftRight(2);
//			BigInteger n2 = n1.Add(BigInteger.One);
//
//			BigInteger wOne = WOne(r, x, q);
//			BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q);
//			BigInteger twoR = r.ShiftLeft(1);
//
//			BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q)
//				.Multiply(x).Mod(q)
//				.Multiply(wSum).Mod(q);
//
//			return new FpFieldElement(q, root);
		}
Esempio n. 12
0
		/**
		 * Multiplies this <code>ECPoint</code> by the given number.
		 * @param k The multiplicator.
		 * @return <code>k * this</code>.
		 */
		public override ECPoint Multiply(
			BigInteger k)
		{
			if (k.SignValue < 0)
				throw new ArgumentException("The multiplicator cannot be negative", "k");

			if (this.IsInfinity)
				return this;

			if (k.SignValue == 0)
				return this.curve.Infinity;

			AssertECMultiplier();
			return this.multiplier.Multiply(this, k, preCompInfo);
		}
Esempio n. 13
0
		public abstract ECPoint Multiply(BigInteger b);
Esempio n. 14
0
		/**
		 * Decode a point on this curve from its ASN.1 encoding. The different
		 * encodings are taken account of, including point compression for
		 * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
		 * @return The decoded point.
		 */
		public override ECPoint DecodePoint(
			byte[] encoded)
		{
			ECPoint p = null;
			int expectedLength = (FieldSize + 7) / 8;

			switch (encoded[0])
			{
				case 0x00: // infinity
				{
					if (encoded.Length != 1)
						throw new ArgumentException("Incorrect length for infinity encoding", "encoded");

					p = Infinity;
					break;
				}

				case 0x02: // compressed
				case 0x03: // compressed
				{
					if (encoded.Length != (expectedLength + 1))
						throw new ArgumentException("Incorrect length for compressed encoding", "encoded");

					int yTilde = encoded[0] & 1;
					BigInteger X1 = new BigInteger(1, encoded, 1, encoded.Length - 1);

					p = DecompressPoint(yTilde, X1);
					break;
				}

				case 0x04: // uncompressed
				case 0x06: // hybrid
				case 0x07: // hybrid
				{
					if (encoded.Length != (2 * expectedLength + 1))
						throw new ArgumentException("Incorrect length for uncompressed/hybrid encoding", "encoded");

					BigInteger X1 = new BigInteger(1, encoded, 1, expectedLength);
					BigInteger Y1 = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);

					p = CreatePoint(X1, Y1, false);
					break;
				}

				default:
					throw new FormatException("Invalid point encoding " + encoded[0]);
			}

			return p;
		}
Esempio n. 15
0
		public BigInteger And(
			BigInteger value)
		{
			if (this.sign == 0 || value.sign == 0)
			{
				return Zero;
			}

			int[] aMag = this.sign > 0
				? this.magnitude
				: Add(One).magnitude;

			int[] bMag = value.sign > 0
				? value.magnitude
				: value.Add(One).magnitude;

			bool resultNeg = sign < 0 && value.sign < 0;
			int resultLength = System.Math.Max(aMag.Length, bMag.Length);
			int[] resultMag = new int[resultLength];

			int aStart = resultMag.Length - aMag.Length;
			int bStart = resultMag.Length - bMag.Length;

			for (int i = 0; i < resultMag.Length; ++i)
			{
				int aWord = i >= aStart ? aMag[i - aStart] : 0;
				int bWord = i >= bStart ? bMag[i - bStart] : 0;

				if (this.sign < 0)
				{
					aWord = ~aWord;
				}

				if (value.sign < 0)
				{
					bWord = ~bWord;
				}

				resultMag[i] = aWord & bWord;

				if (resultNeg)
				{
					resultMag[i] = ~resultMag[i];
				}
			}

			BigInteger result = new BigInteger(1, resultMag, true);

			// TODO Optimise this case
			if (resultNeg)
			{
				result = result.Not();
			}

			return result;
		}
Esempio n. 16
0
		protected internal override ECPoint DecompressPoint(
			int			yTilde,
			BigInteger	X1)
		{
			ECFieldElement x = FromBigInteger(X1);
			ECFieldElement alpha = x.Multiply(x.Square().Add(a)).Add(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");

			BigInteger betaValue = beta.ToBigInteger();
			int bit0 = betaValue.TestBit(0) ? 1 : 0;

			if (bit0 != yTilde)
			{
				// Use the other root
				beta = FromBigInteger(q.Subtract(betaValue));
			}

			return new FpPoint(this, x, beta, true);
		}
Esempio n. 17
0
 public static BigInteger Pow(BigInteger a, int exponent)
 {
     BigInteger result = a.Pow(exponent);
     result.SetEven();
     return result;
 }
Esempio n. 18
0
		public override ECFieldElement FromBigInteger(BigInteger x)
        {
            return new FpFieldElement(this.q, x);
        }
Esempio n. 19
0
		public BigInteger Subtract(
			BigInteger n)
		{
			if (n.sign == 0)
				return this;

			if (this.sign == 0)
				return n.Negate();

			if (this.sign != n.sign)
				return Add(n.Negate());

			int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
			if (compare == 0)
				return Zero;

			BigInteger bigun, lilun;
			if (compare < 0)
			{
				bigun = n;
				lilun = this;
			}
			else
			{
				bigun = this;
				lilun = n;
			}

			return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
		}
Esempio n. 20
0
		public FpCurve(BigInteger q, BigInteger a, BigInteger b)
        {
            this.q = q;
            this.a = FromBigInteger(a);
            this.b = FromBigInteger(b);
			this.infinity = new FpPoint(this, null, null);
        }
Esempio n. 21
0
		private static BigInteger createUValueOf(
			ulong value)
		{
			int msw = (int)(value >> 32);
			int lsw = (int)value;

			if (msw != 0)
				return new BigInteger(1, new int[] { msw, lsw }, false);

			if (lsw != 0)
			{
				BigInteger n = new BigInteger(1, new int[] { lsw }, false);
				// Check for a power of two
				if ((lsw & -lsw) == lsw)
				{
					n.nBits = 1;
				}
				return n;
			}

			return Zero;
		}
		/**
		* 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;
		}
//		private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p)
//		{
//			if (n.Equals(BigInteger.One))
//				return wOne;
//
//			bool isEven = !n.TestBit(0);
//			n = n.ShiftRight(1);
//			if (isEven)
//			{
//				BigInteger w = W(n, wOne, p);
//				return w.Multiply(w).Subtract(BigInteger.Two).Mod(p);
//			}
//			BigInteger w1 = W(n.Add(BigInteger.One), wOne, p);
//			BigInteger w2 = W(n, wOne, p);
//			return w1.Multiply(w2).Subtract(wOne).Mod(p);
//		}
//
//		private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p)
//		{
//			return r.Multiply(r).Multiply(x.ModPow(q.Subtract(BigInteger.Two), q)).Subtract(BigInteger.Two).Mod(p);
//		}

		private static BigInteger[] fastLucasSequence(
			BigInteger	p,
			BigInteger	P,
			BigInteger	Q,
			BigInteger	k)
		{
			// TODO Research and apply "common-multiplicand multiplication here"

			int n = k.BitLength;
			int s = k.GetLowestSetBit();

			Debug.Assert(k.TestBit(s));

			BigInteger Uh = BigInteger.One;
			BigInteger Vl = BigInteger.Two;
			BigInteger Vh = P;
			BigInteger Ql = BigInteger.One;
			BigInteger Qh = BigInteger.One;

			for (int j = n - 1; j >= s + 1; --j)
			{
				Ql = Ql.Multiply(Qh).Mod(p);

				if (k.TestBit(j))
				{
					Qh = Ql.Multiply(Q).Mod(p);
					Uh = Uh.Multiply(Vh).Mod(p);
					Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p);
					Vh = Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)).Mod(p);
				}
				else
				{
					Qh = Ql;
					Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p);
					Vh = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p);
					Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p);
				}
			}

			Ql = Ql.Multiply(Qh).Mod(p);
			Qh = Ql.Multiply(Q).Mod(p);
			Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p);
			Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p);
			Ql = Ql.Multiply(Qh).Mod(p);

			for (int j = 1; j <= s; ++j)
			{
				Uh = Uh.Multiply(Vl).Mod(p);
				Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p);
				Ql = Ql.Multiply(Ql).Mod(p);
			}

			return new BigInteger[]{ Uh, Vl };
		}
Esempio n. 24
0
		public abstract ECFieldElement FromBigInteger(BigInteger x);
Esempio n. 25
0
        public static BigInteger DivRem(BigInteger i1, BigInteger i2, out BigInteger i3)
        {
            BigInteger[] result = i1.DivideAndRemainder(i2);

            i3 = result[1];
            return result[0];
        }
Esempio n. 26
0
		public abstract ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression);
Esempio n. 27
0
		public BigInteger ShiftLeft(
			int n)
		{
			if (sign == 0 || magnitude.Length == 0)
				return Zero;

			if (n == 0)
				return this;

			if (n < 0)
				return ShiftRight(-n);

			BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true);

			if (this.nBits != -1)
			{
				result.nBits = sign > 0
					?	this.nBits
					:	this.nBits + n;
			}

			if (this.nBitLength != -1)
			{
				result.nBitLength = this.nBitLength + n;
			}

			return result;
		}
Esempio n. 28
0
		protected internal abstract ECPoint DecompressPoint(int yTilde, BigInteger X1);
Esempio n. 29
0
		public override ECPoint CreatePoint(
			BigInteger	X1,
			BigInteger	Y1,
			bool		withCompression)
		{
			// TODO Validation of X1, Y1?
			return new FpPoint(
				this,
				FromBigInteger(X1),
				FromBigInteger(Y1),
				withCompression);
		}
Esempio n. 30
0
		public BigInteger Add(
			BigInteger value)
		{
			if (this.sign == 0)
				return value;

			if (this.sign != value.sign)
			{
				if (value.sign == 0)
					return this;

				if (value.sign < 0)
					return Subtract(value.Negate());

				return value.Subtract(Negate());
			}

			return AddToMagnitude(value.magnitude);
		}