private static void Precompute()
        {
            PointAccum p = new PointAccum();

            X25519Field.Copy(B_x, 0, p.x, 0);
            X25519Field.Copy(B_y, 0, p.y, 0);

            PointExtendXY(p);

            precompBase = new int[PrecompBlocks * PrecompPoints * 3 * X25519Field.Size];

            int off = 0;

            for (int b = 0; b < PrecompBlocks; ++b)
            {
                PointExt[] ds  = new PointExt[PrecompTeeth];
                PointExt   sum = new PointExt();
                PointSetNeutral(sum);

                for (int t = 0; t < PrecompTeeth; ++t)
                {
                    PointExt q = PointCopy(p);
                    PointAddVar(true, sum, q, sum);
                    PointDouble(p);

                    ds[t] = PointCopy(p);

                    if (b + t != PrecompBlocks + PrecompTeeth - 2)
                    {
                        for (int s = 1; s < PrecompSpacing; ++s)
                        {
                            PointDouble(p);
                        }
                    }
                }

                PointExt[] points = new PointExt[PrecompPoints];
                int        k      = 0;
                points[k++] = sum;

                for (int t = 0; t < (PrecompTeeth - 1); ++t)
                {
                    int size = 1 << t;
                    for (int j = 0; j < size; ++j, ++k)
                    {
                        PointAddVar(false, points[k - size], ds[t], points[k] = new PointExt());
                    }
                }

                for (int i = 0; i < PrecompPoints; ++i)
                {
                    PointExt q = points[i];

                    int[] x = new int[X25519Field.Size];
                    int[] y = new int[X25519Field.Size];

                    X25519Field.Add(q.z, q.z, x);
                    X25519Field.Inv(x, y);
                    X25519Field.Mul(q.x, y, x);
                    X25519Field.Mul(q.y, y, y);

                    PointPrecomp r = new PointPrecomp();
                    X25519Field.Apm(y, x, r.ypx_h, r.ymx_h);
                    X25519Field.Mul(x, y, r.xyd);
                    X25519Field.Mul(r.xyd, C_d4, r.xyd);

                    X25519Field.Normalize(r.ypx_h);
                    X25519Field.Normalize(r.ymx_h);

                    X25519Field.Copy(r.ypx_h, 0, precompBase, off); off += X25519Field.Size;
                    X25519Field.Copy(r.ymx_h, 0, precompBase, off); off += X25519Field.Size;
                    X25519Field.Copy(r.xyd, 0, precompBase, off); off   += X25519Field.Size;
                }
            }
        }
Exemple #2
0
        private static void ScalarMult(ReadOnlySpan <byte> k, int kOff, ReadOnlySpan <byte> u, int uOff, Span <byte> r, int rOff)
        {
            Span <uint> n = stackalloc uint[8];

            DecodeScalar(k, kOff, n);

            Span <int> x1 = stackalloc int[X25519Field.Size];

            X25519Field.Decode(u, uOff, x1);
            Span <int> x2 = stackalloc int[X25519Field.Size];

            X25519Field.Copy(x1, 0, x2, 0);
            Span <int> z2 = stackalloc int[X25519Field.Size];

            z2[0] = 1;
            Span <int> x3 = stackalloc int[X25519Field.Size];

            x3[0] = 1;
            Span <int> z3 = stackalloc int[X25519Field.Size];

            Span <int> t1 = stackalloc int[X25519Field.Size];
            Span <int> t2 = stackalloc int[X25519Field.Size];

            int bit = 254, swap = 1;

            do
            {
                X25519Field.Apm(x3, z3, t1, x3);
                X25519Field.Apm(x2, z2, z3, x2);
                X25519Field.Mul(t1, x2, t1);
                X25519Field.Mul(x3, z3, x3);
                X25519Field.Sqr(z3, z3);
                X25519Field.Sqr(x2, x2);

                X25519Field.Sub(z3, x2, t2);
                X25519Field.Mul(t2, C_A24, z2);
                X25519Field.Add(z2, x2, z2);
                X25519Field.Mul(z2, t2, z2);
                X25519Field.Mul(x2, z3, x2);

                X25519Field.Apm(t1, x3, x3, z3);
                X25519Field.Sqr(x3, x3);
                X25519Field.Sqr(z3, z3);
                X25519Field.Mul(z3, x1, z3);

                --bit;

                int word = bit >> 5, shift = bit & 0x1F;
                int kt = (int)(n[word] >> shift) & 1;
                swap ^= kt;
                X25519Field.CSwap(swap, x2, x3);
                X25519Field.CSwap(swap, z2, z3);
                swap = kt;
            }while (bit >= 3);

            for (int i = 0; i < 3; ++i)
            {
                PointDouble(x2, z2);
            }

            X25519Field.Inv(z2, z2);
            X25519Field.Mul(x2, z2, x2);

            X25519Field.Normalize(x2);
            X25519Field.Encode(x2, r, rOff);
        }