Пример #1
0
 private static void PointSetNeutral(PointExt p)
 {
     X25519Field.Zero(p.x);
     X25519Field.One(p.y);
     X25519Field.One(p.z);
     X25519Field.Zero(p.t);
 }
Пример #2
0
 private static void Decode32(Span <byte> bs, int bsOff, Span <uint> n, int nOff, int nLen)
 {
     for (int i = 0; i < nLen; ++i)
     {
         n[nOff + i] = X25519Field.Decode32(bs, bsOff + i * 4);
     }
 }
Пример #3
0
        private static PointExt PointCopy(PointAccum p)
        {
            PointExt r = new PointExt();

            X25519Field.Copy(p.x, 0, r.x, 0);
            X25519Field.Copy(p.y, 0, r.y, 0);
            X25519Field.Copy(p.z, 0, r.z, 0);
            X25519Field.Mul(p.u, p.v, r.t);
            return(r);
        }
Пример #4
0
        private static void DecodeScalar(ReadOnlySpan <byte> k, int kOff, Span <uint> n)
        {
            for (int i = 0; i < 8; ++i)
            {
                n[i] = X25519Field.Decode32(k, kOff + i * 4);
            }

            n[0] &= 0xFFFFFFF8U;
            n[7] &= 0x7FFFFFFFU;
            n[7] |= 0x40000000U;
        }
Пример #5
0
        private static void PointDouble(Span <int> x, Span <int> z)
        {
            Span <int> A = stackalloc int[X25519Field.Size];
            Span <int> B = stackalloc int[X25519Field.Size];

            X25519Field.Apm(x, z, A, B);
            X25519Field.Sqr(A, A);
            X25519Field.Sqr(B, B);
            X25519Field.Mul(A, B, x);
            X25519Field.Sub(A, B, A);
            X25519Field.Mul(A, C_A24, z);
            X25519Field.Add(z, B, z);
            X25519Field.Mul(z, A, z);
        }
Пример #6
0
        private static void ScalarMultBase(ReadOnlySpan <byte> k, int kOff, Span <byte> r, int rOff)
        {
            Span <int> y = stackalloc int[X25519Field.Size];
            Span <int> z = stackalloc int[X25519Field.Size];

            Ed25519.ScalarMultBaseYZ(k, kOff, y, z);

            X25519Field.Apm(z, y, y, z);

            X25519Field.Inv(z, z);
            X25519Field.Mul(y, z, y);

            X25519Field.Normalize(y);
            X25519Field.Encode(y, r, rOff);
        }
Пример #7
0
        private static int CheckPoint(Span <int> x, Span <int> y, Span <int> z)
        {
            Span <int> t = stackalloc int[X25519Field.Size];
            Span <int> u = stackalloc int[X25519Field.Size];
            Span <int> v = stackalloc int[X25519Field.Size];
            Span <int> w = stackalloc int[X25519Field.Size];

            X25519Field.Sqr(x, u);
            X25519Field.Sqr(y, v);
            X25519Field.Sqr(z, w);
            X25519Field.Mul(u, v, t);
            X25519Field.Sub(v, u, v);
            X25519Field.Mul(v, w, v);
            X25519Field.Sqr(w, w);
            X25519Field.Mul(t, C_d, t);
            X25519Field.Add(t, w, t);
            X25519Field.Sub(t, v, t);
            X25519Field.Normalize(t);

            return(X25519Field.IsZero(t));
        }
Пример #8
0
        private static void PointAddVar(bool negate, PointExt p, PointExt q, PointExt r)
        {
            int[] A = new int[X25519Field.Size];
            int[] B = new int[X25519Field.Size];
            int[] C = new int[X25519Field.Size];
            int[] D = new int[X25519Field.Size];
            int[] E = new int[X25519Field.Size];
            int[] F = new int[X25519Field.Size];
            int[] G = new int[X25519Field.Size];
            int[] H = new int[X25519Field.Size];

            int[] c, d, f, g;
            if (negate)
            {
                c = D; d = C; f = G; g = F;
            }
            else
            {
                c = C; d = D; f = F; g = G;
            }

            X25519Field.Apm(p.y, p.x, B, A);
            X25519Field.Apm(q.y, q.x, d, c);
            X25519Field.Mul(A, C, A);
            X25519Field.Mul(B, D, B);
            X25519Field.Mul(p.t, q.t, C);
            X25519Field.Mul(C, C_d2, C);
            X25519Field.Mul(p.z, q.z, D);
            X25519Field.Add(D, D, D);
            X25519Field.Apm(B, A, H, E);
            X25519Field.Apm(D, C, g, f);
            X25519Field.Carry(g);
            X25519Field.Mul(E, F, r.x);
            X25519Field.Mul(G, H, r.y);
            X25519Field.Mul(F, G, r.z);
            X25519Field.Mul(E, H, r.t);
        }
Пример #9
0
        private static void PointDouble(PointAccum r)
        {
            int[] A = new int[X25519Field.Size];
            int[] B = new int[X25519Field.Size];
            int[] C = new int[X25519Field.Size];
            int[] E = r.u;
            int[] F = new int[X25519Field.Size];
            int[] G = new int[X25519Field.Size];
            int[] H = r.v;

            X25519Field.Sqr(r.x, A);
            X25519Field.Sqr(r.y, B);
            X25519Field.Sqr(r.z, C);
            X25519Field.Add(C, C, C);
            X25519Field.Apm(A, B, H, G);
            X25519Field.Add(r.x, r.y, E);
            X25519Field.Sqr(E, E);
            X25519Field.Sub(H, E, E);
            X25519Field.Add(C, G, F);
            X25519Field.Carry(F);
            X25519Field.Mul(E, F, r.x);
            X25519Field.Mul(G, H, r.y);
            X25519Field.Mul(F, G, r.z);
        }
Пример #10
0
 private static void PointExtendXY(PointAccum p)
 {
     X25519Field.One(p.z);
     X25519Field.Copy(p.x, 0, p.u, 0);
     X25519Field.Copy(p.y, 0, p.v, 0);
 }
Пример #11
0
        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;
                }
            }
        }
Пример #12
0
        private static void ScalarMultBase(Span <byte> k, Span <int> y, Span <int> z)
        {
            Span <int> rx = stackalloc int[X25519Field.Size];
            Span <int> ry = stackalloc int[X25519Field.Size];
            Span <int> rz = stackalloc int[X25519Field.Size];
            Span <int> ru = stackalloc int[X25519Field.Size];
            Span <int> rv = stackalloc int[X25519Field.Size];

            X25519Field.Zero(rx);
            X25519Field.One(ry);
            X25519Field.One(rz);
            X25519Field.Zero(ru);
            X25519Field.One(rv);

            Span <uint> n = stackalloc uint[ScalarUints];

            DecodeScalar(k, 0, n);

            {
                uint c1 = CAdd(ScalarUints, ~(int)n[0] & 1, n, L, n);
                uint c2 = ShiftDownBit(ScalarUints, n, 1U);

                for (int i = 0; i < ScalarUints; ++i)
                {
                    n[i] = Shuffle2(n[i]);
                }
            }

            Span <int> pypx_h = stackalloc int[X25519Field.Size];
            Span <int> pymx_h = stackalloc int[X25519Field.Size];
            Span <int> pxyd   = stackalloc int[X25519Field.Size];

            int cOff = (PrecompSpacing - 1) * PrecompTeeth;

            Span <int> A = stackalloc int[X25519Field.Size];
            Span <int> B = stackalloc int[X25519Field.Size];
            Span <int> C = stackalloc int[X25519Field.Size];
            Span <int> E = stackalloc int[X25519Field.Size];
            Span <int> F = stackalloc int[X25519Field.Size];
            Span <int> G = stackalloc int[X25519Field.Size];
            Span <int> H = stackalloc int[X25519Field.Size];

            Span <int> pdA = stackalloc int[X25519Field.Size];
            Span <int> pdB = stackalloc int[X25519Field.Size];
            Span <int> pdC = stackalloc int[X25519Field.Size];
            Span <int> pdE = stackalloc int[X25519Field.Size];
            Span <int> pdF = stackalloc int[X25519Field.Size];
            Span <int> pdG = stackalloc int[X25519Field.Size];
            Span <int> pdH = stackalloc int[X25519Field.Size];

            for (; ;)
            {
                for (int b = 0; b < PrecompBlocks; ++b)
                {
                    uint w    = n[b] >> cOff;
                    int  sign = (int)(w >> (PrecompTeeth - 1)) & 1;
                    int  abs  = ((int)w ^ -sign) & PrecompMask;

                    int off = b * PrecompPoints * 3 * X25519Field.Size;

                    for (int i = 0; i < PrecompPoints; ++i)
                    {
                        int cond = ((i ^ abs) - 1) >> 31;
                        X25519Field.CMov(cond, precompBase, off, pypx_h, 0); off += X25519Field.Size;
                        X25519Field.CMov(cond, precompBase, off, pymx_h, 0); off += X25519Field.Size;
                        X25519Field.CMov(cond, precompBase, off, pxyd, 0); off   += X25519Field.Size;
                    }

                    X25519Field.CSwap(sign, pypx_h, pymx_h);
                    X25519Field.CNegate(sign, pxyd);

                    A.Clear();
                    B.Clear();
                    C.Clear();
                    E = ru;
                    F.Clear();
                    G.Clear();
                    H = rv;

                    X25519Field.Apm(ry, rx, B, A);
                    X25519Field.Mul(A, pymx_h, A);
                    X25519Field.Mul(B, pypx_h, B);
                    X25519Field.Mul(ru, rv, C);
                    X25519Field.Mul(C, pxyd, C);
                    X25519Field.Apm(B, A, H, E);
                    X25519Field.Apm(rz, C, G, F);
                    X25519Field.Carry(G);
                    X25519Field.Mul(E, F, rx);
                    X25519Field.Mul(G, H, ry);
                    X25519Field.Mul(F, G, rz);
                }

                if ((cOff -= PrecompTeeth) < 0)
                {
                    break;
                }

                pdA.Clear();
                pdB.Clear();
                pdC.Clear();
                pdE = ru;
                pdF.Clear();
                pdG.Clear();
                pdH = rv;

                X25519Field.Sqr(rx, pdA);
                X25519Field.Sqr(ry, pdB);
                X25519Field.Sqr(rz, pdC);
                X25519Field.Add(pdC, pdC, pdC);
                X25519Field.Apm(pdA, pdB, pdH, pdG);
                X25519Field.Add(rx, ry, pdE);
                X25519Field.Sqr(pdE, pdE);
                X25519Field.Sub(pdH, pdE, pdE);
                X25519Field.Add(pdC, pdG, pdF);
                X25519Field.Carry(pdF);
                X25519Field.Mul(pdE, pdF, rx);
                X25519Field.Mul(pdG, pdH, ry);
                X25519Field.Mul(pdF, pdG, rz);
            }

            if (0 == CheckPoint(rx, ry, rz))
            {
                throw new InvalidOperationException();
            }

            X25519Field.Copy(ry, 0, y, 0);
            X25519Field.Copy(rz, 0, z, 0);
        }
Пример #13
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);
        }