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

X448

public static class X448
using Org.BouncyCastle.Math.EC.Rfc8032; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Math.EC.Rfc7748 { public static class X448 { public const int PointSize = 56; public const int ScalarSize = 56; private const uint C_A = 156326; private const uint C_A24 = 39082; public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) { ScalarMult(k, kOff, u, uOff, r, rOff); return !Arrays.AreAllZeroes(r, rOff, 56); } public static void ClampPrivateKey(byte[] k) { if (k.Length != 56) throw new ArgumentException("k"); k[0] &= 252; k[55] |= 128; } private static uint Decode32(byte[] bs, int off) { return (uint)(bs[off] | (bs[++off] << 8) | (bs[++off] << 16) | (bs[++off] << 24)); } private static void DecodeScalar(byte[] k, int kOff, uint[] n) { for (int i = 0; i < 14; i++) { n[i] = Decode32(k, kOff + i * 4); } n[0] &= 4294967292; n[13] |= 2147483648; } public static void GeneratePrivateKey(SecureRandom random, byte[] k) { if (k.Length != 56) throw new ArgumentException("k"); random.NextBytes(k); ClampPrivateKey(k); } public static void GeneratePublicKey(byte[] k, int kOff, byte[] r, int rOff) { ScalarMultBase(k, kOff, r, rOff); } private static void PointDouble(uint[] x, uint[] z) { uint[] array = X448Field.Create(); uint[] array2 = X448Field.Create(); X448Field.Add(x, z, array); X448Field.Sub(x, z, array2); X448Field.Sqr(array, array); X448Field.Sqr(array2, array2); X448Field.Mul(array, array2, x); X448Field.Sub(array, array2, array); X448Field.Mul(array, 39082, z); X448Field.Add(z, array2, z); X448Field.Mul(z, array, z); } public static void Precompute() { Ed448.Precompute(); } public static void ScalarMult(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) { uint[] array = new uint[14]; DecodeScalar(k, kOff, array); uint[] array2 = X448Field.Create(); X448Field.Decode(u, uOff, array2); uint[] array3 = X448Field.Create(); X448Field.Copy(array2, 0, array3, 0); uint[] array4 = X448Field.Create(); array4[0] = 1; uint[] array5 = X448Field.Create(); array5[0] = 1; uint[] array6 = X448Field.Create(); uint[] array7 = X448Field.Create(); uint[] array8 = X448Field.Create(); int num = 447; int num2 = 1; do { X448Field.Add(array5, array6, array7); X448Field.Sub(array5, array6, array5); X448Field.Add(array3, array4, array6); X448Field.Sub(array3, array4, array3); X448Field.Mul(array7, array3, array7); X448Field.Mul(array5, array6, array5); X448Field.Sqr(array6, array6); X448Field.Sqr(array3, array3); X448Field.Sub(array6, array3, array8); X448Field.Mul(array8, 39082, array4); X448Field.Add(array4, array3, array4); X448Field.Mul(array4, array8, array4); X448Field.Mul(array3, array6, array3); X448Field.Sub(array7, array5, array6); X448Field.Add(array7, array5, array5); X448Field.Sqr(array5, array5); X448Field.Sqr(array6, array6); X448Field.Mul(array6, array2, array6); num--; int num3 = num >> 5; int num4 = num & 31; int num5 = (int)((array[num3] >> num4) & 1); num2 ^= num5; X448Field.CSwap(num2, array3, array5); X448Field.CSwap(num2, array4, array6); num2 = num5; } while (num >= 2); for (int i = 0; i < 2; i++) { PointDouble(array3, array4); } X448Field.Inv(array4, array4); X448Field.Mul(array3, array4, array3); X448Field.Normalize(array3); X448Field.Encode(array3, r, rOff); } public static void ScalarMultBase(byte[] k, int kOff, byte[] r, int rOff) { uint[] array = X448Field.Create(); uint[] y = X448Field.Create(); Ed448.ScalarMultBaseXY(k, kOff, array, y); X448Field.Inv(array, array); X448Field.Mul(array, y, array); X448Field.Sqr(array, array); X448Field.Normalize(array); X448Field.Encode(array, r, rOff); } } }