summary refs log tree commit diff
path: root/crypto/src/math/ec/Mod.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-01-23 13:17:21 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-01-23 13:17:21 +0700
commit1eae3093554e12822f1c53b174af894af28bbfaa (patch)
tree7b91f11bb15892c0498ec81703a473154bc3d4e9 /crypto/src/math/ec/Mod.cs
parentAvoid unnecessary multiplication in final ExtEuclid iteration (diff)
downloadBouncyCastle.NET-ed25519-1eae3093554e12822f1c53b174af894af28bbfaa.tar.xz
Add Nat/Mod classes and use instead of (slow) BigInteger.ModInverse implementation for FpFieldElement
Diffstat (limited to 'crypto/src/math/ec/Mod.cs')
-rw-r--r--crypto/src/math/ec/Mod.cs115
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;
+        }
+    }
+}