Beispiel #1
0
        private static GroupElementP1 Madd(ref GroupElementP3 p, ref GroupElementP4 q)
        {
            var t0 = FieldElementOperations.Add(ref p.Z, ref p.Z);             /* D = 2*Z1 */
            var r  = new GroupElementP1();

            /* YpX1 = Y1+X1 */
            r.X = FieldElementOperations.Add(ref p.Y, ref p.X);

            /* YmX1 = Y1-X1 */
            r.Y = FieldElementOperations.Sub(ref p.Y, ref p.X);

            /* A = YpX1*ypx2 */
            r.Z = FieldElementOperations.Multiplication(ref r.X, ref q.YplusX);

            /* B = YmX1*ymx2 */
            r.Y = FieldElementOperations.Multiplication(ref r.Y, ref q.YminusX);

            /* C = xy2d2*T1 */
            r.T = FieldElementOperations.Multiplication(ref q.XY2D, ref p.T);

            /* X3 = A-B */
            r.X = FieldElementOperations.Sub(ref r.Z, ref r.Y);

            /* Y3 = A+B */
            r.Y = FieldElementOperations.Add(ref r.Z, ref r.Y);

            /* Z3 = D+C */
            r.Z = FieldElementOperations.Add(ref t0, ref r.T);

            /* T3 = D-C */
            r.T = FieldElementOperations.Sub(ref t0, ref r.T);

            return(r);
        }
Beispiel #2
0
        private static GroupElementP1 P2ToP1(ref GroupElementP2 p)
        {
            var r = new GroupElementP1();

            /* XX=X1^2 */
            r.X = FieldElementOperations.Squared(ref p.X);

            /* YY=Y1^2 */
            r.Z = FieldElementOperations.Squared(ref p.Y);

            /* B=2*Z1^2 */
            r.T = FieldElementOperations.DoubleSquare(ref p.Z);

            /* A=X1+Y1 */
            r.Y = FieldElementOperations.Add(ref p.X, ref p.Y);

            /* AA=A^2 */
            var t0 = FieldElementOperations.Squared(ref r.Y);

            /* Y3=YY+XX */
            r.Y = FieldElementOperations.Add(ref r.Z, ref r.X);

            /* Z3=YY-XX */
            r.Z = FieldElementOperations.Sub(ref r.Z, ref r.X);

            /* X3=AA-Y3 */
            r.X = FieldElementOperations.Sub(ref t0, ref r.Y);

            /* T3=B-Z3 */
            r.T = FieldElementOperations.Sub(ref r.T, ref r.Z);

            return(r);
        }
Beispiel #3
0
 private static GroupElementP3 P1ToP3(ref GroupElementP1 p) => new GroupElementP3
 {
     X = FieldElementOperations.Multiplication(ref p.X, ref p.T),
     Y = FieldElementOperations.Multiplication(ref p.Y, ref p.Z),
     Z = FieldElementOperations.Multiplication(ref p.Z, ref p.T),
     T = FieldElementOperations.Multiplication(ref p.X, ref p.Y)
 };
Beispiel #4
0
        private static GroupElementP4 Select(int pos, sbyte b)
        {
            GroupElementP4 t;

            GroupElementP4 minust;
            var            bnegative = Negative(b);
            var            babs      = (byte)(b - ((-bnegative & b) << 1));

            t = new GroupElementP4
            {
                YplusX  = FieldElementOperations.Set1(),
                YminusX = FieldElementOperations.Set1(),
                XY2D    = FieldElementOperations.Set0()
            };

            var table = LookupTables.Base[pos];

            Cmov(ref t, ref table[0], Equal(babs, 1));
            Cmov(ref t, ref table[1], Equal(babs, 2));
            Cmov(ref t, ref table[2], Equal(babs, 3));
            Cmov(ref t, ref table[3], Equal(babs, 4));
            Cmov(ref t, ref table[4], Equal(babs, 5));
            Cmov(ref t, ref table[5], Equal(babs, 6));
            Cmov(ref t, ref table[6], Equal(babs, 7));
            Cmov(ref t, ref table[7], Equal(babs, 8));
            minust.YplusX  = t.YminusX;
            minust.YminusX = t.YplusX;
            minust.XY2D    = FieldElementOperations.Negate(ref t.XY2D);
            Cmov(ref t, ref minust, bnegative);

            return(t);
        }
        /// <summary>
        /// Curve25519 uses a so-called differential-addition chain proposed by Montgomery to multiply a point,
        /// identified only by its x-coordinate, by a scalar
        /// </summary>
        /// <param name="n"></param>
        /// <param name="p"></param>
        /// <param name="qSize"></param>
        /// <returns></returns>
        internal static byte[] ScalarMultiplication(byte[] n, byte[] p, int qSize)
        {
            var q  = new byte[qSize];
            var p0 = FieldElementOperations.FromBytes(p);
            var q0 = CalculateLadderStep(n, ref p0);

            FieldElementOperations.ToBytes(q, ref q0);

            return(q);
        }
Beispiel #6
0
        /// <summary>
        /// h = a * B
        /// where a = a[0]+256*a[1]+...+256^31 a[31]
        /// B is the Ed25519 base point (x,4/5) with x positive.
        ///
        /// Preconditions:
        /// a[31] <= 127
        /// </summary>
        /// <param name="a"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        internal static GroupElementP3 ScalarMultiplicationBase(byte[] a, int offset = 0)
        {
            GroupElementP3 h;

            var            e = new sbyte[64];
            sbyte          carry;
            GroupElementP1 r;
            GroupElementP2 s;
            GroupElementP4 t;
            int            i;

            for (i = 0; i < 32; ++i)
            {
                e[2 * i + 0] = (sbyte)((a[offset + i] >> 0) & 15);
                e[2 * i + 1] = (sbyte)((a[offset + i] >> 4) & 15);
            }
            /* each e[i] is between 0 and 15 */
            /* e[63] is between 0 and 7 */

            carry = 0;
            for (i = 0; i < 63; ++i)
            {
                e[i]   += carry;
                carry   = (sbyte)(e[i] + 8);
                carry >>= 4;
                e[i]   -= (sbyte)(carry << 4);
            }
            e[63] += carry;
            /* each e[i] is between -8 and 8 */

            h = new GroupElementP3
            {
                X = FieldElementOperations.Set0(),
                Y = FieldElementOperations.Set1(),
                Z = FieldElementOperations.Set1(),
                T = FieldElementOperations.Set0()
            };

            for (i = 1; i < 64; i += 2)
            {
                t = Select(i / 2, e[i]);
                r = Madd(ref h, ref t);
                h = P1ToP3(ref r);
            }

            r = P3ToP1(ref h);
            s = P1ToP2(ref r);

            r = P2ToP1(ref s);
            s = P1ToP2(ref r);

            r = P2ToP1(ref s);
            s = P1ToP2(ref r);

            r = P2ToP1(ref s);
            h = P1ToP3(ref r);

            for (i = 0; i < 64; i += 2)
            {
                t = Select(i / 2, e[i]);
                r = Madd(ref h, ref t);
                h = P1ToP3(ref r);
            }

            return(h);
        }
Beispiel #7
0
 private static void Cmov(ref GroupElementP4 t, ref GroupElementP4 u, byte b)
 {
     FieldElementOperations.Mov(ref t.YplusX, ref u.YplusX, b);
     FieldElementOperations.Mov(ref t.YminusX, ref u.YminusX, b);
     FieldElementOperations.Mov(ref t.XY2D, ref u.XY2D, b);
 }
        private static FieldElement CalculateLadderStep(byte[] n, ref FieldElement p, int noffset = 0)
        {
            var          e = new byte[32];
            uint         i;
            FieldElement x1;
            FieldElement x2;
            FieldElement z2;
            FieldElement x3;
            FieldElement z3;
            int          pos;
            uint         swap;

            for (i = 0; i < 32; ++i)
            {
                e[i] = n[noffset + i];
            }
            ClampOperation.Clamp(e, 0);
            x1 = p;
            x2 = FieldElementOperations.Set1();
            z2 = FieldElementOperations.Set0();
            x3 = x1;
            z3 = FieldElementOperations.Set1();

            swap = 0;
            for (pos = 254; pos >= 0; --pos)
            {
                var b = (uint)(e[pos / 8] >> (pos & 7));
                b    &= 1;
                swap ^= b;
                FieldElementOperations.Swap(ref x2, ref x3, swap);
                FieldElementOperations.Swap(ref z2, ref z3, swap);
                swap = b;

                /* D = X3-Z3 */
                var tmp0 = FieldElementOperations.Sub(ref x3, ref z3);

                /* B = X2-Z2 */
                var tmp1 = FieldElementOperations.Sub(ref x2, ref z2);

                /* A = X2+Z2 */
                x2 = FieldElementOperations.Add(ref x2, ref z2);

                /* C = X3+Z3 */
                z2 = FieldElementOperations.Add(ref x3, ref z3);

                /* DA = D*A */
                z3 = FieldElementOperations.Multiplication(ref tmp0, ref x2);

                /* CB = C*B */
                z2 = FieldElementOperations.Multiplication(ref z2, ref tmp1);

                /* BB = B^2 */
                tmp0 = FieldElementOperations.Squared(ref tmp1);

                /* AA = A^2 */
                tmp1 = FieldElementOperations.Squared(ref x2);

                /* t0 = DA+CB */
                x3 = FieldElementOperations.Add(ref z3, ref z2);

                /* t1 = DA-CB */
                z2 = FieldElementOperations.Sub(ref z3, ref z2);

                /* X4 = AA*BB */
                x2 = FieldElementOperations.Multiplication(ref tmp1, ref tmp0);

                /* E = AA-BB */
                tmp1 = FieldElementOperations.Sub(ref tmp1, ref tmp0);

                /* t2 = t1^2 */
                z2 = FieldElementOperations.Squared(ref z2);

                /* t3 = a24*E */
                z3 = FieldElementOperations.Multiply121666(ref tmp1);

                /* X5 = t0^2 */
                x3 = FieldElementOperations.Squared(ref x3);

                /* t4 = BB+t3 */
                tmp0 = FieldElementOperations.Add(ref tmp0, ref z3);

                /* Z5 = X1*t2 */
                z3 = FieldElementOperations.Multiplication(ref x1, ref z2);

                /* Z4 = E*t4 */
                z2 = FieldElementOperations.Multiplication(ref tmp1, ref tmp0);
            }

            FieldElementOperations.Swap(ref x2, ref x3, swap);
            FieldElementOperations.Swap(ref z2, ref z3, swap);
            z2 = FieldElementOperations.Invert(ref z2);
            x2 = FieldElementOperations.Multiplication(ref x2, ref z2);
            var q = x2;

            Array.Clear(e, 0, e.Length);
            return(q);
        }