// 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); }
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)); }
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); }
public void SquareModP(ulong[] inputOutput) { AsmX64Operations.KaratsubaSquare(inputOutput, temporary2x, N, temporaryKaratsubaBuffer); this.GetModFriendlyPrime(temporary2x); for (int i = N; --i >= 0;) { inputOutput[i] = temporary2x[i]; } }
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]; } }
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)); }
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)); }
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); }
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); }
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); }
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)); }
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])); }
//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); }
private void subScaledModP(ulong[] result, ulong[] input, ulong multiplier) { AsmX64Operations.SubScaledModP521(result, input, multiplier, N); }
private void addScaledModP(ulong[] result, ulong[] input, ulong multiplier) { AsmX64Operations.AddScaledModP(result, input, multiplier, LowP, N); }
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); }
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)); }
private void addModP(ulong[] input1, ulong[] input2, ulong[] result) { AsmX64Operations.AddModP521(input1, input2, result, N); }
private void subModP(ulong[] input1, ulong[] input2, ulong[] result) { AsmX64Operations.SubtractModP521(input1, input2, result, N); }
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); }
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); }
public IntegerNumber Square() { ulong[] result = new ulong[this.Digits * 2]; AsmX64Operations.FastestSquare(this.bits, result, this.Digits, true); return(new IntegerNumber(result, false)); }
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); }
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); }
public override void GetModFriendlyPrime(ulong[] inputOutput2x) { AsmX64Operations.GetModFriendlyPrime521(inputOutput2x, N); }
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); }
public override void RemodFriendlyPrime(ulong[] inputOutput1x) { AsmX64Operations.RemodFriendlyPrime521(inputOutput1x, N); }