<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

SecT571Field

static class SecT571Field
using Org.BouncyCastle.Math.Raw; using System; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal static class SecT571Field { private const ulong M59 = 576460752303423487; private static readonly ulong[] ROOT_Z = new ulong[9] { 3161836309350906777, 10804290191530228771, 14625517132619890193, 7312758566309945096, 17890083061325672324, 8945041530681231562, 13695892802195391589, 6847946401097695794, 541669439031730457 }; public static void Add(ulong[] x, ulong[] y, ulong[] z) { Nat.Xor64(9, x, y, z); } private static void Add(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff) { Nat.Xor64(9, x, xOff, y, yOff, z, zOff); } public static void AddBothTo(ulong[] x, ulong[] y, ulong[] z) { for (int i = 0; i < 9; i++) { z[i] ^= (x[i] ^ y[i]); } } private static void AddBothTo(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff) { for (int i = 0; i < 9; i++) { z[zOff + i] ^= (x[xOff + i] ^ y[yOff + i]); } } public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) { Nat.Xor64(18, xx, yy, zz); } public static void AddOne(ulong[] x, ulong[] z) { z[0] = (x[0] ^ 1); for (int i = 1; i < 9; i++) { z[i] = x[i]; } } public static void AddTo(ulong[] x, ulong[] z) { Nat.XorTo64(9, x, z); } public static ulong[] FromBigInteger(BigInteger x) { return Nat.FromBigInteger64(571, x); } public static void HalfTrace(ulong[] x, ulong[] z) { ulong[] array = Nat576.CreateExt64(); Nat576.Copy64(x, z); for (int i = 1; i < 571; i += 2) { ImplSquare(z, array); Reduce(array, z); ImplSquare(z, array); Reduce(array, z); AddTo(x, z); } } public static void Invert(ulong[] x, ulong[] z) { if (Nat576.IsZero64(x)) throw new InvalidOperationException(); ulong[] array = Nat576.Create64(); ulong[] array2 = Nat576.Create64(); ulong[] array3 = Nat576.Create64(); Square(x, array3); Square(array3, array); Square(array, array2); Multiply(array, array2, array); SquareN(array, 2, array2); Multiply(array, array2, array); Multiply(array, array3, array); SquareN(array, 5, array2); Multiply(array, array2, array); SquareN(array2, 5, array2); Multiply(array, array2, array); SquareN(array, 15, array2); Multiply(array, array2, array3); SquareN(array3, 30, array); SquareN(array, 30, array2); Multiply(array, array2, array); SquareN(array, 60, array2); Multiply(array, array2, array); SquareN(array2, 60, array2); Multiply(array, array2, array); SquareN(array, 180, array2); Multiply(array, array2, array); SquareN(array2, 180, array2); Multiply(array, array2, array); Multiply(array, array3, z); } public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] array = Nat576.CreateExt64(); ImplMultiply(x, y, array); Reduce(array, z); } public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) { ulong[] array = Nat576.CreateExt64(); ImplMultiply(x, y, array); AddExt(zz, array, zz); } public static void MultiplyExt(ulong[] x, ulong[] y, ulong[] zz) { Array.Clear(zz, 0, 18); ImplMultiply(x, y, zz); } public static void MultiplyPrecomp(ulong[] x, ulong[] precomp, ulong[] z) { ulong[] array = Nat576.CreateExt64(); ImplMultiplyPrecomp(x, precomp, array); Reduce(array, z); } public static void MultiplyPrecompAddToExt(ulong[] x, ulong[] precomp, ulong[] zz) { ulong[] array = Nat576.CreateExt64(); ImplMultiplyPrecomp(x, precomp, array); AddExt(zz, array, zz); } public static ulong[] PrecompMultiplicand(ulong[] x) { int num = 144; ulong[] array = new ulong[num << 1]; Array.Copy(x, 0, array, 9, 9); int num2 = 0; for (int num3 = 7; num3 > 0; num3--) { num2 += 18; Nat.ShiftUpBit64(9, array, num2 >> 1, 0, array, num2); Reduce5(array, num2); Add(array, 9, array, num2, array, num2 + 9); } Nat.ShiftUpBits64(num, array, 0, 4, 0, array, num); return array; } public static void Reduce(ulong[] xx, ulong[] z) { ulong num = xx[9]; ulong num2 = xx[17]; ulong num3 = num; num = (num3 ^ (num2 >> 59) ^ (num2 >> 57) ^ (num2 >> 54) ^ (num2 >> 49)); num3 = (xx[8] ^ (num2 << 5) ^ (num2 << 7) ^ (num2 << 10) ^ (num2 << 15)); for (int num4 = 16; num4 >= 10; num4--) { num2 = xx[num4]; z[num4 - 8] = (num3 ^ (num2 >> 59) ^ (num2 >> 57) ^ (num2 >> 54) ^ (num2 >> 49)); num3 = (xx[num4 - 9] ^ (num2 << 5) ^ (num2 << 7) ^ (num2 << 10) ^ (num2 << 15)); } num2 = num; z[1] = (num3 ^ (num2 >> 59) ^ (num2 >> 57) ^ (num2 >> 54) ^ (num2 >> 49)); num3 = (xx[0] ^ (num2 << 5) ^ (num2 << 7) ^ (num2 << 10) ^ (num2 << 15)); ulong num5 = z[8]; ulong num6 = num5 >> 59; z[0] = (num3 ^ num6 ^ (num6 << 2) ^ (num6 << 5) ^ (num6 << 10)); z[8] = (num5 & 576460752303423487); } public static void Reduce5(ulong[] z, int zOff) { ulong num = z[zOff + 8]; ulong num2 = num >> 59; z[zOff] ^= (num2 ^ (num2 << 2) ^ (num2 << 5) ^ (num2 << 10)); z[zOff + 8] = (num & 576460752303423487); } public static void Sqrt(ulong[] x, ulong[] z) { ulong[] array = Nat576.Create64(); ulong[] array2 = Nat576.Create64(); array2[0] = Interleave.Unshuffle(x[0], x[1], out array[0]); array2[1] = Interleave.Unshuffle(x[2], x[3], out array[1]); array2[2] = Interleave.Unshuffle(x[4], x[5], out array[2]); array2[3] = Interleave.Unshuffle(x[6], x[7], out array[3]); array2[4] = Interleave.Unshuffle(x[8], out array[4]); Multiply(array2, ROOT_Z, z); Add(z, array, z); } public static void Square(ulong[] x, ulong[] z) { ulong[] array = Nat576.CreateExt64(); ImplSquare(x, array); Reduce(array, z); } public static void SquareAddToExt(ulong[] x, ulong[] zz) { ulong[] array = Nat576.CreateExt64(); ImplSquare(x, array); AddExt(zz, array, zz); } public static void SquareExt(ulong[] x, ulong[] zz) { ImplSquare(x, zz); } public static void SquareN(ulong[] x, int n, ulong[] z) { ulong[] array = Nat576.CreateExt64(); ImplSquare(x, array); Reduce(array, z); while (--n > 0) { ImplSquare(z, array); Reduce(array, z); } } public static uint Trace(ulong[] x) { return (uint)((int)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1); } private static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { ulong[] u = new ulong[16]; for (int i = 0; i < 9; i++) { ImplMulwAcc(u, x[i], y[i], zz, i << 1); } ulong num = zz[0]; ulong num2 = zz[1]; num ^= zz[2]; zz[1] = (num ^ num2); num2 ^= zz[3]; num ^= zz[4]; zz[2] = (num ^ num2); num2 ^= zz[5]; num ^= zz[6]; zz[3] = (num ^ num2); num2 ^= zz[7]; num ^= zz[8]; zz[4] = (num ^ num2); num2 ^= zz[9]; num ^= zz[10]; zz[5] = (num ^ num2); num2 ^= zz[11]; num ^= zz[12]; zz[6] = (num ^ num2); num2 ^= zz[13]; num ^= zz[14]; zz[7] = (num ^ num2); num2 ^= zz[15]; num ^= zz[16]; zz[8] = (num ^ num2); num2 ^= zz[17]; ulong num3 = num ^ num2; zz[9] = (zz[0] ^ num3); zz[10] = (zz[1] ^ num3); zz[11] = (zz[2] ^ num3); zz[12] = (zz[3] ^ num3); zz[13] = (zz[4] ^ num3); zz[14] = (zz[5] ^ num3); zz[15] = (zz[6] ^ num3); zz[16] = (zz[7] ^ num3); zz[17] = (zz[8] ^ num3); ImplMulwAcc(u, x[0] ^ x[1], y[0] ^ y[1], zz, 1); ImplMulwAcc(u, x[0] ^ x[2], y[0] ^ y[2], zz, 2); ImplMulwAcc(u, x[0] ^ x[3], y[0] ^ y[3], zz, 3); ImplMulwAcc(u, x[1] ^ x[2], y[1] ^ y[2], zz, 3); ImplMulwAcc(u, x[0] ^ x[4], y[0] ^ y[4], zz, 4); ImplMulwAcc(u, x[1] ^ x[3], y[1] ^ y[3], zz, 4); ImplMulwAcc(u, x[0] ^ x[5], y[0] ^ y[5], zz, 5); ImplMulwAcc(u, x[1] ^ x[4], y[1] ^ y[4], zz, 5); ImplMulwAcc(u, x[2] ^ x[3], y[2] ^ y[3], zz, 5); ImplMulwAcc(u, x[0] ^ x[6], y[0] ^ y[6], zz, 6); ImplMulwAcc(u, x[1] ^ x[5], y[1] ^ y[5], zz, 6); ImplMulwAcc(u, x[2] ^ x[4], y[2] ^ y[4], zz, 6); ImplMulwAcc(u, x[0] ^ x[7], y[0] ^ y[7], zz, 7); ImplMulwAcc(u, x[1] ^ x[6], y[1] ^ y[6], zz, 7); ImplMulwAcc(u, x[2] ^ x[5], y[2] ^ y[5], zz, 7); ImplMulwAcc(u, x[3] ^ x[4], y[3] ^ y[4], zz, 7); ImplMulwAcc(u, x[0] ^ x[8], y[0] ^ y[8], zz, 8); ImplMulwAcc(u, x[1] ^ x[7], y[1] ^ y[7], zz, 8); ImplMulwAcc(u, x[2] ^ x[6], y[2] ^ y[6], zz, 8); ImplMulwAcc(u, x[3] ^ x[5], y[3] ^ y[5], zz, 8); ImplMulwAcc(u, x[1] ^ x[8], y[1] ^ y[8], zz, 9); ImplMulwAcc(u, x[2] ^ x[7], y[2] ^ y[7], zz, 9); ImplMulwAcc(u, x[3] ^ x[6], y[3] ^ y[6], zz, 9); ImplMulwAcc(u, x[4] ^ x[5], y[4] ^ y[5], zz, 9); ImplMulwAcc(u, x[2] ^ x[8], y[2] ^ y[8], zz, 10); ImplMulwAcc(u, x[3] ^ x[7], y[3] ^ y[7], zz, 10); ImplMulwAcc(u, x[4] ^ x[6], y[4] ^ y[6], zz, 10); ImplMulwAcc(u, x[3] ^ x[8], y[3] ^ y[8], zz, 11); ImplMulwAcc(u, x[4] ^ x[7], y[4] ^ y[7], zz, 11); ImplMulwAcc(u, x[5] ^ x[6], y[5] ^ y[6], zz, 11); ImplMulwAcc(u, x[4] ^ x[8], y[4] ^ y[8], zz, 12); ImplMulwAcc(u, x[5] ^ x[7], y[5] ^ y[7], zz, 12); ImplMulwAcc(u, x[5] ^ x[8], y[5] ^ y[8], zz, 13); ImplMulwAcc(u, x[6] ^ x[7], y[6] ^ y[7], zz, 13); ImplMulwAcc(u, x[6] ^ x[8], y[6] ^ y[8], zz, 14); ImplMulwAcc(u, x[7] ^ x[8], y[7] ^ y[8], zz, 15); } private static void ImplMultiplyPrecomp(ulong[] x, ulong[] precomp, ulong[] zz) { uint num = 15; for (int num2 = 56; num2 >= 0; num2 -= 8) { for (int i = 1; i < 9; i += 2) { int num3 = (int)(x[i] >> num2); uint num4 = (uint)(num3 & (int)num); uint num5 = ((uint)num3 >> 4) & num; AddBothTo(precomp, (int)(9 * num4), precomp, (int)(9 * (num5 + 16)), zz, i - 1); } Nat.ShiftUpBits64(16, zz, 0, 8, 0); } for (int num6 = 56; num6 >= 0; num6 -= 8) { for (int j = 0; j < 9; j += 2) { int num7 = (int)(x[j] >> num6); uint num8 = (uint)(num7 & (int)num); uint num9 = ((uint)num7 >> 4) & num; AddBothTo(precomp, (int)(9 * num8), precomp, (int)(9 * (num9 + 16)), zz, j); } if (num6 > 0) Nat.ShiftUpBits64(18, zz, 0, 8, 0); } } private static void ImplMulwAcc(ulong[] u, ulong x, ulong y, ulong[] z, int zOff) { u[1] = y; for (int i = 2; i < 16; i += 2) { u[i] = u[i >> 1] << 1; u[i + 1] = (u[i] ^ y); } uint num = (uint)x; ulong num2 = 0; ulong num3 = u[num & 15] ^ (u[(num >> 4) & 15] << 4); int num4 = 56; do { num = (uint)(x >> num4); ulong num5 = u[num & 15] ^ (u[(num >> 4) & 15] << 4); num3 ^= num5 << num4; num2 ^= num5 >> -num4; } while ((num4 -= 8) > 0); for (int j = 0; j < 7; j++) { x = (ulong)((long)x & -72340172838076674) >> 1; num2 = (ulong)((long)num2 ^ ((long)x & ((long)(y << j) >> 63))); } z[zOff] ^= num3; z[zOff + 1] ^= num2; } private static void ImplSquare(ulong[] x, ulong[] zz) { Interleave.Expand64To128(x, 0, 9, zz, 0); } } }