summary refs log tree commit diff
path: root/crypto/src/util/BigIntegers.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/util/BigIntegers.cs')
-rw-r--r--crypto/src/util/BigIntegers.cs74
1 files changed, 70 insertions, 4 deletions
diff --git a/crypto/src/util/BigIntegers.cs b/crypto/src/util/BigIntegers.cs
index 9c5477e6a..419e98701 100644
--- a/crypto/src/util/BigIntegers.cs
+++ b/crypto/src/util/BigIntegers.cs
@@ -187,10 +187,10 @@ namespace Org.BouncyCastle.Utilities
         public static BigInteger ModOddInverse(BigInteger M, BigInteger X)
         {
             if (!M.TestBit(0))
-                throw new ArgumentException("must be odd", "M");
+                throw new ArgumentException("must be odd", nameof(M));
             if (M.SignValue != 1)
                 throw new ArithmeticException("BigInteger: modulus not positive");
-            if (X.SignValue < 0 || X.CompareTo(M) >= 0)
+            if (X.SignValue < 0 || X.BitLength > M.BitLength)
             {
                 X = X.Mod(M);
             }
@@ -226,12 +226,12 @@ namespace Org.BouncyCastle.Utilities
         public static BigInteger ModOddInverseVar(BigInteger M, BigInteger X)
         {
             if (!M.TestBit(0))
-                throw new ArgumentException("must be odd", "M");
+                throw new ArgumentException("must be odd", nameof(M));
             if (M.SignValue != 1)
                 throw new ArithmeticException("BigInteger: modulus not positive");
             if (M.Equals(One))
                 return Zero;
-            if (X.SignValue < 0 || X.CompareTo(M) >= 0)
+            if (X.SignValue < 0 || X.BitLength > M.BitLength)
             {
                 X = X.Mod(M);
             }
@@ -265,5 +265,71 @@ namespace Org.BouncyCastle.Utilities
                 return Nat.ToBigInteger(len, z);
             }
         }
+
+        public static bool ModOddIsCoprime(BigInteger M, BigInteger X)
+        {
+            if (!M.TestBit(0))
+                throw new ArgumentException("must be odd", nameof(M));
+            if (M.SignValue != 1)
+                throw new ArithmeticException("BigInteger: modulus not positive");
+            if (X.SignValue < 0 || X.BitLength > M.BitLength)
+            {
+                X = X.Mod(M);
+            }
+
+            int bits = M.BitLength;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            if (bits <= 2048)
+            {
+                int len = Nat.GetLengthForBits(bits);
+                Span<uint> m = stackalloc uint[len];
+                Span<uint> x = stackalloc uint[len];
+                Nat.FromBigInteger(bits, M, m);
+                Nat.FromBigInteger(bits, X, x);
+                return 0 != Mod.ModOddIsCoprime(m, x);
+            }
+            else
+#endif
+            {
+                uint[] m = Nat.FromBigInteger(bits, M);
+                uint[] x = Nat.FromBigInteger(bits, X);
+                return 0 != Mod.ModOddIsCoprime(m, x);
+            }
+        }
+
+        public static bool ModOddIsCoprimeVar(BigInteger M, BigInteger X)
+        {
+            if (!M.TestBit(0))
+                throw new ArgumentException("must be odd", nameof(M));
+            if (M.SignValue != 1)
+                throw new ArithmeticException("BigInteger: modulus not positive");
+            if (X.SignValue < 0 || X.BitLength > M.BitLength)
+            {
+                X = X.Mod(M);
+            }
+            if (X.Equals(One))
+                return true;
+
+            int bits = M.BitLength;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            if (bits <= 2048)
+            {
+                int len = Nat.GetLengthForBits(bits);
+                Span<uint> m = stackalloc uint[len];
+                Span<uint> x = stackalloc uint[len];
+                Nat.FromBigInteger(bits, M, m);
+                Nat.FromBigInteger(bits, X, x);
+                return Mod.ModOddIsCoprimeVar(m, x);
+            }
+            else
+#endif
+            {
+                uint[] m = Nat.FromBigInteger(bits, M);
+                uint[] x = Nat.FromBigInteger(bits, X);
+                return Mod.ModOddIsCoprimeVar(m, x);
+            }
+        }
     }
 }