/// <summary>
        /// Sums two projected Montgomery point using only x- and z-coordinates and knowledge of
        /// the difference.
        /// </summary>
        /// <returns>The sum of <paramref name="left"/> and
        /// <paramref name="right"/>.</returns>
        /// <param name="left">Curve point to add.</param>
        /// <param name="right">Curve point to add.</param>
        /// <param name="diff">Difference of <paramref name="left"/> and
        /// <paramref name="right"/>.</param>
        private MontgomeryCurvePoint XOnlyAdd(MontgomeryCurvePoint left, MontgomeryCurvePoint right, MontgomeryCurvePoint diff)
        {
            if (right.IsAtInfinity)
            {
                return(left);
            }
            if (left.IsAtInfinity)
            {
                return(right);
            }

            BigInteger xp = left.X;
            BigInteger xq = right.X;
            BigInteger zp = left.Z;
            BigInteger zq = right.Z;

            var xpPlusZp  = Field.Mod(xp + zp);
            var xpMinusZp = Field.Mod(xp - zp);

            var xqPlusZq  = Field.Mod(xq + zq);
            var xqMinusZq = Field.Mod(xq - zq);

            var firstProduct  = Field.Mod(xpMinusZp * xqPlusZq);
            var secondProduct = Field.Mod(xpPlusZp * xqMinusZq);

            var xNew = Field.Mod(diff.Z * Field.Square(
                                     firstProduct + secondProduct
                                     ));

            var zNew = Field.Mod(diff.X * Field.Square(
                                     firstProduct - secondProduct
                                     ));

            return(new MontgomeryCurvePoint(xNew, zNew));
        }
Beispiel #2
0
        public void TestEqualsFalseForX0AndPointAtInfinity()
        {
            var point      = new MontgomeryCurvePoint(0);
            var otherPoint = MontgomeryCurvePoint.PointAtInfinity;

            Assert.IsFalse(point.Equals(otherPoint));
        }
Beispiel #3
0
        public void TestGetHashCodeSameForEqual()
        {
            var x          = new BigInteger(3);
            var z          = new BigInteger(67);
            var point      = new MontgomeryCurvePoint(x, z);
            var otherPoint = new MontgomeryCurvePoint(x, z);

            Assert.AreEqual(point.GetHashCode(), otherPoint.GetHashCode());
        }
Beispiel #4
0
        public void TestEqualsTrueForEqual()
        {
            var x          = new BigInteger(3);
            var z          = new BigInteger(67);
            var point      = new MontgomeryCurvePoint(x, z);
            var otherPoint = new MontgomeryCurvePoint(x, z);

            Assert.IsTrue(point.Equals(otherPoint));
        }
 /// <summary>
 /// Conditionally swaps the two given curve points.
 ///
 /// This allows side-channel resistant selection by avoiding branching.
 /// The swap is made based on the value of the parameter
 /// <paramref name="swap"/>. A value of <c>BigInteger.Zero</c> means
 /// no swapping takes place, a value of <c>BigInteger.One</c> causes
 /// a swap.
 /// </summary>
 /// <returns>
 /// <c>(<paramref name="first"/>, <paramref name="second"/>)</c>
 /// if <paramref name="swap"/> is <c>false</c>; otherwise
 /// <c>(<paramref name="second"/>, <paramref name="first"/>)</c>
 /// </returns>
 /// <param name="swap">Swapping indicator.</param>
 /// <param name="first">Curve point.</param>
 /// <param name="second">Curve point.</param>
 private (MontgomeryCurvePoint, MontgomeryCurvePoint) ConditionalSwap(
     bool swap, MontgomeryCurvePoint first, MontgomeryCurvePoint second
     )
 {
     if (swap)
     {
         return(second, first);
     }
     return(first, second);
 }
Beispiel #6
0
        public void TestConstructorXOnly()
        {
            var x     = new BigInteger(5);
            var point = new MontgomeryCurvePoint(x);

            Assert.AreEqual(x, point.X);
            Assert.AreEqual(BigInteger.One, point.Z);
            Assert.IsTrue(point.IsNormalized);
            Assert.IsFalse(point.IsAtInfinity);
        }
Beispiel #7
0
        public void TestConstructor()
        {
            var x     = new BigInteger(2);
            var z     = new BigInteger(7);
            var point = new MontgomeryCurvePoint(x, z);

            Assert.AreEqual(x, point.X);
            Assert.AreEqual(z, point.Z);
            Assert.IsFalse(point.IsNormalized);
            Assert.IsFalse(point.IsAtInfinity);
        }
Beispiel #8
0
        public void TestEqualsFalseForDifferent()
        {
            var x     = new BigInteger(3);
            var z     = new BigInteger(67);
            var point = new MontgomeryCurvePoint(x, z);

            var otherPoint = new MontgomeryCurvePoint(1, z);

            Assert.IsFalse(point.Equals(otherPoint));

            otherPoint = new MontgomeryCurvePoint(8, z);
            Assert.IsFalse(point.Equals(otherPoint));
        }
        /// <summary>
        /// Doubles a projected Montgomery point using only x- and z-coordinates.
        /// </summary>
        /// <returns>The curve point.</returns>
        /// <param name="point">The doubled curve point.</param>
        private MontgomeryCurvePoint XOnlyDouble(MontgomeryCurvePoint point)
        {
            BigInteger xp = point.X;
            BigInteger zp = point.Z;

            var xpPlusZpSquared  = Field.Square(xp + zp);
            var xpMinusZpSquared = Field.Square(xp - zp);
            var xpzp4            = xpPlusZpSquared - xpMinusZpSquared;

            var xNew = Field.Mod(xpPlusZpSquared * xpMinusZpSquared);
            var zNew = Field.Mod(xpzp4 * (xpMinusZpSquared + _aConstant * xpzp4));

            return(new MontgomeryCurvePoint(xNew, zNew));
        }
        /// <inheritdoc/>
        protected override BigInteger MultiplyScalarUnchecked(BigInteger e, BigInteger k, int factorBitLength)
        {
            BigInteger maxFactor = BigInteger.One << factorBitLength;
            int        i         = factorBitLength - 1;

            MontgomeryCurvePoint point = new MontgomeryCurvePoint(e);
            MontgomeryCurvePoint r0    = MontgomeryCurvePoint.PointAtInfinity;
            MontgomeryCurvePoint r1    = point;

            // Montgomery ladder maintains invariant r1 = r0 + e
            // and can thus use x-only addition that requires knowledge of r1-r0 (= e)
            for (BigInteger mask = maxFactor >> 1; !mask.IsZero; mask = mask >> 1, --i)
            {
                BigInteger bitI = (k & mask) >> i;

                (r0, r1) = ConditionalSwap(bitI.IsOne, r0, r1);
                r1       = XOnlyAdd(r0, r1, point);
                r0       = XOnlyDouble(r0);
                (r0, r1) = ConditionalSwap(bitI.IsOne, r0, r1);
            }
            Debug.Assert(i == -1);
            return(RenormalizePoint(r0).X);
        }
 /// <summary>
 /// Renormalizes a Montgomery point by setting its z-coordinate to 1
 /// and scaling its x-coordinate accordingly.
 /// </summary>
 /// <returns>The curve point point.</returns>
 /// <param name="point">The renormalized curve point.</param>
 private MontgomeryCurvePoint RenormalizePoint(MontgomeryCurvePoint point)
 {
     return(new MontgomeryCurvePoint(
                Field.Mod(Field.InvertMult(point.Z) * point.X)
                ));
 }
 /// <summary>
 /// Compares this point for equality with another one.
 /// </summary>
 /// <param name="other">The point to compare this one to.</param>
 /// <returns>True, if either both points are points at infinity or have identical coordinates.</returns>
 public bool Equals(MontgomeryCurvePoint other)
 {
     return(X == other.X && Z == other.Z);
 }