private static int[] PointPrecompute(PointAffine p, int count)
        {
            Debug.Assert(count > 0);

            PointExt q = PointCopy(p);
            PointExt d = PointCopy(q);

            PointAdd(q, d);

            int[] table = X25519Field.CreateTable(count * 4);
            int   off   = 0;

            int i = 0;

            for (;;)
            {
                X25519Field.Copy(q.x, 0, table, off); off += X25519Field.Size;
                X25519Field.Copy(q.y, 0, table, off); off += X25519Field.Size;
                X25519Field.Copy(q.z, 0, table, off); off += X25519Field.Size;
                X25519Field.Copy(q.t, 0, table, off); off += X25519Field.Size;

                if (++i == count)
                {
                    break;
                }

                PointAdd(d, q);
            }

            return(table);
        }
示例#2
0
 private static void PointSetNeutral(PointExt p)
 {
     X25519Field.Zero(p.x);
     X25519Field.One(p.y);
     X25519Field.One(p.z);
     X25519Field.Zero(p.t);
 }
示例#3
0
 private static void PointSetNeutral(PointAccum p)
 {
     X25519Field.Zero(p.x);
     X25519Field.One(p.y);
     X25519Field.One(p.z);
     X25519Field.Zero(p.u);
     X25519Field.One(p.v);
 }
示例#4
0
        private static PointExt PointCopy(PointExt 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.Copy(p.t, 0, r.t, 0);
            return(r);
        }
示例#5
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);
        }
示例#6
0
        internal static void ScalarMultBaseYZ(byte[] k, int kOff, int[] y, int[] z)
        {
            byte[] n = new byte[ScalarBytes];
            PruneScalar(k, kOff, n);

            PointAccum p = new PointAccum();

            ScalarMultBase(n, p);
            X25519Field.Copy(p.y, 0, y, 0);
            X25519Field.Copy(p.z, 0, z, 0);
        }
示例#7
0
        private static void ScalarMultBase(byte[] k, PointAccum r)
        {
            Precompute();

            PointSetNeutral(r);

            uint[] n = new uint[ScalarUints];
            DecodeScalar(k, 0, n);

            // Recode the scalar into signed-digit form, then group comb bits in each block
            {
                uint c1 = Nat.CAdd(ScalarUints, ~(int)n[0] & 1, n, L, n); Debug.Assert(c1 == 0);
                uint c2 = Nat.ShiftDownBit(ScalarUints, n, 1U); Debug.Assert(c2 == (1U << 31));

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

            PointPrecomp p = new PointPrecomp();

            int cOff = (PrecompSpacing - 1) * PrecompTeeth;

            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;

                    Debug.Assert(sign == 0 || sign == 1);
                    Debug.Assert(0 <= abs && abs < PrecompPoints);

                    PointLookup(b, abs, p);

                    X25519Field.CSwap(sign, p.ypx_h, p.ymx_h);
                    X25519Field.CNegate(sign, p.xyd);

                    PointAddPrecomp(p, r);
                }

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

                PointDouble(r);
            }
        }
示例#8
0
        private static void EncodePoint(PointAccum p, byte[] r, int rOff)
        {
            int[] x = X25519Field.Create();
            int[] y = X25519Field.Create();

            X25519Field.Inv(p.z, y);
            X25519Field.Mul(p.x, y, x);
            X25519Field.Mul(p.y, y, y);
            X25519Field.Normalize(x);
            X25519Field.Normalize(y);

            X25519Field.Encode(y, r, rOff);
            r[rOff + PointBytes - 1] |= (byte)((x[0] & 1) << 7);
        }
示例#9
0
        private static void PointLookup(int block, int index, PointPrecomp p)
        {
            Debug.Assert(0 <= block && block < PrecompBlocks);
            Debug.Assert(0 <= index && index < PrecompPoints);

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

            for (int i = 0; i < PrecompPoints; ++i)
            {
                int cond = ((i ^ index) - 1) >> 31;
                X25519Field.CMov(cond, precompBase, off, p.ypx_h, 0);   off += X25519Field.Size;
                X25519Field.CMov(cond, precompBase, off, p.ymx_h, 0);   off += X25519Field.Size;
                X25519Field.CMov(cond, precompBase, off, p.xyd, 0);     off += X25519Field.Size;
            }
        }
示例#10
0
        internal static void ScalarMultBaseYZ(byte[] k, int kOff, int[] y, int[] z)
        {
            byte[] n = new byte[ScalarBytes];
            PruneScalar(k, kOff, n);

            PointAccum p = new PointAccum();

            ScalarMultBase(n, p);

            if (0 == CheckPoint(p.x, p.y, p.z))
            {
                throw new InvalidOperationException();
            }

            X25519Field.Copy(p.y, 0, y, 0);
            X25519Field.Copy(p.z, 0, z, 0);
        }
示例#11
0
        private static int CheckPoint(int[] x, int[] y)
        {
            int[] t = X25519Field.Create();
            int[] u = X25519Field.Create();
            int[] v = X25519Field.Create();

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

            return(X25519Field.IsZero(t));
        }
示例#12
0
        private byte[] ConvertEdPublicKeyToMontgomery(byte[] edPublicKey)
        {
            int[] x         = X25519Field.Create();
            int[] oneMinusY = X25519Field.Create();
            int[] aY        = new int[X25519Field.Size];
            X25519Field.Decode(edPublicKey, 0, aY);

            X25519Field.One(oneMinusY);
            X25519Field.Sub(oneMinusY, aY, oneMinusY);
            X25519Field.One(x);
            X25519Field.Add(x, aY, x);
            X25519Field.Inv(oneMinusY, oneMinusY);
            X25519Field.Mul(x, oneMinusY, x);

            byte[] xpublicKey = new byte[X25519PublicKeyParameters.KeySize];
            X25519Field.Encode(x, xpublicKey, 0);

            // UPDATE: the reality of the situation is that it's OK to check if it works, because the vast, vast majority work right off the bat, and it takes very little time to generate
            // I have no idea, but it has always worked....: I am very unhappy with it (tested 1m times, didn't fail). But since I don't trust it, I check it too (when it is possible)
            if (xpublicKey[X25519PublicKeyParameters.KeySize - 1] >= 128)
            {
                // Take off 128
                xpublicKey[X25519PublicKeyParameters.KeySize - 1] -= 128;
                // We need to add 19 as well...
                xpublicKey[0] = (byte)((xpublicKey[0] + 19) % 256);
                if (xpublicKey[0] < 19)
                {
                    int index = 0;
                    while (true)
                    {
                        index++;
                        if (xpublicKey[index] != 255)
                        {
                            xpublicKey[index] += 1;
                            break;
                        }

                        xpublicKey[index] = 0;
                    }
                }
            }

            return(xpublicKey);
        }
示例#13
0
        private static bool DecodePointVar(byte[] p, int pOff, bool negate, PointExt r)
        {
            byte[] py = Arrays.CopyOfRange(p, pOff, pOff + PointBytes);
            if (!CheckPointVar(py))
            {
                return(false);
            }

            int x_0 = (py[PointBytes - 1] & 0x80) >> 7;

            py[PointBytes - 1] &= 0x7F;

            X25519Field.Decode(py, 0, r.y);

            int[] u = X25519Field.Create();
            int[] v = X25519Field.Create();

            X25519Field.Sqr(r.y, u);
            X25519Field.Mul(C_d, u, v);
            X25519Field.SubOne(u);
            X25519Field.AddOne(v);

            if (!X25519Field.SqrtRatioVar(u, v, r.x))
            {
                return(false);
            }

            X25519Field.Normalize(r.x);
            if (x_0 == 1 && X25519Field.IsZeroVar(r.x))
            {
                return(false);
            }

            if (negate ^ (x_0 != (r.x[0] & 1)))
            {
                X25519Field.Negate(r.x, r.x);
            }

            PointExtendXY(r);
            return(true);
        }
示例#14
0
        private static void PointAddPrecomp(PointPrecomp p, PointAccum r)
        {
            int[] A = X25519Field.Create();
            int[] B = X25519Field.Create();
            int[] C = X25519Field.Create();
            int[] E = r.u;
            int[] F = X25519Field.Create();
            int[] G = X25519Field.Create();
            int[] H = r.v;

            X25519Field.Apm(r.y, r.x, B, A);
            X25519Field.Mul(A, p.ymx_h, A);
            X25519Field.Mul(B, p.ypx_h, B);
            X25519Field.Mul(r.u, r.v, C);
            X25519Field.Mul(C, p.xyd, C);
            X25519Field.Apm(B, A, H, E);
            X25519Field.Apm(r.z, C, G, F);
            X25519Field.Carry(G);
            X25519Field.Mul(E, F, r.x);
            X25519Field.Mul(G, H, r.y);
            X25519Field.Mul(F, G, r.z);
        }
示例#15
0
        private static void PointAddVar(bool negate, PointExt p, PointExt q, PointExt r)
        {
            int[] A = X25519Field.Create();
            int[] B = X25519Field.Create();
            int[] C = X25519Field.Create();
            int[] D = X25519Field.Create();
            int[] E = X25519Field.Create();
            int[] F = X25519Field.Create();
            int[] G = X25519Field.Create();
            int[] H = X25519Field.Create();

            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);
        }
示例#16
0
        private static void PointDouble(PointAccum r)
        {
            int[] A = X25519Field.Create();
            int[] B = X25519Field.Create();
            int[] C = X25519Field.Create();
            int[] E = r.u;
            int[] F = X25519Field.Create();
            int[] G = X25519Field.Create();
            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);
        }
示例#17
0
        public static void Precompute()
        {
            lock (precompLock)
            {
                if (precompBase != null)
                {
                    return;
                }

                // Precomputed table for the base point in verification ladder
                {
                    PointExt b = new PointExt();
                    X25519Field.Copy(B_x, 0, b.x, 0);
                    X25519Field.Copy(B_y, 0, b.y, 0);
                    PointExtendXY(b);

                    precompBaseTable = PointPrecompVar(b, 1 << (WnafWidthBase - 2));
                }

                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());
                        }
                    }

                    Debug.Assert(k == PrecompPoints);

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

                        int[] x = X25519Field.Create();
                        int[] y = X25519Field.Create();

                        X25519Field.Add(q.z, q.z, x);
                        // TODO[ed25519] Batch inversion
                        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.Normalize(r.xyd);

                        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;
                    }
                }

                Debug.Assert(off == precompBase.Length);
            }
        }
示例#18
0
 private static void PointExtendXY(PointExt p)
 {
     X25519Field.One(p.z);
     X25519Field.Mul(p.x, p.y, p.t);
 }
示例#19
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);
 }