diff options
Diffstat (limited to 'crypto/src/util/BigIntegers.cs')
-rw-r--r-- | crypto/src/util/BigIntegers.cs | 74 |
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); + } + } } } |