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

X25519Field

public static class X25519Field
using Org.BouncyCastle.Math.Raw; using System; namespace Org.BouncyCastle.Math.EC.Rfc7748 { public static class X25519Field { public const int Size = 10; private const int M24 = 16777215; private const int M25 = 33554431; private const int M26 = 67108863; private static readonly uint[] P32 = new uint[8] { 4294967277, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, 2147483647 }; private static readonly int[] RootNegOne = new int[10] { -32595792, -7943725, 4688975, 3500415, 6194736, 33281959, -12573105, -1002827, 163343, 5703241 }; public static void Add(int[] x, int[] y, int[] z) { for (int i = 0; i < 10; i++) { z[i] = x[i] + y[i]; } } public static void AddOne(int[] z) { z[0]++; } public static void AddOne(int[] z, int zOff) { z[zOff]++; } public static void Apm(int[] x, int[] y, int[] zp, int[] zm) { for (int i = 0; i < 10; i++) { int num = x[i]; int num2 = y[i]; zp[i] = num + num2; zm[i] = num - num2; } } public static int AreEqual(int[] x, int[] y) { int num = 0; for (int i = 0; i < 10; i++) { num |= (x[i] ^ y[i]); } num |= num >> 16; num &= 65535; return num - 1 >> 31; } public static bool AreEqualVar(int[] x, int[] y) { return AreEqual(x, y) != 0; } public static void Carry(int[] z) { int num = z[0]; int num2 = z[1]; int num3 = z[2]; int num4 = z[3]; int num5 = z[4]; int num6 = z[5]; int num7 = z[6]; int num8 = z[7]; int num9 = z[8]; int num10 = z[9]; num3 += num2 >> 26; num2 &= 67108863; num5 += num4 >> 26; num4 &= 67108863; num8 += num7 >> 26; num7 &= 67108863; num10 += num9 >> 26; num9 &= 67108863; num4 += num3 >> 25; num3 &= 33554431; num6 += num5 >> 25; num5 &= 33554431; num9 += num8 >> 25; num8 &= 33554431; num += (num10 >> 25) * 38; num10 &= 33554431; num2 += num >> 26; num &= 67108863; num7 += num6 >> 26; num6 &= 67108863; num3 += num2 >> 26; num2 &= 67108863; num5 += num4 >> 26; num4 &= 67108863; num8 += num7 >> 26; num7 &= 67108863; num10 += num9 >> 26; num9 &= 67108863; z[0] = num; z[1] = num2; z[2] = num3; z[3] = num4; z[4] = num5; z[5] = num6; z[6] = num7; z[7] = num8; z[8] = num9; z[9] = num10; } public static void CMov(int cond, int[] x, int xOff, int[] z, int zOff) { for (int i = 0; i < 10; i++) { int num = z[zOff + i]; int num2 = num ^ x[xOff + i]; num = (z[zOff + i] = (num ^ (num2 & cond))); } } public static void CNegate(int negate, int[] z) { int num = -negate; for (int i = 0; i < 10; i++) { z[i] = (z[i] ^ num) - num; } } public static void Copy(int[] x, int xOff, int[] z, int zOff) { for (int i = 0; i < 10; i++) { z[zOff + i] = x[xOff + i]; } } public static int[] Create() { return new int[10]; } public static int[] CreateTable(int n) { return new int[10 * n]; } public static void CSwap(int swap, int[] a, int[] b) { int num = -swap; for (int i = 0; i < 10; i++) { int num2 = a[i]; int num3 = b[i]; int num4 = num & (num2 ^ num3); a[i] = (num2 ^ num4); b[i] = (num3 ^ num4); } } [CLSCompliant(false)] public static void Decode(uint[] x, int xOff, int[] z) { Decode128(x, xOff, z, 0); Decode128(x, xOff + 4, z, 5); z[9] &= 16777215; } public static void Decode(byte[] x, int[] z) { Decode128(x, 0, z, 0); Decode128(x, 16, z, 5); z[9] &= 16777215; } public static void Decode(byte[] x, int xOff, int[] z) { Decode128(x, xOff, z, 0); Decode128(x, xOff + 16, z, 5); z[9] &= 16777215; } public static void Decode(byte[] x, int xOff, int[] z, int zOff) { Decode128(x, xOff, z, zOff); Decode128(x, xOff + 16, z, zOff + 5); z[zOff + 9] &= 16777215; } private static void Decode128(uint[] x, int xOff, int[] z, int zOff) { uint num = x[xOff]; uint num2 = x[xOff + 1]; uint num3 = x[xOff + 2]; uint num4 = x[xOff + 3]; z[zOff] = (int)(num & 67108863); z[zOff + 1] = (int)(((num2 << 6) | (num >> 26)) & 67108863); z[zOff + 2] = (int)(((num3 << 12) | (num2 >> 20)) & 33554431); z[zOff + 3] = (int)(((num4 << 19) | (num3 >> 13)) & 67108863); z[zOff + 4] = (int)(num4 >> 7); } private static void Decode128(byte[] bs, int off, int[] z, int zOff) { uint num = Decode32(bs, off); uint num2 = Decode32(bs, off + 4); uint num3 = Decode32(bs, off + 8); uint num4 = Decode32(bs, off + 12); z[zOff] = (int)(num & 67108863); z[zOff + 1] = (int)(((num2 << 6) | (num >> 26)) & 67108863); z[zOff + 2] = (int)(((num3 << 12) | (num2 >> 20)) & 33554431); z[zOff + 3] = (int)(((num4 << 19) | (num3 >> 13)) & 67108863); z[zOff + 4] = (int)(num4 >> 7); } private static uint Decode32(byte[] bs, int off) { return (uint)(bs[off] | (bs[++off] << 8) | (bs[++off] << 16) | (bs[++off] << 24)); } [CLSCompliant(false)] public static void Encode(int[] x, uint[] z, int zOff) { Encode128(x, 0, z, zOff); Encode128(x, 5, z, zOff + 4); } public static void Encode(int[] x, byte[] z) { Encode128(x, 0, z, 0); Encode128(x, 5, z, 16); } public static void Encode(int[] x, byte[] z, int zOff) { Encode128(x, 0, z, zOff); Encode128(x, 5, z, zOff + 16); } public static void Encode(int[] x, int xOff, byte[] z, int zOff) { Encode128(x, xOff, z, zOff); Encode128(x, xOff + 5, z, zOff + 16); } private static void Encode128(int[] x, int xOff, uint[] z, int zOff) { uint num = (uint)x[xOff]; uint num2 = (uint)x[xOff + 1]; uint num3 = (uint)x[xOff + 2]; uint num4 = (uint)x[xOff + 3]; uint num5 = (uint)x[xOff + 4]; z[zOff] = (num | (num2 << 26)); z[zOff + 1] = ((num2 >> 6) | (num3 << 20)); z[zOff + 2] = ((num3 >> 12) | (num4 << 13)); z[zOff + 3] = ((num4 >> 19) | (num5 << 7)); } private static void Encode128(int[] x, int xOff, byte[] bs, int off) { int num = x[xOff]; uint num2 = (uint)x[xOff + 1]; uint num3 = (uint)x[xOff + 2]; uint num4 = (uint)x[xOff + 3]; uint num5 = (uint)x[xOff + 4]; Encode32((uint)(num | (int)(num2 << 26)), bs, off); Encode32((num2 >> 6) | (num3 << 20), bs, off + 4); Encode32((num3 >> 12) | (num4 << 13), bs, off + 8); Encode32((num4 >> 19) | (num5 << 7), bs, off + 12); } private static void Encode32(uint n, byte[] bs, int off) { bs[off] = (byte)n; bs[++off] = (byte)(n >> 8); bs[++off] = (byte)(n >> 16); bs[++off] = (byte)(n >> 24); } public static void Inv(int[] x, int[] z) { int[] array = Create(); uint[] array2 = new uint[8]; Copy(x, 0, array, 0); Normalize(array); Encode(array, array2, 0); Mod.ModOddInverse(P32, array2, array2); Decode(array2, 0, z); } public static void InvVar(int[] x, int[] z) { int[] array = Create(); uint[] array2 = new uint[8]; Copy(x, 0, array, 0); Normalize(array); Encode(array, array2, 0); Mod.ModOddInverseVar(P32, array2, array2); Decode(array2, 0, z); } public static int IsOne(int[] x) { int num = x[0] ^ 1; for (int i = 1; i < 10; i++) { num |= x[i]; } num |= num >> 16; num &= 65535; return num - 1 >> 31; } public static bool IsOneVar(int[] x) { return IsOne(x) != 0; } public static int IsZero(int[] x) { int num = 0; for (int i = 0; i < 10; i++) { num |= x[i]; } num |= num >> 16; num &= 65535; return num - 1 >> 31; } public static bool IsZeroVar(int[] x) { return IsZero(x) != 0; } public static void Mul(int[] x, int y, int[] z) { int num = x[0]; int num2 = x[1]; int num3 = x[2]; int num4 = x[3]; int num5 = x[4]; int num6 = x[5]; int num7 = x[6]; int num8 = x[7]; int num9 = x[8]; int num10 = x[9]; long num11 = (long)num3 * (long)y; num3 = ((int)num11 & 33554431); num11 >>= 25; long num12 = (long)num5 * (long)y; num5 = ((int)num12 & 33554431); num12 >>= 25; long num13 = (long)num8 * (long)y; num8 = ((int)num13 & 33554431); num13 >>= 25; long num14 = (long)num10 * (long)y; num10 = ((int)num14 & 33554431); num14 >>= 25; num14 *= 38; num14 += (long)num * (long)y; z[0] = ((int)num14 & 67108863); num14 >>= 26; num12 += (long)num6 * (long)y; z[5] = ((int)num12 & 67108863); num12 >>= 26; num14 += (long)num2 * (long)y; z[1] = ((int)num14 & 67108863); num14 >>= 26; num11 += (long)num4 * (long)y; z[3] = ((int)num11 & 67108863); num11 >>= 26; num12 += (long)num7 * (long)y; z[6] = ((int)num12 & 67108863); num12 >>= 26; num13 += (long)num9 * (long)y; z[8] = ((int)num13 & 67108863); num13 >>= 26; z[2] = num3 + (int)num14; z[4] = num5 + (int)num11; z[7] = num8 + (int)num12; z[9] = num10 + (int)num13; } public static void Mul(int[] x, int[] y, int[] z) { int num = x[0]; int num2 = y[0]; int num3 = x[1]; int num4 = y[1]; int num5 = x[2]; int num6 = y[2]; int num7 = x[3]; int num8 = y[3]; int num9 = x[4]; int num10 = y[4]; int num11 = x[5]; int num12 = y[5]; int num13 = x[6]; int num14 = y[6]; int num15 = x[7]; int num16 = y[7]; int num17 = x[8]; int num18 = y[8]; int num19 = x[9]; int num20 = y[9]; long num21 = (long)num * (long)num2; long num22 = (long)num * (long)num4 + (long)num3 * (long)num2; long num23 = (long)num * (long)num6 + (long)num3 * (long)num4 + (long)num5 * (long)num2; long num24 = (long)num3 * (long)num6 + (long)num5 * (long)num4; num24 <<= 1; num24 += (long)num * (long)num8 + (long)num7 * (long)num2; long num25 = (long)num5 * (long)num6; num25 <<= 1; num25 += (long)num * (long)num10 + (long)num3 * (long)num8 + (long)num7 * (long)num4 + (long)num9 * (long)num2; long num26 = (long)num3 * (long)num10 + (long)num5 * (long)num8 + (long)num7 * (long)num6 + (long)num9 * (long)num4; num26 <<= 1; long num27 = (long)num5 * (long)num10 + (long)num9 * (long)num6; num27 <<= 1; num27 += (long)num7 * (long)num8; long num28 = (long)num7 * (long)num10 + (long)num9 * (long)num8; long num29 = (long)num9 * (long)num10; num29 <<= 1; long num30 = (long)num11 * (long)num12; long num31 = (long)num11 * (long)num14 + (long)num13 * (long)num12; long num32 = (long)num11 * (long)num16 + (long)num13 * (long)num14 + (long)num15 * (long)num12; long num33 = (long)num13 * (long)num16 + (long)num15 * (long)num14; num33 <<= 1; num33 += (long)num11 * (long)num18 + (long)num17 * (long)num12; long num34 = (long)num15 * (long)num16; num34 <<= 1; num34 += (long)num11 * (long)num20 + (long)num13 * (long)num18 + (long)num17 * (long)num14 + (long)num19 * (long)num12; long num35 = (long)num13 * (long)num20 + (long)num15 * (long)num18 + (long)num17 * (long)num16 + (long)num19 * (long)num14; long num36 = (long)num15 * (long)num20 + (long)num19 * (long)num16; num36 <<= 1; num36 += (long)num17 * (long)num18; long num37 = (long)num17 * (long)num20 + (long)num19 * (long)num18; long num38 = (long)num19 * (long)num20; num21 -= num35 * 76; num22 -= num36 * 38; num23 -= num37 * 38; num24 -= num38 * 76; num26 -= num30; num27 -= num31; num28 -= num32; num29 -= num33; num += num11; num2 += num12; num3 += num13; num4 += num14; num5 += num15; num6 += num16; num7 += num17; num8 += num18; num9 += num19; num10 += num20; long num39 = (long)num * (long)num2; long num40 = (long)num * (long)num4 + (long)num3 * (long)num2; long num41 = (long)num * (long)num6 + (long)num3 * (long)num4 + (long)num5 * (long)num2; long num42 = (long)num3 * (long)num6 + (long)num5 * (long)num4; num42 <<= 1; num42 += (long)num * (long)num8 + (long)num7 * (long)num2; long num43 = (long)num5 * (long)num6; num43 <<= 1; num43 += (long)num * (long)num10 + (long)num3 * (long)num8 + (long)num7 * (long)num4 + (long)num9 * (long)num2; long num44 = (long)num3 * (long)num10 + (long)num5 * (long)num8 + (long)num7 * (long)num6 + (long)num9 * (long)num4; num44 <<= 1; long num45 = (long)num5 * (long)num10 + (long)num9 * (long)num6; num45 <<= 1; num45 += (long)num7 * (long)num8; long num46 = (long)num7 * (long)num10 + (long)num9 * (long)num8; long num47 = (long)num9 * (long)num10; num47 <<= 1; long num48 = num29 + (num42 - num24); int num49 = (int)num48 & 67108863; num48 >>= 26; num48 += num43 - num25 - num34; int num50 = (int)num48 & 33554431; num48 >>= 25; num48 = num21 + (num48 + num44 - num26) * 38; z[0] = ((int)num48 & 67108863); num48 >>= 26; num48 += num22 + (num45 - num27) * 38; z[1] = ((int)num48 & 67108863); num48 >>= 26; num48 += num23 + (num46 - num28) * 38; z[2] = ((int)num48 & 33554431); num48 >>= 25; num48 += num24 + (num47 - num29) * 38; z[3] = ((int)num48 & 67108863); num48 >>= 26; num48 += num25 + num34 * 38; z[4] = ((int)num48 & 33554431); num48 >>= 25; num48 += num26 + (num39 - num21); z[5] = ((int)num48 & 67108863); num48 >>= 26; num48 += num27 + (num40 - num22); z[6] = ((int)num48 & 67108863); num48 >>= 26; num48 += num28 + (num41 - num23); z[7] = ((int)num48 & 33554431); num48 >>= 25; num48 += num49; z[8] = ((int)num48 & 67108863); num48 >>= 26; z[9] = num50 + (int)num48; } public static void Negate(int[] x, int[] z) { for (int i = 0; i < 10; i++) { z[i] = -x[i]; } } public static void Normalize(int[] z) { int num = (z[9] >> 23) & 1; Reduce(z, num); Reduce(z, -num); } public static void One(int[] z) { z[0] = 1; for (int i = 1; i < 10; i++) { z[i] = 0; } } private static void PowPm5d8(int[] x, int[] rx2, int[] rz) { Sqr(x, rx2); Mul(x, rx2, rx2); int[] array = Create(); Sqr(rx2, array); Mul(x, array, array); int[] array2 = array; Sqr(array, 2, array2); Mul(rx2, array2, array2); int[] array3 = Create(); Sqr(array2, 5, array3); Mul(array2, array3, array3); int[] array4 = Create(); Sqr(array3, 5, array4); Mul(array2, array4, array4); int[] array5 = array2; Sqr(array4, 10, array5); Mul(array3, array5, array5); int[] array6 = array3; Sqr(array5, 25, array6); Mul(array5, array6, array6); int[] array7 = array4; Sqr(array6, 25, array7); Mul(array5, array7, array7); int[] array8 = array5; Sqr(array7, 50, array8); Mul(array6, array8, array8); int[] array9 = array6; Sqr(array8, 125, array9); Mul(array8, array9, array9); int[] array10 = array8; Sqr(array9, 2, array10); Mul(array10, x, rz); } private static void Reduce(int[] z, int x) { int num = z[9]; int num2 = num & 16777215; long num3 = ((num >> 24) + x) * 19; num3 += z[0]; z[0] = ((int)num3 & 67108863); num3 >>= 26; num3 += z[1]; z[1] = ((int)num3 & 67108863); num3 >>= 26; num3 += z[2]; z[2] = ((int)num3 & 33554431); num3 >>= 25; num3 += z[3]; z[3] = ((int)num3 & 67108863); num3 >>= 26; num3 += z[4]; z[4] = ((int)num3 & 33554431); num3 >>= 25; num3 += z[5]; z[5] = ((int)num3 & 67108863); num3 >>= 26; num3 += z[6]; z[6] = ((int)num3 & 67108863); num3 >>= 26; num3 += z[7]; z[7] = ((int)num3 & 33554431); num3 >>= 25; num3 += z[8]; z[8] = ((int)num3 & 67108863); num3 >>= 26; z[9] = num2 + (int)num3; } public static void Sqr(int[] x, int[] z) { int num = x[0]; int num2 = x[1]; int num3 = x[2]; int num4 = x[3]; int num5 = x[4]; int num6 = x[5]; int num7 = x[6]; int num8 = x[7]; int num9 = x[8]; int num10 = x[9]; int num11 = num2 * 2; int num12 = num3 * 2; int num13 = num4 * 2; int num14 = num5 * 2; long num15 = (long)num * (long)num; long num16 = (long)num * (long)num11; long num17 = (long)num * (long)num12 + (long)num2 * (long)num2; long num18 = (long)num11 * (long)num12 + (long)num * (long)num13; long num19 = (long)num3 * (long)num12 + (long)num * (long)num14 + (long)num2 * (long)num13; long num20 = (long)num11 * (long)num14 + (long)num12 * (long)num13; long num21 = (long)num12 * (long)num14 + (long)num4 * (long)num4; long num22 = (long)num4 * (long)num14; long num23 = (long)num5 * (long)num14; int num24 = num7 * 2; int num25 = num8 * 2; int num26 = num9 * 2; int num27 = num10 * 2; long num28 = (long)num6 * (long)num6; long num29 = (long)num6 * (long)num24; long num30 = (long)num6 * (long)num25 + (long)num7 * (long)num7; long num31 = (long)num24 * (long)num25 + (long)num6 * (long)num26; long num32 = (long)num8 * (long)num25 + (long)num6 * (long)num27 + (long)num7 * (long)num26; long num33 = (long)num24 * (long)num27 + (long)num25 * (long)num26; long num34 = (long)num25 * (long)num27 + (long)num9 * (long)num9; long num35 = (long)num9 * (long)num27; long num36 = (long)num10 * (long)num27; num15 -= num33 * 38; num16 -= num34 * 38; num17 -= num35 * 38; num18 -= num36 * 38; num20 -= num28; num21 -= num29; num22 -= num30; num23 -= num31; num += num6; num2 += num7; int num37 = num3 + num8; num4 += num9; num5 += num10; num11 = num2 * 2; num12 = num37 * 2; num13 = num4 * 2; num14 = num5 * 2; long num38 = (long)num * (long)num; long num39 = (long)num * (long)num11; long num40 = (long)num * (long)num12 + (long)num2 * (long)num2; long num41 = (long)num11 * (long)num12 + (long)num * (long)num13; long num42 = (long)num37 * (long)num12 + (long)num * (long)num14 + (long)num2 * (long)num13; long num43 = (long)num11 * (long)num14 + (long)num12 * (long)num13; long num44 = (long)num12 * (long)num14 + (long)num4 * (long)num4; long num45 = (long)num4 * (long)num14; long num46 = (long)num5 * (long)num14; long num47 = num23 + (num41 - num18); int num48 = (int)num47 & 67108863; num47 >>= 26; num47 += num42 - num19 - num32; int num49 = (int)num47 & 33554431; num47 >>= 25; num47 = num15 + (num47 + num43 - num20) * 38; z[0] = ((int)num47 & 67108863); num47 >>= 26; num47 += num16 + (num44 - num21) * 38; z[1] = ((int)num47 & 67108863); num47 >>= 26; num47 += num17 + (num45 - num22) * 38; z[2] = ((int)num47 & 33554431); num47 >>= 25; num47 += num18 + (num46 - num23) * 38; z[3] = ((int)num47 & 67108863); num47 >>= 26; num47 += num19 + num32 * 38; z[4] = ((int)num47 & 33554431); num47 >>= 25; num47 += num20 + (num38 - num15); z[5] = ((int)num47 & 67108863); num47 >>= 26; num47 += num21 + (num39 - num16); z[6] = ((int)num47 & 67108863); num47 >>= 26; num47 += num22 + (num40 - num17); z[7] = ((int)num47 & 33554431); num47 >>= 25; num47 += num48; z[8] = ((int)num47 & 67108863); num47 >>= 26; z[9] = num49 + (int)num47; } public static void Sqr(int[] x, int n, int[] z) { Sqr(x, z); while (--n > 0) { Sqr(z, z); } } public static bool SqrtRatioVar(int[] u, int[] v, int[] z) { int[] array = Create(); int[] array2 = Create(); Mul(u, v, array); Sqr(v, array2); Mul(array, array2, array); Sqr(array2, array2); Mul(array2, array, array2); int[] array3 = Create(); int[] array4 = Create(); PowPm5d8(array2, array3, array4); Mul(array4, array, array4); int[] array5 = Create(); Sqr(array4, array5); Mul(array5, v, array5); Sub(array5, u, array3); Normalize(array3); if (IsZeroVar(array3)) { Copy(array4, 0, z, 0); return true; } Add(array5, u, array3); Normalize(array3); if (IsZeroVar(array3)) { Mul(array4, RootNegOne, z); return true; } return false; } public static void Sub(int[] x, int[] y, int[] z) { for (int i = 0; i < 10; i++) { z[i] = x[i] - y[i]; } } public static void SubOne(int[] z) { z[0]--; } public static void Zero(int[] z) { for (int i = 0; i < 10; i++) { z[i] = 0; } } } }