Mod
using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities;
using Renci.SshNet.Security.Org.BouncyCastle.Security;
using System;
namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Raw
{
internal abstract class Mod
{
private static readonly SecureRandom RandomSource = new SecureRandom();
public static void Invert(uint[] p, uint[] x, uint[] z)
{
int num = p.Length;
if (Nat.IsZero(num, x))
throw new ArgumentException("cannot be 0", "x");
if (Nat.IsOne(num, x))
Array.Copy(x, 0, z, 0, num);
else {
uint[] array = Nat.Copy(num, x);
uint[] array2 = Nat.Create(num);
array2[0] = 1;
int xc = 0;
if ((array[0] & 1) == 0)
InversionStep(p, array, num, array2, ref xc);
if (Nat.IsOne(num, array))
InversionResult(p, xc, array2, z);
else {
uint[] array3 = Nat.Copy(num, p);
uint[] array4 = Nat.Create(num);
int xc2 = 0;
int num2 = num;
while (true) {
if (array[num2 - 1] == 0 && array3[num2 - 1] == 0)
num2--;
else if (Nat.Gte(num, array, array3)) {
Nat.SubFrom(num, array3, array);
xc += Nat.SubFrom(num, array4, array2) - xc2;
InversionStep(p, array, num2, array2, ref xc);
if (Nat.IsOne(num, array)) {
InversionResult(p, xc, array2, z);
return;
}
} else {
Nat.SubFrom(num, array, array3);
xc2 += Nat.SubFrom(num, array2, array4) - xc;
InversionStep(p, array3, num2, array4, ref xc2);
if (Nat.IsOne(num, array3))
break;
}
}
InversionResult(p, xc2, array4, z);
}
}
}
public static uint[] Random(uint[] p)
{
int num = p.Length;
uint[] array = Nat.Create(num);
uint num2 = p[num - 1];
num2 |= num2 >> 1;
num2 |= num2 >> 2;
num2 |= num2 >> 4;
num2 |= num2 >> 8;
num2 |= num2 >> 16;
do {
byte[] array2 = new byte[num << 2];
RandomSource.NextBytes(array2);
Pack.BE_To_UInt32(array2, 0, array);
array[num - 1] &= num2;
} while (Nat.Gte(num, array, p));
return array;
}
public static void Add(uint[] p, uint[] x, uint[] y, uint[] z)
{
int len = p.Length;
if (Nat.Add(len, x, y, z) != 0)
Nat.SubFrom(len, p, z);
}
public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z)
{
int len = p.Length;
if (Nat.Sub(len, x, y, z) != 0)
Nat.AddTo(len, p, z);
}
private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z)
{
if (ac < 0)
Nat.Add(p.Length, a, p, z);
else
Array.Copy(a, 0, z, 0, p.Length);
}
private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc)
{
int len = p.Length;
int num = 0;
while (u[0] == 0) {
Nat.ShiftDownWord(uLen, u, 0);
num += 32;
}
int trailingZeroes = GetTrailingZeroes(u[0]);
if (trailingZeroes > 0) {
Nat.ShiftDownBits(uLen, u, trailingZeroes, 0);
num += trailingZeroes;
}
for (int i = 0; i < num; i++) {
if ((x[0] & 1) != 0) {
if (xc < 0)
xc += (int)Nat.AddTo(len, p, x);
else
xc += Nat.SubFrom(len, p, x);
}
Nat.ShiftDownBit(len, x, (uint)xc);
}
}
private static int GetTrailingZeroes(uint x)
{
int num = 0;
while ((x & 1) == 0) {
x >>= 1;
num++;
}
return num;
}
}
}