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