diff options
Diffstat (limited to 'crypto/src/math/ec/Mod.cs')
-rw-r--r-- | crypto/src/math/ec/Mod.cs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/crypto/src/math/ec/Mod.cs b/crypto/src/math/ec/Mod.cs new file mode 100644 index 000000000..57f75ed12 --- /dev/null +++ b/crypto/src/math/ec/Mod.cs @@ -0,0 +1,115 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC +{ + internal abstract class Mod + { + public static void Invert(uint[] p, uint[] x, uint[] z) + { + int len = p.Length; + if (Nat.IsOne(len, x)) + { + Array.Copy(x, 0, z, 0, len); + return; + } + + uint[] u = Nat.Copy(len, x); + uint[] a = Nat.Create(len); + a[0] = 1; + + if ((u[0] & 1) == 0) + { + InversionStep(p, u, a); + } + if (Nat.IsOne(len, u)) + { + Array.Copy(a, 0, z, 0, len); + return; + } + + uint[] v = Nat.Copy(len, p); + uint[] b = Nat.Create(len); + + for (;;) + { + if (Nat.Gte(len, u, v)) + { + Subtract(p, a, b, a); + Nat.Sub(len, u, v, u); + if ((u[0] & 1) == 0) + { + InversionStep(p, u, a); + } + if (Nat.IsOne(len, u)) + { + Array.Copy(a, 0, z, 0, len); + return; + } + } + else + { + Subtract(p, b, a, b); + Nat.Sub(len, v, u, v); + if ((v[0] & 1) == 0) + { + InversionStep(p, v, b); + } + if (Nat.IsOne(len, v)) + { + Array.Copy(b, 0, z, 0, len); + return; + } + } + } + } + + public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z) + { + int len = p.Length; + int c = Nat.Sub(len, x, y, z); + if (c != 0) + { + Nat.Add(len, z, p, z); + } + } + + private static void InversionStep(uint[] p, uint[] u, uint[] x) + { + int len = p.Length; + int count = 0; + while (u[0] == 0) + { + Nat.ShiftDownWord(u, len, 0); + count += 32; + } + + int zeroes = GetTrailingZeroes(u[0]); + if (zeroes > 0) + { + Nat.ShiftDownBits(u, len, zeroes, 0); + count += zeroes; + } + + for (int i = 0; i < count; ++i) + { + uint c = (x[0] & 1) == 0 ? 0 : Nat.Add(len, x, p, x); + Nat.ShiftDownBit(x, len, c); + } + } + + private static int GetTrailingZeroes(uint x) + { + // assert x != 0; + + int count = 0; + while ((x & 1) == 0) + { + x >>= 1; + ++count; + } + return count; + } + } +} |