/// <summary>
        /// Удвоить точку на кривой
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public IEllipticCurvePoint Doubling()
        {
            if (m_Y.Zero)
            {
                return(GetInfinity());
            }
            // Исходные координаты
            uint[] a                 = m_a4.m_Value;
            uint[] x                 = m_X.m_Value;
            uint[] y                 = m_Y.m_Value;
            uint[] z                 = m_Z.m_Value;
            uint[] modulo            = m_Modulo.m_Value;
            int    maxModuloBitIndex = BigHelper.MaxNonZeroBitIndex(modulo);
            int    length            = modulo.Length;

            // Выделим кэш операций умножения
            uint[] cache = new uint[length * 2];
            uint[] s     = new uint[length];
            uint[] m     = new uint[length];

            uint[] x1 = new uint[length];
            uint[] y1 = new uint[length];
            uint[] z1 = new uint[length];

            // Расчитаем m
            // Первое слагаемое a*Z1^4
            ModuloOperations.Multiply(z, z, modulo, z1, cache);
            ModuloOperations.Multiply(z1, z1, modulo, z1, cache);
            ModuloOperations.Multiply(z1, a, modulo, z1, cache);
            // Второе слагаемое 3*X1^2
            ModuloOperations.Multiply(x, x, modulo, m, cache);
            ModuloOperations.Multiply(m, 3, modulo, m, cache);
            // Результат m = 3*X1^2 + a*Z1^4
            ModuloOperations.Addition(m, z1, modulo);

            // Расчитаем s = 4*X1*Y1^2
            ModuloOperations.Multiply(y, y, modulo, z1, cache);

            ModuloOperations.Multiply(z1, x, modulo, s, cache);
            ModuloOperations.Multiply(s, 4, modulo, s, cache);

            // Расчитаем X3 = m^2 - 2*s
            ModuloOperations.Multiply(m, m, modulo, x1, cache);
            ModuloOperations.Multiply(s, 2, modulo, y1, cache);
            ModuloOperations.Substraction(x1, y1, modulo);

            // Расчитаем Y3 = m*(s - X3) - 8*Y1^4
            ModuloOperations.Multiply(z1, z1, modulo, z1, cache);
            ModuloOperations.Multiply(z1, 8, modulo, z1, cache);

            ModuloOperations.Substraction(s, x1, modulo, y1);
            ModuloOperations.Multiply(y1, m, modulo, y1, cache);
            ModuloOperations.Substraction(y1, z1, modulo);

            // Расчитаем Z3 = 2*Y1*Z1
            ModuloOperations.Multiply(y, z, modulo, z1, cache);
            ModuloOperations.Multiply(z1, 2, modulo, z1, cache);

            return(new EllipticCurvePointB(x1, y1, z1, this));
        }
        /// <summary>
        /// Doubling the point in elliptic curve
        /// </summary>
        /// <returns></returns>
        public IEllipticCurvePoint Doubling()
        {
            if (Infinity)
            {
                return(GetInfinity());
            }
            // Coordinates
            uint[] a                 = m_a4.m_Value;
            uint[] b                 = m_a6.m_Value;
            uint[] x                 = m_X.m_Value;
            uint[] y                 = m_Y.m_Value;
            uint[] z                 = m_Z.m_Value;
            uint[] modulo            = m_Modulo.m_Value;
            int    maxModuloBitIndex = BigHelper.MaxNonZeroBitIndex(modulo);
            int    length            = modulo.Length;

            // Get the cache
            uint[] cache = new uint[length * 2];
            uint[] s     = new uint[length];
            uint[] m     = new uint[length];

            uint[] x1 = new uint[length];
            uint[] y1 = new uint[length];
            uint[] z1 = new uint[length];


            // X^2
            ModuloOperations.Multiply(x, x, modulo, x1, cache);
            // Z^2
            ModuloOperations.Multiply(z, z, modulo, y1, cache);
            // Z1 = Z^2*X^2
            ModuloOperations.Multiply(x1, y1, modulo, z1, cache);

            // X^4
            ModuloOperations.Multiply(x1, x1, modulo, x1, cache);
            // Z^4
            ModuloOperations.Multiply(y1, y1, modulo, y1, cache);
            // b*Z^4
            ModuloOperations.Multiply(y1, y1, modulo, y1, cache);
            // X1 = X^4 + b*Z^4
            ModuloOperations.Addition(x1, y1, modulo);

            // a*Z1
            ModuloOperations.Multiply(z1, a, modulo, s, cache);
            // Y^2
            ModuloOperations.Multiply(y, y, modulo, m, cache);
            // a*Z1 + Y^2
            ModuloOperations.Addition(s, m, modulo);
            // a*Z1 + Y^2 + b*Z^4
            ModuloOperations.Addition(s, y1, modulo);
            // X1*(a*Z1 + Y^2 + b*Z^4)
            ModuloOperations.Multiply(s, x1, modulo, s, cache);
            // b*Z^4*Z1
            ModuloOperations.Multiply(y1, z1, modulo, y1, cache);

            // Y1 = b*Z^4*Z1 + X1*(a*Z1 + Y^2 + b*Z^4)
            ModuloOperations.Addition(y1, s, modulo);

            return(new EllipticCurvePointC(x1, y1, z1, this));
        }
Exemple #3
0
        unsafe public static void RightShift(uint[] value, uint[] result, uint[] modulo, uint[] cache, int shiftValue)
        {
            Array.Clear(cache, 0, cache.Length);
            // Количество сдвигов по индексам
            int indexShift = shiftValue / 32;
            // Количество внутренних сдвигов
            int valueShift = shiftValue % 32;

            // Заменить на указатели
            if (valueShift == 0)
            {
                Array.Copy(value, 0, cache, indexShift, value.Length);
            }
            else
            {
                int t1 = value.Length + indexShift;
                int t2 = 32 - valueShift;
                // Заполнить старший байт выходного вектора
                cache[t1] = (value[value.Length - 1] >> t2);
                t1--;
                // Заполнить серединку выходного массива
                for (int i = t1, i1 = value.Length - 1, i2 = value.Length - 2; i > indexShift; i--, i1--, i2--)
                {
                    cache[i] = (value[i1] << valueShift) + (value[i2] >> t2);
                }
                // Заполнить "младший" байт массива
                cache[indexShift] = (value[0] << valueShift);
            }
            BigHelper.Modulo(cache, modulo);
            ArrayCopyHelper.Copy(cache, result, value.Length);
        }
Exemple #4
0
        /// <summary>
        /// Получение обратного числа по модулю от текущего
        /// Используется расширенный алгоритм Евклида
        /// </summary>
        /// <param name="value">Первое число</param>
        /// <param name="modulo">Второй число</param>
        /// <param name="result">Результат</param>
        unsafe public static void Invert(uint[] value, uint[] modulo, uint[] result, uint[] cache1, uint[] cache2, uint[] cache3, uint[] cache4, uint[] cache5, uint[] cache6)
        {
            uint[] a = cache1;
            uint[] b = cache2;

            uint[] q      = cache3;
            uint[] r      = cache4;
            uint[] v2     = cache5;
            uint[] v1     = cache6;
            int    length = value.Length;

            ArrayCopyHelper.Copy(modulo, a, length);
            ArrayCopyHelper.Copy(value, b, length);
            v2[0] = 1;
            uint[] temp;
            // Пока целевое число не обнулилось
            while (!BigHelper.IfZero(b))
            {
                //TODO: Собственно бег по результату надо написать
                // Получить первый результат деления
                BigHelper.Divide(a, b, q, r);
                temp = a;
                a    = b;
                b    = r;
                r    = temp;

                Multiply(q, v2, modulo, q);
                Substraction(v1, q, modulo, v1);
                temp = v1;
                v1   = v2;
                v2   = temp;
            }
            ArrayCopyHelper.Copy(v1, result, length);
        }
Exemple #5
0
        /// <summary>
        /// Умножение по модулю с результатом в отдельный массив
        /// </summary>
        /// <param name="value1">Первый массив</param>
        /// <param name="value2">Второй массив</param>
        /// <param name="modulo">Модуль</param>
        /// <param name="result">Итоговый массив, можно не чистить</param>
        /// <param name="cache">Кэш, в два раза больше длины вектора величин, в него копируются промежуточные результаты умножений</param>
        unsafe public static void Multiply(uint[] value1, uint value2, uint[] modulo, uint[] result, uint[] cache)
        {
            // Внешний цикл для скорости должен иметь меньший размер
            fixed(uint *value1Pointer = value1, moduloPointer = modulo, cachePointer = cache)
            {
                // Этап умножения
                ulong temp   = 0;
                int   length = modulo.Length;
                // Границы массивов
                uint *value1EndPointer    = value1Pointer + length;
                uint *tempValueEndPointer = cachePointer + cache.Length;

                // Переменные указатели
                uint *ptrCounter1, ptrResult;

                // Почистить кэш умножения
                for (ptrCounter1 = cachePointer; ptrCounter1 < tempValueEndPointer; ++ptrCounter1)
                {
                    *ptrCounter1 = 0;
                }
                // Внутренний цикл
                for (ptrCounter1 = value1Pointer, ptrResult = cachePointer; ptrCounter1 < value1EndPointer; ++ptrCounter1, ++ptrResult)
                {
                    // Нужно загрузить очередь блоков умножения современных процессоров (ориентировочно, латентность 3 такта, однако загрузка возможна каждый такт)
                    temp += (ulong)value2 * *ptrCounter1 + (ulong)*ptrResult;
                    *ptrResult = (uint)temp;
                    temp >>= 32;
                }
                *ptrResult = (uint)temp;
                BigHelper.Modulo(cache, modulo);
                ArrayCopyHelper.Copy(cache, result, length);
            }
        }
        /// <summary>
        /// Умножить точку на число на эллиптической кривой
        /// </summary>
        /// <param name="value1">Точка на эллиптической кривой</param>
        /// <param name="value2">Множитель к точке</param>
        /// <returns></returns>
        public IEllipticCurvePoint Multiply(IntBig value2)
        {
            EllipticCurvePointB tempPoint = null;

            // Массив значений для этапа "предвычислений"
            // !!!!!!!!!!!!!!Занимательная задачка: надо подумать над графом вычислений, ибо почти стопроцентная уверенность, что не все значения массива понадобятся... Налицо оптимизация
            EllipticCurvePointB[] points = new EllipticCurvePointB[16];
            points[0]  = GetInfinity() as EllipticCurvePointB;
            points[1]  = this;
            points[2]  = points[1].Doubling() as EllipticCurvePointB;
            points[3]  = points[1].Addition(points[2]) as EllipticCurvePointB;
            points[4]  = points[2].Doubling() as EllipticCurvePointB;
            points[5]  = points[1].Addition(points[4]) as EllipticCurvePointB;
            points[6]  = points[3].Doubling() as EllipticCurvePointB;
            points[7]  = points[1].Addition(points[6]) as EllipticCurvePointB;
            points[8]  = points[4].Doubling() as EllipticCurvePointB;
            points[9]  = points[1].Addition(points[8]) as EllipticCurvePointB;
            points[10] = points[5].Doubling() as EllipticCurvePointB;
            points[11] = points[1].Addition(points[10]) as EllipticCurvePointB;
            points[12] = points[6].Doubling() as EllipticCurvePointB;
            points[13] = points[1].Addition(points[12]) as EllipticCurvePointB;
            points[14] = points[7].Doubling() as EllipticCurvePointB;
            points[15] = points[1].Addition(points[14]) as EllipticCurvePointB;
            // Начальный индекс множителя, от него начинается движение по двоичному представлению большого числа
            int index         = BigHelper.MaxNonZeroBitIndex(value2.m_Value);
            int howManyDouble = 0;
            int howMuchAdd    = 0;

            //if (index < 0)
            //    break;
            index     = GetWindow(value2, index, out howManyDouble, out howMuchAdd);
            tempPoint = points[howMuchAdd];

            while (true)
            {
                if (index < 0)
                {
                    break;
                }
                index = GetWindow(value2, index, out howManyDouble, out howMuchAdd);
                if (howManyDouble > 0)
                {
                    for (int t = 0; t < howManyDouble; ++t)
                    {
                        tempPoint = tempPoint.Doubling() as EllipticCurvePointB;
                    }
                }
                if (howMuchAdd > 0)
                {
                    tempPoint = tempPoint.Addition(points[howMuchAdd]) as EllipticCurvePointB;
                }
            }
            return(tempPoint);
        }
        /// <summary>
        /// Multiplies the this value at IntBig value
        /// </summary>
        /// <param name="value">IntBig multiplier</param>
        /// <returns>Result of operation</returns>
        public IEllipticCurvePoint Multiply(IntBig value2)
        {
            EllipticCurvePointC tempPoint = null;

            EllipticCurvePointC[] points = new EllipticCurvePointC[16];
            points[0]  = GetInfinity() as EllipticCurvePointC;
            points[1]  = this;
            points[2]  = points[1].Doubling() as EllipticCurvePointC;
            points[3]  = points[1].Addition(points[2]) as EllipticCurvePointC;
            points[4]  = points[2].Doubling() as EllipticCurvePointC;
            points[5]  = points[1].Addition(points[4]) as EllipticCurvePointC;
            points[6]  = points[3].Doubling() as EllipticCurvePointC;
            points[7]  = points[1].Addition(points[6]) as EllipticCurvePointC;
            points[8]  = points[4].Doubling() as EllipticCurvePointC;
            points[9]  = points[1].Addition(points[8]) as EllipticCurvePointC;
            points[10] = points[5].Doubling() as EllipticCurvePointC;
            points[11] = points[1].Addition(points[10]) as EllipticCurvePointC;
            points[12] = points[6].Doubling() as EllipticCurvePointC;
            points[13] = points[1].Addition(points[12]) as EllipticCurvePointC;
            points[14] = points[7].Doubling() as EllipticCurvePointC;
            points[15] = points[1].Addition(points[14]) as EllipticCurvePointC;
            // First index
            int index         = BigHelper.MaxNonZeroBitIndex(value2.m_Value);
            int howManyDouble = 0;
            int howMuchAdd    = 0;

            //if (index < 0)
            //    break;
            index     = GetWindow(value2, index, out howManyDouble, out howMuchAdd);
            tempPoint = points[howMuchAdd];

            while (true)
            {
                if (index < 0)
                {
                    break;
                }
                index = GetWindow(value2, index, out howManyDouble, out howMuchAdd);
                if (howManyDouble > 0)
                {
                    for (int t = 0; t < howManyDouble; ++t)
                    {
                        tempPoint = tempPoint.Doubling() as EllipticCurvePointC;
                    }
                }
                if (howMuchAdd > 0)
                {
                    tempPoint = tempPoint.Addition(points[howMuchAdd]) as EllipticCurvePointC;
                }
            }
            return(tempPoint);
        }
Exemple #8
0
        unsafe public static uint[] Pow(uint[] value1, uint[] modulo, int value2)
        {
            if (value2 == 0)
            {
                return new uint[] { 1 }
            }
            ;
            uint[] returnValue = new uint[value1.Length];
            ArrayCopyHelper.Copy(value1, returnValue, value1.Length);
            if (value2 < 0)
            {
                Invert(returnValue, modulo);
            }
            value2 = Math.Abs(value2);
            int nonZeroLength = BigHelper.MaxNonZeroBitIndex((uint)value2) + 1;

            if (nonZeroLength == 0)
            {
                return(null);
            }
            for (int i = nonZeroLength - 2; i >= 0; --i)
            {
                Multiply(returnValue, returnValue, modulo);
                if (((value2 >> i) & 1) == 1)
                {
                    Multiply(returnValue, value1, modulo);
                }
            }
            return(returnValue);
        }

        #endregion Pow
        #endregion Public methods
        #region Internal methods
        #endregion Internal methods
        #region Private methods
        #endregion Private methods
        #region  Events, overrides
        #endregion Events, overrides
        #endregion Methods
    }
        /// <summary>
        /// Adds the this value with another value in elliptic curve
        /// </summary>
        /// <param name="value">The value to add with this value</param>
        /// <returns>The sum of values</returns>
        public IEllipticCurvePoint Addition(IEllipticCurvePoint value)
        {
            EllipticCurvePointC value2 = value as EllipticCurvePointC;

            if (value2 as object == null)
            {
                throw new Exception("Incorrect point type!");
            }
            if (m_a4 != value2.m_a4 || m_a6 != value2.m_a6 || m_Modulo != value2.m_Modulo)
            {
                throw new Exception("Incorrect value elliptic curve parameters!");
            }
            if (value2.Infinity)
            {
                return(new EllipticCurvePointC(m_X, m_Y, m_Z, this));
            }
            if (Infinity)
            {
                return(new EllipticCurvePointC(value2.m_X, value2.m_Y, value2.m_Z, value2));
            }
            if (Equals(value2))
            {
                return(Doubling());
            }
            // Coordinates
            uint[] a                 = m_a4.m_Value;
            uint[] x1                = m_X.m_Value;
            uint[] y1                = m_Y.m_Value;
            uint[] z1                = m_Z.m_Value;
            uint[] x2                = value2.m_X.m_Value;
            uint[] y2                = value2.m_Y.m_Value;
            uint[] z2                = value2.m_Z.m_Value;
            uint[] modulo            = m_Modulo.m_Value;
            int    maxModuloBitIndex = BigHelper.MaxNonZeroBitIndex(modulo);
            int    length            = modulo.Length;

            // Get the cache
            uint[] cache = new uint[length * 2];

            uint[] A = new uint[length];
            uint[] D = new uint[length];
            uint[] B = new uint[length];
            uint[] C = new uint[length];

            uint[] xr = new uint[length];
            uint[] yr = new uint[length];
            uint[] zr = new uint[length];
            // Z1^2
            ModuloOperations.Multiply(z1, z1, modulo, A, cache);
            // Z1^2 * a
            ModuloOperations.Multiply(z1, a, modulo, D, cache);
            // X2 * Z1
            ModuloOperations.Multiply(x2, z1, modulo, B, cache);
            // B = X2 * Z1 + X1
            ModuloOperations.Addition(B, x1, modulo);

            // C = Z1*B
            ModuloOperations.Multiply(z1, B, modulo, C, cache);

            // C + Z1^2 * a
            ModuloOperations.Addition(D, C, modulo);
            // B * (C + Z1^2 * a)
            ModuloOperations.Multiply(D, B, modulo, D, cache);
            // D = B^2 * (C + Z1^2 * a)
            ModuloOperations.Multiply(D, B, modulo, D, cache);

            // Y2 * Z1^2
            ModuloOperations.Multiply(A, y2, modulo, A, cache);
            // A =  Y2 * Z1^2 + Y1
            ModuloOperations.Addition(A, y1, modulo);

            if (BigHelper.IfZero(B))
            {
                if (BigHelper.IfZero(A))
                {
                    return(value2.Doubling());
                }
                else
                {
                    return(GetInfinity());
                }
            }

            // Z3 = C^2
            ModuloOperations.Multiply(C, C, modulo, zr, cache);

            // E = A * C
            ModuloOperations.Multiply(C, A, modulo, C, cache);

            // A^2
            ModuloOperations.Multiply(A, A, modulo, xr, cache);
            // A^2 + D
            ModuloOperations.Addition(xr, D, modulo);
            // X3 = A^2 + D + E
            ModuloOperations.Addition(xr, C, modulo);

            // X2 * Z3
            ModuloOperations.Multiply(x2, zr, modulo, A, cache);
            // F = X3 + X2 * Z3
            ModuloOperations.Addition(A, xr, modulo);

            // X2 + Y2
            ModuloOperations.Addition(x2, y2, modulo, B);
            // (X2 + Y2) * Z3
            ModuloOperations.Multiply(B, zr, modulo, B, cache);
            // G = (X2 + Y2) * Z3^2
            ModuloOperations.Multiply(B, zr, modulo, B, cache);

            // E + Z3
            ModuloOperations.Addition(C, zr, modulo, yr);
            // (E + Z3) * F
            ModuloOperations.Multiply(yr, A, modulo, yr, cache);
            // (E + Z3) * F + G
            ModuloOperations.Addition(yr, B, modulo, yr);

            return(new EllipticCurvePointC(xr, yr, zr, this));
        }
        /// <summary>
        /// Сложить две точки на кривой
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <returns></returns>
        public IEllipticCurvePoint Addition(IEllipticCurvePoint value)
        {
            EllipticCurvePointB value2 = value as EllipticCurvePointB;

            if (value2 as object == null)
            {
                throw new Exception("Incorrect point type!");
            }
            if (m_a4 != value2.m_a4 || m_a6 != value2.m_a6 || m_Modulo != value2.m_Modulo)
            {
                throw new Exception("Incorrect value elliptic curve parameters!");
            }

            if (Equals(value2))
            {
                return(Doubling());
            }
            // Исходные координаты
            uint[] a                 = m_a4.m_Value;
            uint[] x1                = m_X.m_Value;
            uint[] y1                = m_Y.m_Value;
            uint[] z1                = m_Z.m_Value;
            uint[] x2                = value2.m_X.m_Value;
            uint[] y2                = value2.m_Y.m_Value;
            uint[] z2                = value2.m_Z.m_Value;
            uint[] modulo            = m_Modulo.m_Value;
            int    maxModuloBitIndex = BigHelper.MaxNonZeroBitIndex(modulo);
            int    length            = modulo.Length;

            // Выделим кэш операций умножения
            uint[] cache = new uint[length * 2];
            // Временные переменные
            uint[] u1 = new uint[length];
            uint[] u2 = new uint[length];
            uint[] s1 = new uint[length];
            uint[] s2 = new uint[length];

            uint[] xr = new uint[length];
            uint[] yr = new uint[length];
            uint[] zr = new uint[length];
            // Вычислить U1, U2, S1, S2
            ModuloOperations.Multiply(z2, z2, modulo, u1, cache);
            ModuloOperations.Multiply(z1, z1, modulo, u2, cache);

            ModuloOperations.Multiply(u1, z2, modulo, s1, cache);
            ModuloOperations.Multiply(u2, z1, modulo, s2, cache);

            ModuloOperations.Multiply(u1, x1, modulo, u1, cache);
            ModuloOperations.Multiply(u2, x2, modulo, u2, cache);

            ModuloOperations.Multiply(s1, y1, modulo, s1, cache);
            ModuloOperations.Multiply(s2, y2, modulo, s2, cache);
            // Проверим, может расчет
            if (Eguals(u1, u2))
            {
                if (Eguals(s1, s2))
                {
                    return(Doubling());
                }
                else
                {
                    return(GetInfinity());
                }
            }
            ModuloOperations.Substraction(u2, u1, modulo);
            ModuloOperations.Substraction(s2, s1, modulo);
            //H^2
            ModuloOperations.Multiply(u2, u2, modulo, yr, cache);
            //H^3
            ModuloOperations.Multiply(yr, u2, modulo, zr, cache);
            //R^2
            ModuloOperations.Multiply(s2, s2, modulo, xr, cache);
            //R^2 - H^3
            ModuloOperations.Substraction(xr, zr, modulo);
            //U1*H^2
            ModuloOperations.Multiply(u1, yr, modulo, yr, cache);
            //2*U1*H^2
            ModuloOperations.Multiply(yr, 2, modulo, u1, cache);

            //X3 = R^2 - H^3 - 2*U1*H^2
            ModuloOperations.Substraction(xr, u1, modulo);

            //U1*H^2 - X3
            ModuloOperations.Substraction(yr, xr, modulo);
            //R*(U1*H^2 - X3)
            ModuloOperations.Multiply(yr, s2, modulo, yr, cache);
            //S1*H^3
            ModuloOperations.Multiply(s1, zr, modulo, zr, cache);
            //R*(U1*H^2 - X3) - S1*H^3
            ModuloOperations.Substraction(yr, zr, modulo);

            //Z1*Z2
            ModuloOperations.Multiply(z1, z2, modulo, zr, cache);
            //Z3 = H*Z1*Z2
            ModuloOperations.Multiply(zr, u2, modulo, zr, cache);

            return(new EllipticCurvePointB(xr, yr, zr, this));
        }
Exemple #11
0
 /// <summary>
 /// Converts the value to its equivalent string representation by using the specified format
 /// </summary>
 /// <param name="value"></param>
 /// <param name="format">A standard or custom numeric format string</param>
 /// <param name="littleEndian">true if value must be represents as little-Endian</param>
 /// <returns></returns>
 public static string ToString(MIntBig value, string format, bool littleEndian)
 {
     return(BigHelper.ToString(value.m_Value.m_Value, format, littleEndian) + " mod " + BigHelper.ToString(value.m_Modulo.m_Value, format, littleEndian));
 }