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