Example #1
0
        //      ec-function: Y^2 = X^3 + a*X + b 'modulo' P
        //P = {Xp, Yp}; Q = {Xq, Yq}
        //ADD:    S = (Yp - Yq) / (Xp - Xq)
        //        RESULT = {Xr = S * S - Xp - Xq; Yr = S(Xp - Xr) - Yp}
        //DUB:    S = (3 * Xp * Xp + a) / (2 * Yp)
        //        RESULT = {Xr = S * S - 2 * Xp ; Yr = S(Xp - Xr) - Yp}
        public void GetDouble(ref OwnECPoint p)
        {   //return: 2 * p
            if (p.IsInfinity)
            {
                return;
            }
            if (IsZero(p.Y))
            {
                p.SetInfinity();
                return;
            }

            Let(S1, p.X);
            SquareModP(S1); AddScaledModP(S1, S1, 2);
            AddModP(S1, A);
            Let(S2, p.Y);
            AddModP(S2, S2);

            this.RemodFriendlyPrime(S1);
            this.RemodFriendlyPrime(S2);
            AsmX64Operations.DivideModuloPrime(S1, S2, P, N);

            Let(R1, S1);
            SquareModP(S1);
            SubScaledModP(S1, p.X, 2); //S1 = Rx = S * S - 2 * Px

            SubtractModP(p.X, S1, S2); //S2 = Px - Rx
            MultiplyModP(S2, R1);
            SubModP(S2, p.Y);          //S2 = S(Px - Rx) - Py

            p.SetFrom(S1, S2, false);
        }
        private static int CompareBaseBits(int bitsPerDigit, long n)
        {   //middle digit <= n * (base - 1) ^ 2 + [2^(128 - bitsPerDigit)] <= P - 1
            ulong[] value      = new ulong[1];
            ulong[] square     = new ulong[value.Length * 2];
            ulong[] multiplier = new ulong[square.Length];
            ulong[] result     = new ulong[square.Length * 2];
            ulong[] adder      = new ulong[result.Length];
            value[0]      = (1UL << bitsPerDigit) - 1;
            multiplier[0] = (ulong)n;
            AsmX64Operations.Square(value, square, value.Length);
            AsmX64Operations.Multiply(square, multiplier, result, square.Length);
            if (128 - bitsPerDigit < 64)
            {
                adder[0] = 1UL << (128 - bitsPerDigit);
            }
            else
            {
                adder[1] = 1UL << (64 - bitsPerDigit);
            }
            AsmX64Operations.Add(result, adder, result, 0, result.Length);

            if (result[2] > 0 || result[3] > 0 || (result[0] >= FourierPoint.PrimeModulo.Low && result[1] == ulong.MaxValue))
            {
                return(1);
            }
            if (result[0] == FourierPoint.PrimeModulo.Low - 1 && result[1] == ulong.MaxValue)
            {
                return(0);
            }
            return(-1);
        }
Example #3
0
        public static IntegerNumber operator <<(IntegerNumber x, int shift)
        {
            if (shift == 0)
            {
                return(x);
            }
            if (shift < 0)
            {
                return(x >> (-shift));
            }

            int xlen             = x.RealDigits;
            int resultDigits     = xlen + (shift >> 6);
            int singleDigitShift = shift & 63;

            if (singleDigitShift != 0)
            {
                long hix = (long)x.bits[xlen - 1] >> (63 - singleDigitShift);
                if (hix != 0L && hix != -1L)
                {
                    resultDigits++;
                }
            }
            ulong[] result = x.bits;
            ExtendToExact(ref result, resultDigits, true);
            AsmX64Operations.IntShl(result, shift, resultDigits);
            return(new IntegerNumber(result, false));
        }
Example #4
0
        public static IntegerNumber DivRem(IntegerNumber number, long digit, out long remainder)
        {
            IntegerNumber result = new IntegerNumber(number.bits, true);

            remainder = (long)AsmX64Operations.DivideDigit(result.bits, (ulong)digit, result.Digits, true);
            return(result);
        }
Example #5
0
 public void SquareModP(ulong[] inputOutput)
 {
     AsmX64Operations.KaratsubaSquare(inputOutput, temporary2x, N, temporaryKaratsubaBuffer);
     this.GetModFriendlyPrime(temporary2x);
     for (int i = N; --i >= 0;)
     {
         inputOutput[i] = temporary2x[i];
     }
 }
Example #6
0
 public void MultiplyModP(ulong[] inputOutput, ulong[] input2)
 {
     AsmX64Operations.Karatsuba(inputOutput, input2, temporary2x, N, temporaryKaratsubaBuffer);
     this.GetModFriendlyPrime(temporary2x);
     for (int i = N; --i >= 0;)
     {
         inputOutput[i] = temporary2x[i];
     }
 }
Example #7
0
        public static IntegerNumber operator *(IntegerNumber number1, IntegerNumber number2)
        {
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits * 2];
            AsmX64Operations.FastestMultiplication(source1.bits, source2.bits, result, source1.Digits, true);
            return(new IntegerNumber(result, false));
        }
Example #8
0
        public static IntegerNumber operator -(IntegerNumber number1, IntegerNumber number2)
        {
            if (number1.IsNegative != number2.IsNegative)
            {
                return(number2.IsZero ? number1 : number1 + (-number2));
            }   //when subtracting numbers with the same sign, the absolute value of the result is less than the absoulute value of each input. (number size decreases).
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits];
            AsmX64Operations.Subtract(source1.bits, source2.bits, result, 0, result.Length);
            return(new IntegerNumber(result, false));
        }
Example #9
0
        public static IntegerNumber operator -(IntegerNumber number)
        {
            if (number.bits[number.bits.Length - 1] == SignBit && number.isZero(0, number.bits.Length - 1))
            {   //make positive the highly compact negative numbers - as a special case.
                ulong[] bits = new ulong[number.bits.Length + 1];
                bits[number.bits.Length - 1] = SignBit;
                return(new IntegerNumber(bits, false));
            }
            IntegerNumber result = new IntegerNumber(number.bits, true);

            AsmX64Operations.Negate(result.bits, result.Digits);
            return(result);
        }
Example #10
0
        public void Add(ref OwnECPoint p, OwnECPoint q, bool subtract = false)
        {   //returns: P + Q
            if (p.IsInfinity || q.IsInfinity)
            {
                if (!q.IsInfinity)
                {
                    p.SetFrom(q.X, q.Y, q.IsInfinity);
                    if (subtract)
                    {
                        SubtractModP(P, p.Y, p.Y);
                    }
                }
                return;
            }

            SubtractModP(p.X, q.X, S2);     //s2 = Px - Qx
            if (subtract)
            {                               //s1 = Py - Qy; in case of subtract real Q.Y is -Q.Y so we add the value modulo P.
                AdditionModP(p.Y, q.Y, S1); //s1 = Py - Qy
            }
            else
            {
                SubtractModP(p.Y, q.Y, S1);
            }

            if (IsZero(S2))
            {     //Px == Qx
                if (IsZero(S1))
                { // P == Q
                    GetDouble(ref p);
                    return;
                }
                p.SetInfinity();
                return;
            }

            this.RemodFriendlyPrime(S1);
            this.RemodFriendlyPrime(S2);
            AsmX64Operations.DivideModuloPrime(S1, S2, P, N);        //S = s1 = s1 / s2 'modulo' P.

            Let(R1, S1);
            SquareModP(S1);
            SubModP(S1, p.X);
            SubModP(S1, q.X);          //s1 = Result.x = S * S - Px - Qx

            SubtractModP(p.X, S1, S2); //s2 = Px - Rx
            MultiplyModP(S2, R1);
            SubModP(S2, p.Y);          //s2 = S(Px - Rx) - Py

            p.SetFrom(S1, S2, false);
        }
Example #11
0
        public static IntegerNumber operator >>(IntegerNumber x, int shift)
        {
            if (shift == 0)
            {
                return(x);
            }
            if (shift < 0)
            {
                return(x << (-shift));
            }
            IntegerNumber result = new IntegerNumber(x.bits, true);

            AsmX64Operations.IntShr(result.bits, shift, result.Digits, true);
            return(result);
        }
Example #12
0
 public OwnECPoint ToECPoint(ECCBase ecc)
 {
     ulong[] inverse = new ulong[ecc.N];
     inverse[0] = 1;
     ecc.RemodFriendlyPrime(this.Z);
     AsmX64Operations.DivideModuloPrime(inverse, this.Z, ecc.P, ecc.N);
     ulong[] inverseSquare = inverse.ToArray();
     ecc.SquareModP(inverseSquare);
     ecc.MultiplyModP(inverse, inverseSquare);
     ulong[] nx = this.X.ToArray(); ecc.MultiplyModP(nx, inverseSquare);
     ulong[] ny = this.Y.ToArray(); ecc.MultiplyModP(ny, inverse);
     ecc.RemodFriendlyPrime(nx);
     ecc.RemodFriendlyPrime(ny);
     return(new OwnECPoint(nx, ny, this.IsInfinity));
 }
Example #13
0
        public static IntegerNumber operator +(IntegerNumber number1, IntegerNumber number2)
        {
            if (number1.IsNegative != number2.IsNegative)
            {
                return(number2.IsZero ? number1 : number1 - (-number2));
            }
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits];
            byte    carry  = AsmX64Operations.Add(source1.bits, source2.bits, result, 0, result.Length);

            if (carry != (byte)(result[result.Length - 1] >> 63))
            {
                Array.Resize(ref result, result.Length + 1);
                result[result.Length - 1] = carry == 0 ? 0UL : ulong.MaxValue;
            }
            return(new IntegerNumber(result, false));
        }
        public static bool UnitTest(int seed)
        {
            Random random = new Random(seed);
            int    n      = 891;

            ulong[] a  = new ulong[n];
            ulong[] b  = new ulong[n];
            ulong[] s1 = new ulong[n + 1];
            ulong[] s2 = new ulong[n + 1];
            ulong[] r1 = new ulong[n * 2];
            ulong[] r2 = new ulong[n * 2];
            for (int i = n; --i >= 0;)
            {
                byte[] data = new byte[16];
                random.NextBytes(data);
                a[i] = BitConverter.ToUInt64(data, 0);
                b[i] = BitConverter.ToUInt64(data, 8);
            }
            bool ok = true;

            s1[n] = AsmX64Operations.CarrylessMultipyAndXor(a, b[0], s1, n);
            s2[n] = carrylessMultiplyAndXor(a, b[0], s2, n);
            for (int i = 0; i <= n; i++)
            {
                if (s1[i] != s2[i])
                {
                    ok = false;
                }
            }

            AsmX64Operations.CarrylessMultiplication(a, b, r1, n);
            carrylessMultiplication(a, b, r2, n);
            for (int i = 0; i < n * 2; i++)
            {
                if (r1[i] != r2[i])
                {
                    ok = false;
                }
            }

            return(ok);
        }
 public static FourierPoint operator >>(FourierPoint x, int shift)
 {
     ulong[] number = new ulong[2] {
         x.Low, x.High
     };
     while (shift >= 64)
     {
         ulong carry = AsmX64Operations.MultiplyDigitAndAdd(PrimeModuloDigits, NegativeInverseLowP * number[0], number, 2);
         number[0] = number[1];
         number[1] = carry;
         shift    -= 64;
     }
     if (shift != 0)
     {
         ulong mask  = (1UL << shift) - 1UL;
         ulong carry = AsmX64Operations.MultiplyDigitAndAdd(PrimeModuloDigits, NegativeInverseLowP * number[0] & mask, number, 2);
         return(new FourierPoint((number[0] >> shift) | (number[1] << (64 - shift)), (number[1] >> shift) | (carry << (64 - shift))));
     }
     return(new FourierPoint(number[0], number[1]));
 }
Example #16
0
        //return: P * factor on the elliptic curves domain.
        public OwnECPoint Multiply(OwnECPoint p, ulong[] factor)
        {
            ulong[] exp  = new ulong[factor.Length + 1];
            ulong[] exp3 = new ulong[factor.Length + 1];
            factor.CopyTo(exp, 0);
            exp3[factor.Length] = AsmX64Operations.MultiplyDigitAndAdd(exp, 3, exp3, factor.Length);
            for (int i = exp.Length; --i >= 0;)
            {
                exp3[i] ^= exp[i];  //exp3= (exp*3) ^ exp
            }
            int high = HighBit(exp3);

            if (high < 0)
            {
                return(new OwnECPoint(p.X, p.Y, true));
            }
            JacobianECPoint x    = new JacobianECPoint(p.X, p.Y, true);
            ulong           mask = 1UL << (high & 63);

            for (int i = high; --i >= 0;)
            {
                GetDouble(ref x);
                if ((exp3[(i + 1) >> 6] & mask) != 0)
                {
                    if ((exp[(i + 1) >> 6] & mask) != 0)
                    {
                        Subtract(ref x, p);
                    }
                    else
                    {
                        Add(ref x, p);
                    }
                }
                mask = (mask >> 1) | (mask << 63);
            }
            OwnECPoint result = x.ToECPoint(this);

            return(result);
        }
Example #17
0
 private void subScaledModP(ulong[] result, ulong[] input, ulong multiplier)
 {
     AsmX64Operations.SubScaledModP521(result, input, multiplier, N);
 }
Example #18
0
 private void addScaledModP(ulong[] result, ulong[] input, ulong multiplier)
 {
     AsmX64Operations.AddScaledModP(result, input, multiplier, LowP, N);
 }
Example #19
0
        public static bool UnitTest()
        {
            //    SPECIAL prime: 2^64 - 2^32 + 1
            //prime: 2^64 - 2^34 + 1
            //prime: 2^64 - 2^40 + 1
            //    SPECIAL prime: 2 ^ 128 - 2 ^ 54 + 1
            //prime: 2 ^ 128 - 2 ^ 108 + 1
            //prime: 2 ^ 256 - 2 ^ 168 + 1
            //prime: 2 ^ 256 - 2 ^ 174 + 1
            //prime: 2 ^ 512 - 2 ^ 32 + 1
            //prime: 2 ^ 512 - 2 ^ 288 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 142 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 226 + 1
            //prime: 2 ^ 1024 - 2 ^ 562 + 1
            //prime: 2 ^ 1024 - 2 ^ 718 + 1
            //prime: 2 ^ 1024 - 2 ^ 856 + 1
            //prime: 2 ^ 1024 - 2 ^ 880 + 1
            //prime: 2 ^ 4096 - 2 ^ 3510 + 1
            //prime: 2 ^ 4096 - 2 ^ 3708 + 1
            if ("not exec".Trim() == "exec")
            {
                StringBuilder primes = new StringBuilder();
                for (int exp = 6; exp <= 12; exp++)
                {
                    int shift = 1 << exp;
                    Parallel.For(32, shift, i =>
                    {
                        ulong[] baseValue   = new ulong[shift / 64];
                        ulong[] expValue    = new ulong[shift / 64];
                        ulong[] modulo      = new ulong[shift / 64];
                        ulong[] subtractor  = new ulong[shift / 64];
                        ulong[] one         = new ulong[shift / 64];
                        ulong[] pPlusOne    = new ulong[shift / 64];
                        subtractor[i / 64] |= 1UL << (i & 63);
                        modulo[0]           = 1UL;
                        one[0]              = 1UL;
                        AsmX64Operations.Subtract(modulo, subtractor, modulo, 0, modulo.Length);
                        modulo.CopyTo(expValue, 0);
                        modulo.CopyTo(pPlusOne, 0);
                        expValue[0]--;
                        pPlusOne[0]++;

                        int isPrime = 1;
                        for (int a = 2; a <= 128; a++)
                        {
                            one.CopyTo(baseValue, 0);
                            baseValue[0] = (ulong)a;
                            AsmX64Operations.ModularExponentiation(baseValue, expValue, modulo, modulo.Length, 5);
                            if (Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == one[idx]) ||
                                Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == pPlusOne[idx]))
                            {
                                continue;
                            }
                            isPrime = 0;
                            break;
                        }

                        if (isPrime != 0)
                        {
                            lock (primes)
                            {
                                primes.AppendLine("prime: 2^" + shift.ToString() + " - 2^" + i.ToString() + " + 1");
                            }
                        }
                    });
                }
                Clipboard.SetText(primes.ToString());
                System.Windows.Forms.MessageBox.Show(primes.ToString(), "message");
            }

            Random random = new Random(1001);
            bool   ok     = true;

            for (int i = 400; --i >= 0;)
            {
                byte[] bytes1 = new byte[31 + random.Next(2)];
                byte[] bytes2 = new byte[31 + random.Next(2)];
                random.NextBytes(bytes1);
                random.NextBytes(bytes2);

                BigInteger  n1 = new BigInteger(bytes1);
                BigInteger  n2 = new BigInteger(bytes2);
                FastInteger f1 = new FastInteger(bytes1);
                FastInteger f2 = new FastInteger(bytes2);
                if (n1.ToString() != f1.ToString())
                {
                    ok = false;
                }
                if (n2.ToString() != f2.ToString())
                {
                    ok = false;
                }
                BigInteger  a1 = n1 + n2;
                FastInteger a2 = f1 + f2;
                if (a1.ToString() != a2.ToString())
                {
                    ok = false;
                }
                BigInteger  s1 = n1 - n2;
                FastInteger s2 = f1 - f2;
                if (s1.ToString() != s2.ToString())
                {
                    ok = false;
                }
                BigInteger  m1 = n1 * n2;
                FastInteger m2 = f1 * f2;
                if (m1.ToString() != m2.ToString())
                {
                    ok = false;
                }
                int         shrvalue = random.Next(256) + 1;
                BigInteger  sh1      = n1 >> shrvalue;
                FastInteger sh2      = f1 >> shrvalue;
                if (sh1.ToString() != sh2.ToString())
                {
                    ok = false;
                }
                if ((-f1).ToString() != (-n1).ToString() || (-f2).ToString() != (-n2).ToString())
                {
                    ok = false;
                }
                int         shlvalue = random.Next(256) + 1;
                BigInteger  shl1     = n1 << shlvalue;
                FastInteger shl2     = f1 << shlvalue;
                if (shl1.ToString() != shl2.ToString())
                {
                    ok = false;
                }
                BigInteger  and1 = n1 & n2;
                FastInteger and2 = f1 & f2;
                if (and1.ToString() != and2.ToString())
                {
                    ok = false;
                }
                BigInteger  xor1 = n1 ^ n2;
                FastInteger xor2 = f1 ^ f2;
                if (xor1.ToString() != xor2.ToString())
                {
                    ok = false;
                }

                if (!ok)
                {
                    break;
                }
            }
            return(ok);
        }
Example #20
0
 public static IntegerNumber operator *(IntegerNumber number, long scalar)
 {
     ulong[] result = new ulong[number.Digits + 1];
     AsmX64Operations.MultiplyDigit(number.bits, (ulong)scalar, result, number.Digits, true);
     return(new IntegerNumber(result, false));
 }
Example #21
0
 private void addModP(ulong[] input1, ulong[] input2, ulong[] result)
 {
     AsmX64Operations.AddModP521(input1, input2, result, N);
 }
Example #22
0
 private void subModP(ulong[] input1, ulong[] input2, ulong[] result)
 {
     AsmX64Operations.SubtractModP521(input1, input2, result, N);
 }
Example #23
0
        public static IntegerNumber DivRem(IntegerNumber dividend, IntegerNumber divisor, out IntegerNumber remainder)
        {
            shrink(dividend);
            shrink(divisor);
            int           dividendDigits = dividend.Digits;
            int           divisorDigits  = divisor.Digits;
            IntegerNumber quotient;
            int           n = Math.Max(divisorDigits, (dividendDigits + 1) >> 1);

            if (divisorDigits <= IntegerDigitsBreakPoint)
            {
                dividend  = dividend.ExtendTo(n * 2);
                divisor   = divisor.ExtendTo(n);
                quotient  = new IntegerNumber(new ulong[n * 2], false);
                remainder = new IntegerNumber(dividend.bits, true);
                AsmX64Operations.GetDivMod(remainder.bits, divisor.bits, n, quotient.bits, true);
                shrink(quotient);
                shrink(remainder);
                return(quotient);
            }
            bool sign = false;

            if (dividend.IsNegative != divisor.IsNegative)
            {
                dividend = IntegerNumber.Abs(dividend);
                divisor  = IntegerNumber.Abs(divisor);
                sign     = true;
            }
            else if (dividend.IsNegative && divisor.IsNegative)
            {
                dividend = -dividend;
                divisor  = -divisor;
            }

            int           delta = n - divisorDigits;
            IntegerNumber x     = (divisor << (delta * 128)).Inverse();

            quotient = dividend * x >> (n * 128);
            shrink(quotient);
            remainder = dividend - quotient * divisor;
            shrink(remainder);
            int count = 0;

            while (remainder.IsNegative)
            {
                remainder += divisor;
                quotient  -= One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            while (remainder >= divisor)
            {
                remainder -= divisor;
                quotient  += One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }

            if (sign)
            {
                quotient  = -quotient;
                remainder = -remainder;
            }
            return(quotient);
        }
Example #24
0
        public static bool UnitTest()
        {
            Random random = new Random(101);
            int    n      = 2048 / 64;

            ulong[] a   = new ulong[n];
            ulong[] b   = new ulong[n];
            ulong[] m   = new ulong[n];
            ulong[] am1 = new ulong[n];
            ulong[] am3 = new ulong[n];
            ulong[] c1  = new ulong[n * 2];
            ulong[] c2  = new ulong[n * 2];
            ulong[] c3  = new ulong[n * 2];
            ulong[] s0  = new ulong[n * 2];
            ulong[] s1  = new ulong[n * 2];
            ulong[] s2  = new ulong[n * 2];

            BigInteger a0, b0, m0;

            TimeSpan
                elapsedMontgomeryExpMod = TimeSpan.Zero,
                elapsedExpMod           = TimeSpan.Zero,
                elapsedBigIntegerExpMod = TimeSpan.Zero;
            bool ok = true;

            for (int iteration = 1; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                getRandom(m, random); m[0] &= ulong.MaxValue - 1;
                a0 = new BigInteger(a.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());
                b0 = new BigInteger(b.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());
                m0 = new BigInteger(m.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());

                a.CopyTo(am1, 0);
                ExpMod(am1, b, m, n, 5);

                BigInteger am2 = BigInteger.Zero;
                elapsedBigIntegerExpMod += MeasureTime(() =>
                {
                    am2 = BigInteger.ModPow(a0, b0, m0);
                });
                var bytes1 = am1.SelectMany(l => BitConverter.GetBytes(l)).ToArray();
                var bytes2 = am2.ToByteArray();
                ok &= Enumerable.Range(0, Math.Min(bytes1.Length, bytes2.Length)).All(idx => bytes1[idx] == bytes2[idx]);
            }

            for (int iteration = 1; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                getRandom(m, random); m[0] |= 1;
                a.CopyTo(am1, 0);
                a.CopyTo(am3, 0);

                elapsedMontgomeryExpMod += MeasureTime(() =>
                {
                    MontgomeryExpMod(am1, b, m, n, 6);
                });
                elapsedExpMod += MeasureTime(() =>
                {
                    ExpMod(am3, b, m, n, 5);
                });

                ok &= Enumerable.Range(0, n).All(idx => am3[idx] == am1[idx]);
            }

            TimeSpan
                elapsedMulDirect = TimeSpan.Zero,
                elapsedKaratsuba = TimeSpan.Zero;

            ulong[] temporaryKaratsubaBuffer = new ulong[GetKaratsubaMultiplicationBufferSize(n)];
            for (int iteration = 128; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                AsmX64Operations.Multiply(a, a, s0, n);

                elapsedMulDirect += MeasureTime(() =>
                {
                    AsmX64Operations.Multiply(a, b, c1, n);
                    AsmX64Operations.Square(a, s1, n);
                });
                elapsedKaratsuba += MeasureTime(() =>
                {
                    AsmX64Operations.Karatsuba(a, b, c2, n, temporaryKaratsubaBuffer);
                    AsmX64Operations.KaratsubaSquare(a, s2, n, temporaryKaratsubaBuffer);
                });

                ok &= Enumerable.Range(0, n * 2).All(idx => c1[idx] == c2[idx]);
                ok &= Enumerable.Range(0, n * 2).All(idx => s0[idx] == s1[idx]);
                ok &= Enumerable.Range(0, n * 2).All(idx => s1[idx] == s2[idx]);
            }
            if (!ok)
            {
                //MessageBox.Show("not ok - error");
                return(false);
            }
            //MessageBox.Show(
            //    "elapsedMontgomeryExpMod: " + elapsedMontgomeryExpMod.ToString() + "\r\n" +
            //    "elapsedExpMod: " + elapsedExpMod.ToString() + "\r\n" +
            //    "elapsedBigIntegerExpMod: " + elapsedBigIntegerExpMod.ToString() + "\r\n" +
            //    "normal: " + elapsedMulDirect.ToString() + "  karatsuba: " + elapsedKaratsuba.ToString());
            return(true);
        }
Example #25
0
 public IntegerNumber Square()
 {
     ulong[] result = new ulong[this.Digits * 2];
     AsmX64Operations.FastestSquare(this.bits, result, this.Digits, true);
     return(new IntegerNumber(result, false));
 }
Example #26
0
        public static bool UnitTest()
        {
            //    SPECIAL prime: 2^64 - 2^32 + 1
            //prime: 2^64 - 2^34 + 1
            //prime: 2^64 - 2^40 + 1
            //    SPECIAL prime: 2 ^ 128 - 2 ^ 54 + 1
            //prime: 2 ^ 128 - 2 ^ 108 + 1
            //prime: 2 ^ 256 - 2 ^ 168 + 1
            //prime: 2 ^ 256 - 2 ^ 174 + 1
            //prime: 2 ^ 512 - 2 ^ 32 + 1
            //prime: 2 ^ 512 - 2 ^ 288 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 142 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 226 + 1
            //prime: 2 ^ 1024 - 2 ^ 562 + 1
            //prime: 2 ^ 1024 - 2 ^ 718 + 1
            //prime: 2 ^ 1024 - 2 ^ 856 + 1
            //prime: 2 ^ 1024 - 2 ^ 880 + 1
            //prime: 2 ^ 4096 - 2 ^ 3510 + 1
            //prime: 2 ^ 4096 - 2 ^ 3708 + 1
            if ("not exec".Trim() == "exec")
            {
                StringBuilder primes = new StringBuilder();
                for (int exp = 6; exp <= 12; exp++)
                {
                    int shift = 1 << exp;
                    Parallel.For(32, shift, i =>
                    {
                        ulong[] baseValue   = new ulong[shift / 64];
                        ulong[] expValue    = new ulong[shift / 64];
                        ulong[] modulo      = new ulong[shift / 64];
                        ulong[] subtractor  = new ulong[shift / 64];
                        ulong[] one         = new ulong[shift / 64];
                        ulong[] pPlusOne    = new ulong[shift / 64];
                        subtractor[i / 64] |= 1UL << (i & 63);
                        modulo[0]           = 1UL;
                        one[0]              = 1UL;
                        AsmX64Operations.Subtract(modulo, subtractor, modulo, 0, modulo.Length);
                        modulo.CopyTo(expValue, 0);
                        modulo.CopyTo(pPlusOne, 0);
                        expValue[0]--;
                        pPlusOne[0]++;

                        int isPrime = 1;
                        for (int a = 2; a <= 128; a++)
                        {
                            one.CopyTo(baseValue, 0);
                            baseValue[0] = (ulong)a;
                            AsmX64Operations.ModularExponentiation(baseValue, expValue, modulo, modulo.Length, 5);
                            if (Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == one[idx]) ||
                                Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == pPlusOne[idx]))
                            {
                                continue;
                            }
                            isPrime = 0;
                            break;
                        }

                        if (isPrime != 0)
                        {
                            lock (primes)
                            {
                                primes.AppendLine("prime: 2^" + shift.ToString() + " - 2^" + i.ToString() + " + 1");
                            }
                        }
                    });
                }
                Clipboard.SetText(primes.ToString());
                System.Windows.Forms.MessageBox.Show(primes.ToString(), "message");
            }

            Random     random = new Random(1002);
            BigInteger maxx   = 0;
            BigInteger minn   = 0;
            bool       ok     = true;

            for (int i = 2; --i >= 0;)
            {
                byte[] bytes1 = new byte[112 * 8 + random.Next(32 * 8)];
                byte[] bytes2 = new byte[112 * 8 + random.Next(32 * 8)];
                random.NextBytes(bytes1);
                random.NextBytes(bytes2);

                BigInteger    n1 = new BigInteger(bytes1);
                BigInteger    n2 = new BigInteger(bytes2);
                IntegerNumber f1 = new IntegerNumber(bytes1);
                IntegerNumber f2 = new IntegerNumber(bytes2);
                if (n1.ToString() != f1.ToString())
                {
                    ok = false;
                }
                if (n2.ToString() != f2.ToString())
                {
                    ok = false;
                }

                BigInteger    a1 = n1 + n2;
                IntegerNumber a2 = f1 + f2;
                if (a1.ToString() != a2.ToString())
                {
                    ok = false;
                }

                BigInteger    s1 = n1 - n2;
                IntegerNumber s2 = f1 - f2;
                if (s1.ToString() != s2.ToString())
                {
                    ok = false;
                }

                BigInteger    m1 = n1 * n2;
                IntegerNumber m2 = f1 * f2;
                if (m1.ToString() != m2.ToString())
                {
                    ok = false;
                }

                int           shrvalue = random.Next(256) + 1;
                BigInteger    sh1      = n1 >> shrvalue;
                IntegerNumber sh2      = f1 >> shrvalue;
                if (sh1.ToString() != sh2.ToString())
                {
                    ok = false;
                }
                if ((-f1).ToString() != (-n1).ToString() || (-f2).ToString() != (-n2).ToString())
                {
                    ok = false;
                }

                int           shlvalue = random.Next(256) + 1;
                BigInteger    shl1     = n1 << shlvalue;
                IntegerNumber shl2     = f1 << shlvalue;
                if (shl1.ToString() != shl2.ToString())
                {
                    ok = false;
                }

                byte[] bytesINV = new byte[(192 + 32) * 8 + random.Next(64 * 8)];
                random.NextBytes(bytesINV);
                BigInteger    num1 = new BigInteger(bytesINV);
                IntegerNumber num2 = new IntegerNumber(bytesINV);
                if (num1.ToString() != num2.ToString())
                {
                    ok = false;
                }
                BigInteger    inv0 = (BigInteger.One << (num2.Digits * 64 * 2)) / num1;
                IntegerNumber inv1 = num2.Inverse();
                if (inv0.ToString() != inv1.ToString())
                {
                    ok = false;
                }

                byte[] bytes4 = new byte[bytes1.Length * 4];
                random.NextBytes(bytes4);
                BigInteger    n4  = new BigInteger(bytes4);
                IntegerNumber f4  = new IntegerNumber(bytes4);
                BigInteger    qb4 = n4 / n1;
                IntegerNumber qn4 = f4 / f1;
                if (qb4.ToString() != qn4.ToString())
                {
                    ok = false;
                }
                byte[] bytes3 = new byte[(bytes1.Length + bytes2.Length) & -8];
                random.NextBytes(bytes3);
                BigInteger    square1 = BigInteger.Abs(new BigInteger(bytes3));
                IntegerNumber square2 = IntegerNumber.Abs(new IntegerNumber(bytes3));
                BigInteger    root1   = square1.Sqrt();
                IntegerNumber root2   = square2.Sqrt();
                if (root1.ToString() != root2.ToString())
                {
                    ok = false;
                }
                if (!ok)
                {
                    break;
                }
            }
            return(ok);
        }
Example #27
0
        public static IntegerNumber Inverse(IntegerNumber number, out IntegerNumber remainder)
        {
            int n = number.Digits;

            if (n <= IntegerDigitsBreakPoint)
            {
                ulong[] a = new ulong[(n + 1) * 2];
                a[n * 2] = 1UL;
                IntegerNumber b = number.ExtendTo(n + 1);
                ulong[]       q = new ulong[(n + 1) * 2];
                AsmX64Operations.GetDivMod(a, b.bits, n + 1, q, true);
                remainder = new IntegerNumber(a, false);
                shrink(remainder);
                IntegerNumber result = new IntegerNumber(q, false);
                shrink(result);
                return(result);
            }

            bool isNegative = false;

            if (number.IsNegative)
            {
                number     = -number;
                isNegative = true;
                n          = number.Digits;
            }
            //Newton iteration: x <- x + x * (1 - d * x^2)
            int           m = (n + 5) >> 1;
            IntegerNumber dx, dhi = number.GetDigits(n - m, m, false);
            IntegerNumber x = Inverse(dhi, out dx);

            //IntegerNumber test = x * d + dx;
            //shrink(ref test);
            //if (test.Digits != d.Digits * 2 + 1 || test.bits[d.Digits * 2] != 1UL || Enumerable.Range(0, d.Digits * 2).Any(idx => test.bits[idx] != 0UL))
            //{
            //    System.Diagnostics.Debugger.Break();
            //}

            const int     CorrectionDigits = 4;
            IntegerNumber dlo = number.GetDigits(0, n - m, true);

            IntegerNumber dp    = (dx << ((n - m) * 64)) - dlo * x;
            IntegerNumber delta = dp >> ((m - CorrectionDigits) * 64);  //keep one additional correction digit.

            shrink(delta);

            delta  *= x;
            delta >>= (m + CorrectionDigits) * 64;
            shrink(delta);

            x <<= (n - m) * 64;
            x  += delta;

            //FACT: number * x == (IntegerNumber.One << (n * 128)) - ((dp << ((n - m) * 64)) - delta * number);
            //but :     remainder = number * x;
            //then:     Array.Resize(ref remainder.bits, n * 2);
            //then:     shrink(ref remainder);
            //then:     remainder = -remainder;
            remainder = ((dp - delta * dhi) << ((n - m) * 64)) - delta * dlo;
            shrink(remainder);

            int count = 0;

            while (remainder.IsNegative)
            {
                remainder += number;
                x         -= One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            while (remainder >= number)
            {
                remainder -= number;
                x         += One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }

            if (isNegative)
            {
                x         = -x;
                remainder = -remainder;
            }
            return(x);
        }
Example #28
0
 public override void GetModFriendlyPrime(ulong[] inputOutput2x)
 {
     AsmX64Operations.GetModFriendlyPrime521(inputOutput2x, N);
 }
Example #29
0
        public static bool ECCUnitTest()
        {
            Random random = new Random(104);
            int    n      = 8;
            bool   ok     = true;

            TimeSpan
                elapsedInvertFast = TimeSpan.Zero,
                elapsedInvertSlow = TimeSpan.Zero;

            byte[] randomBytes = new byte[16 * n];
            for (int i = 20; --i >= 0;)
            {
                ulong[] a0 = new ulong[n * 2]; a0[0] = 1UL;
                random.NextBytes(randomBytes);
                ulong[] x = Enumerable.Range(0, n * 2).Select(idx => idx >= n ? 0 : BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                random.NextBytes(randomBytes);
                ulong[] p = Enumerable.Range(0, n).Select(idx => BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                p[0] |= 1;
                GetDivMod(a0, p, n);
                GetDivMod(x, p, n);
                ulong[] a1 = a0.ToArray();
                ulong[] a2 = a0.ToArray();

                var fx = new FastInteger(x);
                var fp = new FastInteger(p);
                var f0 = new FastInteger(a0);
                if (fx.ToString() != x.ToBigInteger().ToString() || fp.ToString() != p.ToBigInteger().ToString() || f0.ToString() != a0.ToBigInteger().ToString())
                {
                    ok = false;
                }
                FastInteger idv = f0.DivideModulo(fx, fp);
                elapsedInvertFast += MeasureTime(() =>
                {
                    AsmX64Operations.DivideModuloPrime(a1, x, p, n);
                });
                elapsedInvertSlow += MeasureTime(() =>
                {
                    AsmX64Operations.DivideModPSlow(a2, x, p, n);
                });

                if (a1.ToBigInteger().ToString() != idv.ToString())
                {
                    ok = false;
                }

                ulong[] r1 = new ulong[n * 2];
                Multiply(a1, x, r1, n);
                GetDivMod(r1, p, n);

                ulong[] r2 = new ulong[n * 2];
                Multiply(a2, x, r2, n);
                GetDivMod(r2, p, n);

                if (!Enumerable.Range(0, n).All(idx => r1[idx] == r2[idx]))
                {
                    ok = false;
                }
            }

            TimeSpan
                elapsedExponentiationSlow      = TimeSpan.Zero,
                elapsedExponentiation521       = TimeSpan.Zero,
                elapsedExponentiationBigInt    = TimeSpan.Zero,
                elapsedExponentiationFastInt   = TimeSpan.Zero,
                elapsedExponentiationBigInt521 = TimeSpan.Zero,
                elapsedExponentiationFast      = TimeSpan.Zero;
            SECP256K1Base           ecc        = new SECP256K1Base();
            SECP521R1Base           ecc2       = new SECP521R1Base();
            ECCSecP256K1FastInteger fastEcc    = new ECCSecP256K1FastInteger();
            ECCSecP521R1            ecc521     = new ECCSecP521R1();

            random = new Random(105);
            OwnECPoint point    = ecc.G;
            OwnECPoint point521 = ecc2.G;

            ok          = ok && ecc.Verify(point);
            ok          = ok && ecc2.Verify(point521);
            ok          = ok && ecc2.UnitTest();
            randomBytes = new byte[ecc.N * 8];
            ECC other = new ECC();
            int ops   = 1;

            ulong[] order521 = ecc2.Order.ToArray();
            order521[0]--;
            for (int i = ops; --i >= 0;)
            {
                random.NextBytes(randomBytes);
                BigInteger orderInteger = randomBytes.ToBigInteger();
                ulong[]    order        = Enumerable.Range(0, ecc.N).Select(idx => BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                OwnECPoint point2       = ecc.MultiplyReference(point, order);
                OwnECPoint point3       = new OwnECPoint();
                OwnECPoint point521_O   = new OwnECPoint();
                ECPoint    point8_521   = null;
                elapsedExponentiation521 += MeasureTime(() =>
                {
                    point521_O = ecc2.MultiplyWithEndomorphism(point521, order521);
                });
                elapsedExponentiationBigInt521 += MeasureTime(() =>
                {
                    point8_521 = ecc521.ECMultiplication(order521.ToBigInteger());
                });
                ok = ok && point521_O.X.IsEqual(point521.X) && point521_O.Y.ToBigInteger() + point521.Y.ToBigInteger() == (BigInteger.One << 521) - BigInteger.One;
                ok = ok && point8_521.X == point521.X.ToBigInteger() && point8_521.Y + point521.Y.ToBigInteger() == (BigInteger.One << 521) - BigInteger.One;
                FastECPoint point6 = ecc.ECMultiplication(randomBytes.ToFastInteger());
                OwnECPoint  point4 = new OwnECPoint();
                ECPoint     point5 = null;
                ECPoint     point7 = null;
                elapsedExponentiationSlow += MeasureTime(() =>
                {
                    point3 = ecc.Multiply(point, order);
                });
                elapsedExponentiationFast += MeasureTime(() =>
                {
                    point4 = ecc.MultiplyWithEndomorphism(point, order);
                });
                elapsedExponentiationBigInt += MeasureTime(() =>
                {
                    point5 = other.ECMultiplication(orderInteger);
                });
                elapsedExponentiationFastInt += MeasureTime(() =>
                {
                    point7 = fastEcc.ECMultiplication(orderInteger);
                });
                ok &= ecc.Verify(point2);
                ok &= ecc.Verify(point3);
                ok &= ecc.Verify(point4);
                ok &= other.Verify(point5);

                if (!ok || !point2.IsSameAs(point3) || !point2.IsSameAs(point4) || !point2.IsSameAs(point5) ||
                    !point2.IsSameAs(point6) || !point2.IsSameAs(point7))
                {
                    ok = false;
                }
            }
            //MessageBox.Show(
            //    "secP521r1 ecc multiplication: " + elapsedExponentiation521.ToString() + " ops/sec = " + (ops / elapsedExponentiation521.TotalSeconds).ToString("N3") + "\r\n" +
            //    "P521R1 BigInt ecc multiplication: " + elapsedExponentiationBigInt521.ToString() + " ops/sec = " + (ops / elapsedExponentiationBigInt521.TotalSeconds).ToString("N3") + "\r\n" +
            //    "Fast ecc multiplication: " + elapsedExponentiationFast.ToString() + " ops/sec = " + (ops / elapsedExponentiationFast.TotalSeconds).ToString("N3") + "\r\n" +
            //    "BigInteger ecc multiplication: " + elapsedExponentiationBigInt.ToString() + " ops/sec = " + (ops / elapsedExponentiationBigInt.TotalSeconds).ToString("N3") + "\r\n" +
            //    "FastInteger ecc multiplication: " + elapsedExponentiationFastInt.ToString() + " ops/sec = " + (ops / elapsedExponentiationFastInt.TotalSeconds).ToString("N3") + "\r\n" +
            //    "Slow ecc multiplication: " + elapsedExponentiationSlow.ToString() + " ops/sec = " + (ops / elapsedExponentiationSlow.TotalSeconds).ToString("N3") + "\r\n", "Time",
            //     MessageBoxButtons.OK, MessageBoxIcon.Information);

            return(ok);
        }
Example #30
0
 public override void RemodFriendlyPrime(ulong[] inputOutput1x)
 {
     AsmX64Operations.RemodFriendlyPrime521(inputOutput1x, N);
 }