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