summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-10-07 20:41:47 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2008-10-07 20:41:47 -0700
commit5a69457a10dca1ef5b43134865b3e28f20ec621c (patch)
treed99804060986844f63d023068ec3404aaef09a86
parentc85166c7212b4f13b95d22dfd049f677ddbbe745 (diff)
downloadDotNetOpenAuth-5a69457a10dca1ef5b43134865b3e28f20ec621c.zip
DotNetOpenAuth-5a69457a10dca1ef5b43134865b3e28f20ec621c.tar.gz
DotNetOpenAuth-5a69457a10dca1ef5b43134865b3e28f20ec621c.tar.bz2
Revert "Integrated latest Mono source code."v2.5.0.8281
This reverts commit fc06d4dcaef9da92362d19986d4e0e747ecee917. The integration of mono source code caused the Diffie-Hellman tests to take 9X longer than normal. Huge perf regression like this is unacceptable. Conflicts: src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs
-rw-r--r--src/DotNetOpenId/DiffieHellman/DiffieHellmanManaged.cs22
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs1570
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/ConfidenceFactor.cs105
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/NextPrimeFinder.cs78
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/PrimalityTests.cs384
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/PrimeGeneratorBase.cs63
-rw-r--r--src/DotNetOpenId/DiffieHellman/mono/SequentialSearchPrimeGeneratorBase.cs101
7 files changed, 923 insertions, 1400 deletions
diff --git a/src/DotNetOpenId/DiffieHellman/DiffieHellmanManaged.cs b/src/DotNetOpenId/DiffieHellman/DiffieHellmanManaged.cs
index a831b08..3a46d56 100644
--- a/src/DotNetOpenId/DiffieHellman/DiffieHellmanManaged.cs
+++ b/src/DotNetOpenId/DiffieHellman/DiffieHellmanManaged.cs
@@ -74,18 +74,18 @@ namespace Org.Mentalis.Security.Cryptography {
// initializes the private variables (throws CryptographicException)
private void Initialize(BigInteger p, BigInteger g, BigInteger x, int secretLen, bool checkInput) {
- if (!p.IsProbablePrime() || g <= 0 || g >= p || (x != null && (x <= 0 || x > p - 2)))
+ if (!p.isProbablePrime() || g <= 0 || g >= p || (x != null && (x <= 0 || x > p - 2)))
throw new CryptographicException();
// default is to generate a number as large as the prime this
// is usually overkill, but it's the most secure thing we can
// do if the user doesn't specify a desired secret length ...
if (secretLen == 0)
- secretLen = p.BitCount();
+ secretLen = p.bitCount();
m_P = p;
m_G = g;
if (x == null) {
BigInteger pm1 = m_P - 1;
- for(m_X = BigInteger.GenerateRandom(secretLen); m_X >= pm1 || m_X == 0; m_X = BigInteger.GenerateRandom(secretLen)) {}
+ for(m_X = BigInteger.genRandom(secretLen); m_X >= pm1 || m_X == 0; m_X = BigInteger.genRandom(secretLen)) {}
} else {
m_X = x;
}
@@ -95,8 +95,8 @@ namespace Org.Mentalis.Security.Cryptography {
/// </summary>
/// <returns>The key exchange data to be sent to the intended recipient.</returns>
public override byte[] CreateKeyExchange() {
- BigInteger y = m_G.ModPow(m_X, m_P);
- byte[] ret = y.GetBytes();
+ BigInteger y = m_G.modPow(m_X, m_P);
+ byte[] ret = y.getBytes();
y.Clear();
return ret;
}
@@ -107,8 +107,8 @@ namespace Org.Mentalis.Security.Cryptography {
/// <returns>The shared key derived from the key exchange data.</returns>
public override byte[] DecryptKeyExchange(byte[] keyEx) {
BigInteger pvr = new BigInteger(keyEx);
- BigInteger z = pvr.ModPow(m_X, m_P);
- byte[] ret = z.GetBytes();
+ BigInteger z = pvr.modPow(m_X, m_P);
+ byte[] ret = z.getBytes();
z.Clear();
return ret;
}
@@ -149,10 +149,10 @@ namespace Org.Mentalis.Security.Cryptography {
/// <returns>The parameters for <see cref="DiffieHellman"/>.</returns>
public override DHParameters ExportParameters(bool includePrivateParameters) {
DHParameters ret = new DHParameters();
- ret.P = m_P.GetBytes();
- ret.G = m_G.GetBytes();
+ ret.P = m_P.getBytes();
+ ret.G = m_G.getBytes();
if (includePrivateParameters) {
- ret.X = m_X.GetBytes();
+ ret.X = m_X.getBytes();
}
return ret;
}
@@ -201,7 +201,7 @@ namespace Org.Mentalis.Security.Cryptography {
// 4. If g = 1 go to step 2
// BigInteger j = (p - 1) / q;
} else { // random
- p = BigInteger.GeneratePseudoPrime(bitlen);
+ p = BigInteger.genPseudoPrime(bitlen);
g = new BigInteger(3); // always use 3 as a generator
}
}
diff --git a/src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs b/src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs
index e3ae9d1..ece2cc7 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/BigInteger.cs
@@ -4,8 +4,7 @@
// Authors:
// Ben Maurer
// Chew Keong TAN
-// Sebastien Pouliot <sebastien@ximian.com>
-// Pieter Philippaerts <Pieter@mentalis.org>
+// Sebastien Pouliot (spouliot@motus.com)
//
// Copyright (c) 2003 Ben Maurer
// All rights reserved
@@ -15,41 +14,15 @@
//
// Modified 2007 Andrew Arnott (http://blog.nerdbank.net)
// Rewrote unsafe code as safe code.
-//
-// Modified 2008 Troels Thomsen (http://www.codesensus.com/)
-// Integrated modifications by Andrew Arnott with latest Mono release.
-//
-// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
using System;
using System.Security.Cryptography;
using Mono.Math.Prime.Generator;
using Mono.Math.Prime;
-namespace Mono.Math
-{
- internal class BigInteger
- {
+namespace Mono.Math {
+
+ internal class BigInteger {
#region Data Storage
@@ -61,7 +34,7 @@ namespace Mono.Math
/// <summary>
/// The data for this BigInteger
/// </summary>
- uint[] data;
+ uint [] data;
#endregion
@@ -86,7 +59,7 @@ namespace Mono.Math
/// </code>
/// </para>
/// </remarks>
- internal static readonly uint[] smallPrimes = {
+ public static readonly uint [] smallPrimes = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
@@ -155,8 +128,7 @@ namespace Mono.Math
5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
};
- public enum Sign : int
- {
+ public enum Sign : int {
Negative = -1,
Zero = 0,
Positive = 1
@@ -170,344 +142,256 @@ namespace Mono.Math
#region Constructors
- public BigInteger()
+ public BigInteger ()
{
- data = new uint[DEFAULT_LEN];
- this.length = DEFAULT_LEN;
+ data = new uint [DEFAULT_LEN];
}
-
- public BigInteger(Sign sign, uint len)
+ public BigInteger (Sign sign, uint len)
{
- this.data = new uint[len];
+ this.data = new uint [len];
this.length = len;
}
- public BigInteger(BigInteger bi)
+ public BigInteger (BigInteger bi)
{
- this.data = (uint[])bi.data.Clone();
+ this.data = (uint [])bi.data.Clone ();
this.length = bi.length;
}
- public BigInteger(BigInteger bi, uint len)
+ public BigInteger (BigInteger bi, uint len)
{
- this.data = new uint[len];
+ this.data = new uint [len];
for (uint i = 0; i < bi.length; i++)
- this.data[i] = bi.data[i];
+ this.data [i] = bi.data [i];
this.length = bi.length;
}
#endregion
+ public static BigInteger Parse(string number) {
+ if (number == null)
+ throw new ArgumentNullException(number);
+ int i = 0, len = number.Length;
+ char c;
+ bool digits_seen = false;
+ BigInteger val = new BigInteger(0);
+ if (number[i] == '+') {
+ i++;
+ } else if(number[i] == '-') {
+ throw new FormatException("Only positive integers are allowed.");
+ }
+ for(; i < len; i++) {
+ c = number[i];
+ if (c == '\0') {
+ i = len;
+ continue;
+ }
+ if (c >= '0' && c <= '9'){
+ val = val * 10 + (c - '0');
+ digits_seen = true;
+ } else {
+ if (Char.IsWhiteSpace(c)){
+ for (i++; i < len; i++){
+ if (!Char.IsWhiteSpace (number[i]))
+ throw new FormatException();
+ }
+ break;
+ } else
+ throw new FormatException();
+ }
+ }
+ if (!digits_seen)
+ throw new FormatException();
+ return val;
+ }
+
#region Conversions
-
- public BigInteger(byte[] inData)
+
+ public BigInteger (byte [] inData)
{
length = (uint)inData.Length >> 2;
int leftOver = inData.Length & 0x3;
// length not multiples of 4
- if (leftOver != 0)
- length++;
+ if (leftOver != 0) length++;
- data = new uint[length];
+ data = new uint [length];
- for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++)
- {
- data[j] = (uint)(
- (inData[i - 3] << (3 * 8)) |
- (inData[i - 2] << (2 * 8)) |
- (inData[i - 1] << (1 * 8)) |
- (inData[i])
+ for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++) {
+ data [j] = (uint)(
+ (inData [i-3] << (3*8)) |
+ (inData [i-2] << (2*8)) |
+ (inData [i-1] << (1*8)) |
+ (inData [i-0] << (0*8))
);
}
- switch (leftOver)
- {
- case 1:
- data[length - 1] = (uint)inData[0];
- break;
- case 2:
- data[length - 1] = (uint)((inData[0] << 8) | inData[1]);
- break;
- case 3:
- data[length - 1] = (uint)((inData[0] << 16) | (inData[1] << 8) | inData[2]);
- break;
+ switch (leftOver) {
+ case 1: data [length-1] = (uint)inData [0]; break;
+ case 2: data [length-1] = (uint)((inData [0] << 8) | inData [1]); break;
+ case 3: data [length-1] = (uint)((inData [0] << 16) | (inData [1] << 8) | inData [2]); break;
}
- this.Normalize();
+ this.Normalize ();
}
- public BigInteger(uint[] inData)
+ public BigInteger (uint [] inData)
{
length = (uint)inData.Length;
- data = new uint[length];
+ data = new uint [length];
for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
- data[j] = inData[i];
+ data [j] = inData [i];
- this.Normalize();
+ this.Normalize ();
}
- public BigInteger(uint ui)
+ public BigInteger (uint ui)
{
- data = new uint[] { ui };
+ data = new uint [] {ui};
}
- public BigInteger(ulong ul)
+ public BigInteger (ulong ul)
{
- data = new uint[2] { (uint)ul, (uint)(ul >> 32) };
+ data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
length = 2;
- this.Normalize();
+ this.Normalize ();
}
- public static implicit operator BigInteger(uint value)
+ public static implicit operator BigInteger (uint value)
{
- return (new BigInteger(value));
+ return (new BigInteger (value));
}
- public static implicit operator BigInteger(int value)
+ public static implicit operator BigInteger (int value)
{
- if (value < 0)
- throw new ArgumentOutOfRangeException("value");
- return (new BigInteger((uint)value));
+ if (value < 0) throw new ArgumentOutOfRangeException ("value");
+ return (new BigInteger ((uint)value));
}
- public static implicit operator BigInteger(ulong value)
+ public static implicit operator BigInteger (ulong value)
{
- return (new BigInteger(value));
- }
-
- /* This is the BigInteger.Parse method I use. This method works
- because BigInteger.ToString returns the input I gave to Parse. */
- public static BigInteger Parse(string number)
- {
- if (number == null)
- throw new ArgumentNullException("number");
-
- int i = 0, len = number.Length;
- char c;
- bool digits_seen = false;
- BigInteger val = new BigInteger(0);
- if (number[i] == '+')
- {
- i++;
- }
- else if (number[i] == '-')
- {
- throw new FormatException(WouldReturnNegVal);
- }
-
- for (; i < len; i++)
- {
- c = number[i];
- if (c == '\0')
- {
- i = len;
- continue;
- }
- if (c >= '0' && c <= '9')
- {
- val = val * 10 + (c - '0');
- digits_seen = true;
- }
- else
- {
- if (Char.IsWhiteSpace(c))
- {
- for (i++; i < len; i++)
- {
- if (!Char.IsWhiteSpace(number[i]))
- throw new FormatException();
- }
- break;
- }
- else
- throw new FormatException();
- }
- }
- if (!digits_seen)
- throw new FormatException();
- return val;
+ return (new BigInteger (value));
}
#endregion
#region Operators
- public static BigInteger operator +(BigInteger bi1, BigInteger bi2)
+ public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
{
if (bi1 == 0)
- return new BigInteger(bi2);
+ return new BigInteger (bi2);
else if (bi2 == 0)
- return new BigInteger(bi1);
+ return new BigInteger (bi1);
else
- return Kernel.AddSameSign(bi1, bi2);
+ return Kernel.AddSameSign (bi1, bi2);
}
- public static BigInteger operator -(BigInteger bi1, BigInteger bi2)
+ public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
{
if (bi2 == 0)
- return new BigInteger(bi1);
+ return new BigInteger (bi1);
if (bi1 == 0)
- throw new ArithmeticException(WouldReturnNegVal);
+ throw new ArithmeticException (WouldReturnNegVal);
- switch (Kernel.Compare(bi1, bi2))
- {
+ switch (Kernel.Compare (bi1, bi2)) {
case Sign.Zero:
return 0;
case Sign.Positive:
- return Kernel.Subtract(bi1, bi2);
+ return Kernel.Subtract (bi1, bi2);
case Sign.Negative:
- throw new ArithmeticException(WouldReturnNegVal);
+ throw new ArithmeticException (WouldReturnNegVal);
default:
- throw new InvalidOperationException();
+ throw new InvalidOperationException ();
}
}
- public static int operator %(BigInteger bi, int i)
+ public static int operator % (BigInteger bi, int i)
{
if (i > 0)
- return (int)Kernel.DwordMod(bi, (uint)i);
+ return (int)Kernel.DwordMod (bi, (uint)i);
else
- return -(int)Kernel.DwordMod(bi, (uint)-i);
+ return -(int)Kernel.DwordMod (bi, (uint)-i);
}
- public static uint operator %(BigInteger bi, uint ui)
+ public static uint operator % (BigInteger bi, uint ui)
{
- return Kernel.DwordMod(bi, (uint)ui);
+ return Kernel.DwordMod (bi, (uint)ui);
}
- public static BigInteger operator %(BigInteger bi1, BigInteger bi2)
+ public static BigInteger operator % (BigInteger bi1, BigInteger bi2)
{
- return Kernel.multiByteDivide(bi1, bi2)[1];
+ return Kernel.multiByteDivide (bi1, bi2)[1];
}
- public static BigInteger operator /(BigInteger bi, int i)
+ public static BigInteger operator / (BigInteger bi, int i)
{
if (i > 0)
- return Kernel.DwordDiv(bi, (uint)i);
+ return Kernel.DwordDiv (bi, (uint)i);
- throw new ArithmeticException(WouldReturnNegVal);
+ throw new ArithmeticException (WouldReturnNegVal);
}
- public static BigInteger operator /(BigInteger bi1, BigInteger bi2)
+ public static BigInteger operator / (BigInteger bi1, BigInteger bi2)
{
- return Kernel.multiByteDivide(bi1, bi2)[0];
+ return Kernel.multiByteDivide (bi1, bi2)[0];
}
- public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
+ public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
{
- if (bi1 == 0 || bi2 == 0)
- return 0;
+ if (bi1 == 0 || bi2 == 0) return 0;
//
// Validate pointers
//
- if (bi1.data.Length < bi1.length)
- throw new IndexOutOfRangeException("bi1 out of range");
- if (bi2.data.Length < bi2.length)
- throw new IndexOutOfRangeException("bi2 out of range");
+ if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
+ if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");
- BigInteger ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);
+ BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);
- Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
+ Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
- ret.Normalize();
+ ret.Normalize ();
return ret;
}
- public static BigInteger operator *(BigInteger bi, int i)
+ public static BigInteger operator * (BigInteger bi, int i)
{
- if (i < 0)
- throw new ArithmeticException(WouldReturnNegVal);
- if (i == 0)
- return 0;
- if (i == 1)
- return new BigInteger(bi);
+ if (i < 0) throw new ArithmeticException (WouldReturnNegVal);
+ if (i == 0) return 0;
+ if (i == 1) return new BigInteger (bi);
- return Kernel.MultiplyByDword(bi, (uint)i);
+ return Kernel.MultiplyByDword (bi, (uint)i);
}
- public static BigInteger operator <<(BigInteger bi1, int shiftVal)
+ public static BigInteger operator << (BigInteger bi1, int shiftVal)
{
- return Kernel.LeftShift(bi1, shiftVal);
+ return Kernel.LeftShift (bi1, shiftVal);
}
- public static BigInteger operator >>(BigInteger bi1, int shiftVal)
+ public static BigInteger operator >> (BigInteger bi1, int shiftVal)
{
- return Kernel.RightShift(bi1, shiftVal);
- }
-
- #endregion
-
- #region Friendly names for operators
-
- // with names suggested by FxCop 1.30
-
- public static BigInteger Add(BigInteger bi1, BigInteger bi2)
- {
- return (bi1 + bi2);
- }
-
- public static BigInteger Subtract(BigInteger bi1, BigInteger bi2)
- {
- return (bi1 - bi2);
- }
-
- public static int Modulus(BigInteger bi, int i)
- {
- return (bi % i);
- }
-
- public static uint Modulus(BigInteger bi, uint ui)
- {
- return (bi % ui);
- }
-
- public static BigInteger Modulus(BigInteger bi1, BigInteger bi2)
- {
- return (bi1 % bi2);
- }
-
- public static BigInteger Divid(BigInteger bi, int i)
- {
- return (bi / i);
- }
-
- public static BigInteger Divid(BigInteger bi1, BigInteger bi2)
- {
- return (bi1 / bi2);
- }
-
- public static BigInteger Multiply(BigInteger bi1, BigInteger bi2)
- {
- return (bi1 * bi2);
- }
-
- public static BigInteger Multiply(BigInteger bi, int i)
- {
- return (bi * i);
+ return Kernel.RightShift (bi1, shiftVal);
}
#endregion
#region Random
private static RandomNumberGenerator rng;
- private static RandomNumberGenerator Rng
- {
- get
- {
+ private static RandomNumberGenerator Rng {
+ get {
if (rng == null)
- rng = RandomNumberGenerator.Create();
+ rng = RandomNumberGenerator.Create ();
return rng;
}
}
@@ -518,7 +402,7 @@ namespace Mono.Math
/// <param name="bits">The number of bits for the new number.</param>
/// <param name="rng">A random number generator to use to obtain the bits.</param>
/// <returns>A random number of the specified length.</returns>
- public static BigInteger GenerateRandom(int bits, RandomNumberGenerator rng)
+ public static BigInteger genRandom (int bits, RandomNumberGenerator rng)
{
int dwords = bits >> 5;
int remBits = bits & 0x1F;
@@ -526,24 +410,23 @@ namespace Mono.Math
if (remBits != 0)
dwords++;
- BigInteger ret = new BigInteger(Sign.Positive, (uint)dwords + 1);
- byte[] random = new byte[dwords << 2];
+ BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
+ byte [] random = new byte [dwords << 2];
- rng.GetBytes(random);
- Buffer.BlockCopy(random, 0, ret.data, 0, (int)dwords << 2);
+ rng.GetBytes (random);
+ Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);
- if (remBits != 0)
- {
- uint mask = (uint)(0x01 << (remBits - 1));
- ret.data[dwords - 1] |= mask;
+ if (remBits != 0) {
+ uint mask = (uint)(0x01 << (remBits-1));
+ ret.data [dwords-1] |= mask;
mask = (uint)(0xFFFFFFFF >> (32 - remBits));
- ret.data[dwords - 1] &= mask;
+ ret.data [dwords-1] &= mask;
}
else
- ret.data[dwords - 1] |= 0x80000000;
+ ret.data [dwords-1] |= 0x80000000;
- ret.Normalize();
+ ret.Normalize ();
return ret;
}
@@ -552,69 +435,64 @@ namespace Mono.Math
/// </summary>
/// <param name="bits">The number of bits for the new number.</param>
/// <returns>A random number of the specified length.</returns>
- public static BigInteger GenerateRandom(int bits)
+ public static BigInteger genRandom (int bits)
{
- return GenerateRandom(bits, Rng);
+ return genRandom (bits, Rng);
}
/// <summary>
/// Randomizes the bits in "this" from the specified RNG.
/// </summary>
/// <param name="rng">A RNG.</param>
- public void Randomize(RandomNumberGenerator rng)
+ public void randomize (RandomNumberGenerator rng)
{
- if (this == 0)
- return;
-
- int bits = this.BitCount();
+ int bits = this.bitCount ();
int dwords = bits >> 5;
int remBits = bits & 0x1F;
if (remBits != 0)
dwords++;
- byte[] random = new byte[dwords << 2];
+ byte [] random = new byte [dwords << 2];
- rng.GetBytes(random);
- Buffer.BlockCopy(random, 0, data, 0, (int)dwords << 2);
+ rng.GetBytes (random);
+ Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
- if (remBits != 0)
- {
- uint mask = (uint)(0x01 << (remBits - 1));
- data[dwords - 1] |= mask;
+ if (remBits != 0) {
+ uint mask = (uint)(0x01 << (remBits-1));
+ data [dwords-1] |= mask;
mask = (uint)(0xFFFFFFFF >> (32 - remBits));
- data[dwords - 1] &= mask;
+ data [dwords-1] &= mask;
}
else
- data[dwords - 1] |= 0x80000000;
+ data [dwords-1] |= 0x80000000;
- Normalize();
+ Normalize ();
}
/// <summary>
/// Randomizes the bits in "this" from the default RNG.
/// </summary>
- public void Randomize()
+ public void randomize ()
{
- Randomize(Rng);
+ randomize (Rng);
}
#endregion
#region Bitwise
- public int BitCount()
+ public int bitCount ()
{
- this.Normalize();
+ this.Normalize ();
- uint value = data[length - 1];
+ uint value = data [length - 1];
uint mask = 0x80000000;
uint bits = 32;
- while (bits > 0 && (value & mask) == 0)
- {
+ while (bits > 0 && (value & mask) == 0) {
bits--;
mask >>= 1;
}
@@ -628,84 +506,75 @@ namespace Mono.Math
/// </summary>
/// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
/// <returns>True if bitNum is set to 1, else false.</returns>
- public bool TestBit(uint bitNum)
+ public bool testBit (uint bitNum)
{
uint bytePos = bitNum >> 5; // divide by 32
byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
uint mask = (uint)1 << bitPos;
- return ((this.data[bytePos] & mask) != 0);
+ return ((this.data [bytePos] & mask) != 0);
}
- public bool TestBit(int bitNum)
+ public bool testBit (int bitNum)
{
- if (bitNum < 0)
- throw new ArgumentOutOfRangeException("bitNum");
+ if (bitNum < 0) throw new ArgumentOutOfRangeException ("bitNum");
uint bytePos = (uint)bitNum >> 5; // divide by 32
byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
uint mask = (uint)1 << bitPos;
- return ((this.data[bytePos] | mask) == this.data[bytePos]);
+ return ((this.data [bytePos] | mask) == this.data [bytePos]);
}
- public void SetBit(uint bitNum)
+ public void setBit (uint bitNum)
{
- SetBit(bitNum, true);
+ setBit (bitNum, true);
}
-
- public void ClearBit(uint bitNum)
+ public void clearBit (uint bitNum)
{
- SetBit(bitNum, false);
+ setBit (bitNum, false);
}
- public void SetBit(uint bitNum, bool value)
+ public void setBit (uint bitNum, bool val)
{
uint bytePos = bitNum >> 5; // divide by 32
- if (bytePos < this.length)
- {
+ if (bytePos < this.length) {
uint mask = (uint)1 << (int)(bitNum & 0x1F);
- if (value)
- this.data[bytePos] |= mask;
+ if (val)
+ this.data [bytePos] |= mask;
else
- this.data[bytePos] &= ~mask;
+ this.data [bytePos] &= ~mask;
}
}
- public int LowestSetBit()
+ public int LowestSetBit ()
{
- if (this == 0)
- return -1;
+ if (this == 0) return -1;
int i = 0;
- while (!TestBit(i))
- i++;
+ while (!testBit (i)) i++;
return i;
}
- public byte[] GetBytes()
+ public byte [] getBytes ()
{
- if (this == 0)
- return new byte[1];
+ if (this == 0) return new byte [1];
- int numBits = BitCount();
+ int numBits = bitCount ();
int numBytes = numBits >> 3;
if ((numBits & 0x7) != 0)
numBytes++;
- byte[] result = new byte[numBytes];
+ byte [] result = new byte [numBytes];
int numBytesInWord = numBytes & 0x3;
- if (numBytesInWord == 0)
- numBytesInWord = 4;
+ if (numBytesInWord == 0) numBytesInWord = 4;
int pos = 0;
- for (int i = (int)length - 1; i >= 0; i--)
- {
- uint val = data[i];
- for (int j = numBytesInWord - 1; j >= 0; j--)
- {
- result[pos + j] = (byte)(val & 0xFF);
+ for (int i = (int)length - 1; i >= 0; i--) {
+ uint val = data [i];
+ for (int j = numBytesInWord - 1; j >= 0; j--) {
+ result [pos+j] = (byte)(val & 0xFF);
val >>= 8;
}
pos += numBytesInWord;
@@ -718,94 +587,89 @@ namespace Mono.Math
#region Compare
- public static bool operator ==(BigInteger bi1, uint ui)
+ public static bool operator == (BigInteger bi1, uint ui)
{
- if (bi1.length != 1)
- bi1.Normalize();
- return bi1.length == 1 && bi1.data[0] == ui;
+ if (bi1.length != 1) bi1.Normalize ();
+ return bi1.length == 1 && bi1.data [0] == ui;
}
- public static bool operator !=(BigInteger bi1, uint ui)
+ public static bool operator != (BigInteger bi1, uint ui)
{
- if (bi1.length != 1)
- bi1.Normalize();
- return !(bi1.length == 1 && bi1.data[0] == ui);
+ if (bi1.length != 1) bi1.Normalize ();
+ return !(bi1.length == 1 && bi1.data [0] == ui);
}
- public static bool operator ==(BigInteger bi1, BigInteger bi2)
+ public static bool operator == (BigInteger bi1, BigInteger bi2)
{
// we need to compare with null
if ((bi1 as object) == (bi2 as object))
return true;
if (null == bi1 || null == bi2)
return false;
- return Kernel.Compare(bi1, bi2) == 0;
+ return Kernel.Compare (bi1, bi2) == 0;
}
- public static bool operator !=(BigInteger bi1, BigInteger bi2)
+ public static bool operator != (BigInteger bi1, BigInteger bi2)
{
// we need to compare with null
if ((bi1 as object) == (bi2 as object))
return false;
if (null == bi1 || null == bi2)
return true;
- return Kernel.Compare(bi1, bi2) != 0;
+ return Kernel.Compare (bi1, bi2) != 0;
}
- public static bool operator >(BigInteger bi1, BigInteger bi2)
+ public static bool operator > (BigInteger bi1, BigInteger bi2)
{
- return Kernel.Compare(bi1, bi2) > 0;
+ return Kernel.Compare (bi1, bi2) > 0;
}
- public static bool operator <(BigInteger bi1, BigInteger bi2)
+ public static bool operator < (BigInteger bi1, BigInteger bi2)
{
- return Kernel.Compare(bi1, bi2) < 0;
+ return Kernel.Compare (bi1, bi2) < 0;
}
- public static bool operator >=(BigInteger bi1, BigInteger bi2)
+ public static bool operator >= (BigInteger bi1, BigInteger bi2)
{
- return Kernel.Compare(bi1, bi2) >= 0;
+ return Kernel.Compare (bi1, bi2) >= 0;
}
- public static bool operator <=(BigInteger bi1, BigInteger bi2)
+ public static bool operator <= (BigInteger bi1, BigInteger bi2)
{
- return Kernel.Compare(bi1, bi2) <= 0;
+ return Kernel.Compare (bi1, bi2) <= 0;
}
- public Sign Compare(BigInteger bi)
+ public Sign Compare (BigInteger bi)
{
- return Kernel.Compare(this, bi);
+ return Kernel.Compare (this, bi);
}
#endregion
#region Formatting
- public string ToString(uint radix)
+ public string ToString (uint radix)
{
- return ToString(radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
- public string ToString(uint radix, string characterSet)
+ public string ToString (uint radix, string charSet)
{
- if (characterSet.Length < radix)
- throw new ArgumentException("charSet length less than radix", "characterSet");
+ if (charSet.Length < radix)
+ throw new ArgumentException ("charSet length less than radix", "charSet");
if (radix == 1)
- throw new ArgumentException("There is no such thing as radix one notation", "radix");
+ throw new ArgumentException ("There is no such thing as radix one notation", "radix");
- if (this == 0)
- return "0";
- if (this == 1)
- return "1";
+ if (this == 0) return "0";
+ if (this == 1) return "1";
string result = "";
- BigInteger a = new BigInteger(this);
+ BigInteger a = new BigInteger (this);
- while (a != 0)
- {
- uint rem = Kernel.SingleByteDivideInPlace(a, radix);
- result = characterSet[(int)rem] + result;
+ while (a != 0) {
+ uint rem = Kernel.SingleByteDivideInPlace (a, radix);
+ result = charSet [ (int)rem] + result;
}
return result;
@@ -820,102 +684,97 @@ namespace Mono.Math
/// uints used in data and by setting the sign to Sign.Zero if the
/// value of this is 0.
/// </summary>
- private void Normalize()
+ private void Normalize ()
{
// Normalize length
- while (length > 0 && data[length - 1] == 0)
- length--;
+ while (length > 0 && data [length-1] == 0) length--;
// Check for zero
if (length == 0)
length++;
}
- public void Clear()
+ public void Clear ()
{
- for (int i = 0; i < length; i++)
- data[i] = 0x00;
+ for (int i=0; i < length; i++)
+ data [i] = 0x00;
}
#endregion
#region Object Impl
- public override int GetHashCode()
+ public override int GetHashCode ()
{
uint val = 0;
for (uint i = 0; i < this.length; i++)
- val ^= this.data[i];
+ val ^= this.data [i];
return (int)val;
}
- public override string ToString()
+ public override string ToString ()
{
- return ToString(10);
+ return ToString (10);
}
- public override bool Equals(object o)
+ public override bool Equals (object o)
{
- if (o == null)
- return false;
- if (o is int)
- return (int)o >= 0 && this == (uint)o;
+ if (o == null) return false;
+ if (o is int) return (int)o >= 0 && this == (uint)o;
- BigInteger bi = o as BigInteger;
- if (bi == null)
- return false;
-
- return Kernel.Compare(this, bi) == 0;
+ return Kernel.Compare (this, (BigInteger)o) == 0;
}
#endregion
#region Number Theory
- public BigInteger GCD(BigInteger bi)
+ public BigInteger gcd (BigInteger bi)
{
- return Kernel.gcd(this, bi);
+ return Kernel.gcd (this, bi);
}
- public BigInteger ModInverse(BigInteger modulus)
+ public BigInteger modInverse (BigInteger mod)
{
- return Kernel.modInverse(this, modulus);
+ return Kernel.modInverse (this, mod);
}
- public BigInteger ModPow(BigInteger exp, BigInteger n)
+ public BigInteger modPow (BigInteger exp, BigInteger n)
{
- ModulusRing mr = new ModulusRing(n);
- return mr.Pow(this, exp);
+ ModulusRing mr = new ModulusRing (n);
+ return mr.Pow (this, exp);
}
-
+
#endregion
#region Prime Testing
- public bool IsProbablePrime()
+ public bool isProbablePrime ()
{
- // can we use our small-prime table ?
- if (this <= smallPrimes[smallPrimes.Length - 1])
- {
- for (int p = 0; p < smallPrimes.Length; p++)
- {
- if (this == smallPrimes[p])
- return true;
- }
- // the list is complete, so it's not a prime
- return false;
+
+ for (int p = 0; p < smallPrimes.Length; p++) {
+ if (this == smallPrimes [p])
+ return true;
+ if (this % smallPrimes [p] == 0)
+ return false;
}
- // otherwise check if we can divide by one of the small primes
- for (int p = 0; p < smallPrimes.Length; p++)
- {
- if (this % smallPrimes[p] == 0)
+ return PrimalityTests.RabinMillerTest (this, Prime.ConfidenceFactor.Medium);
+ }
+
+ [Obsolete]
+ public bool isProbablePrime (int notUsed)
+ {
+
+ for (int p = 0; p < smallPrimes.Length; p++) {
+ if (this % smallPrimes [p] == 0)
return false;
}
- // the last step is to confirm the "large" prime with the SPP or Miller-Rabin test
- return PrimalityTests.Test(this, Prime.ConfidenceFactor.Medium);
+
+ return
+ PrimalityTests.SmallPrimeSppTest (this, Prime.ConfidenceFactor.Medium);
}
#endregion
@@ -927,37 +786,36 @@ namespace Mono.Math
/// </summary>
/// <param name="bi">A BigInteger</param>
/// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
- public static BigInteger NextHighestPrime(BigInteger bi)
+ public static BigInteger NextHightestPrime (BigInteger bi)
{
- NextPrimeFinder npf = new NextPrimeFinder();
- return npf.GenerateNewPrime(0, bi);
+ NextPrimeFinder npf = new NextPrimeFinder ();
+ return npf.GenerateNewPrime (0, bi);
}
- public static BigInteger GeneratePseudoPrime(int bits)
+ public static BigInteger genPseudoPrime (int bits)
{
- SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase();
- return sspg.GenerateNewPrime(bits);
+ SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase ();
+ return sspg.GenerateNewPrime (bits);
}
/// <summary>
/// Increments this by two
/// </summary>
- public void Incr2()
+ public void Incr2 ()
{
int i = 0;
- data[0] += 2;
+ data [0] += 2;
// If there was no carry, nothing to do
- if (data[0] < 2)
- {
+ if (data [0] < 2) {
// Account for the first carry
- data[++i]++;
+ data [++i]++;
// Keep adding until no carry
- while (data[i++] == 0x0)
- data[i]++;
+ while (data [i++] == 0x0)
+ data [i]++;
// See if we increased the data length
if (length == (uint)i)
@@ -967,50 +825,47 @@ namespace Mono.Math
#endregion
- internal sealed class ModulusRing
- {
+ public sealed class ModulusRing {
BigInteger mod, constant;
- public ModulusRing(BigInteger modulus)
+ public ModulusRing (BigInteger mod)
{
- this.mod = modulus;
+ this.mod = mod;
// calculate constant = b^ (2k) / m
uint i = mod.length << 1;
- constant = new BigInteger(Sign.Positive, i + 1);
- constant.data[i] = 0x00000001;
+ constant = new BigInteger (Sign.Positive, i + 1);
+ constant.data [i] = 0x00000001;
constant = constant / mod;
}
- public void BarrettReduction(BigInteger x)
+ public void BarrettReduction (BigInteger x)
{
BigInteger n = mod;
uint k = n.length,
- kPlusOne = k + 1,
- kMinusOne = k - 1;
+ kPlusOne = k+1,
+ kMinusOne = k-1;
// x < mod, so nothing to do.
- if (x.length < k)
- return;
+ if (x.length < k) return;
BigInteger q3;
//
// Validate pointers
//
- if (x.data.Length < x.length)
- throw new IndexOutOfRangeException("x out of range");
+ if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");
// q1 = x / b^ (k-1)
// q2 = q1 * constant
// q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
// TODO: We should the method in HAC p 604 to do this (14.45)
- q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);
- Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
+ q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
+ Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
// r1 = x mod b^ (k+1)
// i.e. keep the lowest (k+1) words
@@ -1018,100 +873,79 @@ namespace Mono.Math
uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
x.length = lengthToCopy;
- x.Normalize();
+ x.Normalize ();
// r2 = (q3 * n) mod b^ (k+1)
// partial multiplication of q3 and n
- BigInteger r2 = new BigInteger(Sign.Positive, kPlusOne);
- Kernel.MultiplyMod2p32pmod(q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
+ BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
+ Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
- r2.Normalize();
+ r2.Normalize ();
- if (r2 <= x)
- {
- Kernel.MinusEq(x, r2);
- }
- else
- {
- BigInteger val = new BigInteger(Sign.Positive, kPlusOne + 1);
- val.data[kPlusOne] = 0x00000001;
+ if (r2 < x) {
+ Kernel.MinusEq (x, r2);
+ } else {
+ BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
+ val.data [kPlusOne] = 0x00000001;
- Kernel.MinusEq(val, r2);
- Kernel.PlusEq(x, val);
+ Kernel.MinusEq (val, r2);
+ Kernel.PlusEq (x, val);
}
while (x >= n)
- Kernel.MinusEq(x, n);
+ Kernel.MinusEq (x, n);
}
- public BigInteger Multiply(BigInteger a, BigInteger b)
+ public BigInteger Multiply (BigInteger a, BigInteger b)
{
- if (a == 0 || b == 0)
- return 0;
+ if (a == 0 || b == 0) return 0;
- if (a > mod)
+ if (a.length >= mod.length << 1)
a %= mod;
- if (b > mod)
+ if (b.length >= mod.length << 1)
b %= mod;
- BigInteger ret = new BigInteger(a * b);
- BarrettReduction(ret);
+ if (a.length >= mod.length)
+ BarrettReduction (a);
+
+ if (b.length >= mod.length)
+ BarrettReduction (b);
+
+ BigInteger ret = new BigInteger (a * b);
+ BarrettReduction (ret);
return ret;
}
- public BigInteger Difference(BigInteger a, BigInteger b)
+ public BigInteger Difference (BigInteger a, BigInteger b)
{
- Sign cmp = Kernel.Compare(a, b);
+ Sign cmp = Kernel.Compare (a, b);
BigInteger diff;
- switch (cmp)
- {
+ switch (cmp) {
case Sign.Zero:
return 0;
case Sign.Positive:
- diff = a - b;
- break;
+ diff = a - b; break;
case Sign.Negative:
- diff = b - a;
- break;
+ diff = b - a; break;
default:
throw new InvalidOperationException();
}
- if (diff >= mod)
- {
+ if (diff >= mod) {
if (diff.length >= mod.length << 1)
diff %= mod;
else
- BarrettReduction(diff);
+ BarrettReduction (diff);
}
if (cmp == Sign.Negative)
diff = mod - diff;
return diff;
}
-#if true
- public BigInteger Pow(BigInteger a, BigInteger k)
- {
- BigInteger b = new BigInteger(1);
- if (k == 0)
- return b;
-
- BigInteger A = a;
- if (k.TestBit(0))
- b = a;
- for (int i = 1; i < k.BitCount(); i++)
- {
- A = Multiply(A, A);
- if (k.TestBit(i))
- b = Multiply(A, b);
- }
- return b;
- }
-#else
public BigInteger Pow (BigInteger b, BigInteger exp)
{
if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
@@ -1123,13 +957,13 @@ namespace Mono.Math
BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
BigInteger tempNum = new BigInteger (b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
- uint totalBits = (uint)exp.BitCount ();
+ uint totalBits = (uint)exp.bitCount ();
uint [] wkspace = new uint [mod.length << 1];
// perform squaring and multiply exponentiation
for (uint pos = 0; pos < totalBits; pos++) {
- if (exp.TestBit (pos)) {
+ if (exp.testBit (pos)) {
Array.Clear (wkspace, 0, wkspace.Length);
Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
@@ -1157,13 +991,13 @@ namespace Mono.Math
BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
uint mPrime = Montgomery.Inverse (mod.data [0]);
- uint totalBits = (uint)exp.BitCount ();
+ uint totalBits = (uint)exp.bitCount ();
uint [] wkspace = new uint [mod.length << 1];
// perform squaring and multiply exponentiation
for (uint pos = 0; pos < totalBits; pos++) {
- if (exp.TestBit (pos)) {
+ if (exp.testBit (pos)) {
Array.Clear (wkspace, 0, wkspace.Length);
Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
@@ -1175,70 +1009,53 @@ namespace Mono.Math
Montgomery.Reduce (resultNum, mod, mPrime);
}
- // the value of tempNum is required in the last loop
- if (pos < totalBits - 1) {
- Kernel.SquarePositive (tempNum, ref wkspace);
- Montgomery.Reduce (tempNum, mod, mPrime);
- }
+ Kernel.SquarePositive (tempNum, ref wkspace);
+ Montgomery.Reduce (tempNum, mod, mPrime);
}
Montgomery.Reduce (resultNum, mod, mPrime);
return resultNum;
}
-#endif
+
#region Pow Small Base
// TODO: Make tests for this, not really needed b/c prime stuff
// checks it, but still would be nice
-#if true
- public BigInteger Pow(uint b, BigInteger exp)
- {
- return Pow(new BigInteger(b), exp);
- }
-#else
public BigInteger Pow (uint b, BigInteger exp)
{
-// if (b != 2) {
- if ((mod.data [0] & 1) == 1)
- return OddPow (b, exp);
- else
- return EvenPow (b, exp);
-/* buggy in some cases (like the well tested primes)
+ if (b != 2) {
+ if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
+ else return EvenPow (b, exp);
} else {
- if ((mod.data [0] & 1) == 1)
- return OddModTwoPow (exp);
- else
- return EvenModTwoPow (exp);
- }*/
+ if ((mod.data [0] & 1) == 1) return OddModTwoPow (exp);
+ else return EvenModTwoPow (exp);
+ }
}
- private BigInteger OddPow(uint b, BigInteger exp)
+ private BigInteger OddPow (uint b, BigInteger exp)
{
- exp.Normalize();
- uint[] wkspace = new uint[mod.length << 1 + 1];
+ exp.Normalize ();
+ uint [] wkspace = new uint [mod.length << 1 + 1];
- BigInteger resultNum = Montgomery.ToMont((BigInteger)b, this.mod);
- resultNum = new BigInteger(resultNum, mod.length << 1 + 1);
+ BigInteger resultNum = Montgomery.ToMont ((BigInteger)b, this.mod);
+ resultNum = new BigInteger (resultNum, mod.length << 1 +1);
- uint mPrime = Montgomery.Inverse(mod.data[0]);
+ uint mPrime = Montgomery.Inverse (mod.data [0]);
- int bc = exp.BitCount () - 2;
- uint pos = (bc > 1 ? (uint) bc : 1);
+ uint pos = (uint)exp.bitCount () - 2;
//
// We know that the first itr will make the val b
//
- do
- {
+ do {
//
// r = r ^ 2 % m
//
Kernel.SquarePositive(resultNum, ref wkspace);
resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
- if (exp.TestBit(pos))
- {
+ if (exp.testBit(pos)) {
//
// r = r * b % m
@@ -1249,25 +1066,20 @@ namespace Mono.Math
uint i = 0;
ulong mc = 0;
- do
- {
+ do {
mc += (ulong)resultNum.data[u + i] * (ulong)b;
resultNum.data[u + i] = (uint)mc;
mc >>= 32;
} while (++i < resultNum.length);
- if (resultNum.length < mod.length)
- {
- if (mc != 0)
- {
+ if (resultNum.length < mod.length) {
+ if (mc != 0) {
resultNum.data[u + i] = (uint)mc;
resultNum.length++;
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
}
- }
- else if (mc != 0)
- {
+ } else if (mc != 0) {
//
// First, we estimate the quotient by dividing
@@ -1279,79 +1091,61 @@ namespace Mono.Math
// We would rather have this estimate overshoot,
// so we add one to the divisor
- uint divEstimate;
- if (mod.data [mod.length - 1] < UInt32.MaxValue) {
- divEstimate = (uint) ((((ulong)cc << 32) | (ulong)resultNum.data[u + i - 1]) /
- (mod.data [mod.length-1] + 1));
- }
- else {
- // guess but don't divide by 0
- divEstimate = (uint) ((((ulong)cc << 32) | (ulong)resultNum.data[i - 1]) /
- (mod.data [mod.length-1]));
- }
+ uint divEstimate = (uint)((((ulong)cc << 32) | (ulong)resultNum.data[u + i - 1]) /
+ (mod.data[mod.length - 1] + 1));
uint t;
i = 0;
mc = 0;
- do
- {
+ do {
mc += (ulong)mod.data[i] * (ulong)divEstimate;
t = resultNum.data[u + i];
resultNum.data[u + i] -= (uint)mc;
mc >>= 32;
- if (resultNum.data[u + i] > t)
- mc++;
+ if (resultNum.data[u + i] > t) mc++;
i++;
} while (i < resultNum.length);
cc -= (uint)mc;
- if (cc != 0)
- {
+ if (cc != 0) {
uint sc = 0, j = 0;
uint[] s = mod.data;
- do
- {
+ do {
uint a = s[j];
- if (((a += sc) < sc) | ((resultNum.data[u + j] -= a) > ~a))
- sc = 1;
- else
- sc = 0;
+ if (((a += sc) < sc) | ((resultNum.data[u + j] -= a) > ~a)) sc = 1;
+ else sc = 0;
j++;
} while (j < resultNum.length);
cc -= sc;
}
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
- }
- else
- {
+ } else {
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
}
}
} while (pos-- > 0);
- resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
+ resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
return resultNum;
}
-
- private BigInteger EvenPow(uint b, BigInteger exp)
- {
+
+ private BigInteger EvenPow(uint b, BigInteger exp) {
exp.Normalize();
uint[] wkspace = new uint[mod.length << 1 + 1];
BigInteger resultNum = new BigInteger((BigInteger)b, mod.length << 1 + 1);
- uint pos = (uint)exp.BitCount() - 2;
+ uint pos = (uint)exp.bitCount() - 2;
//
// We know that the first itr will make the val b
//
- do
- {
+ do {
//
// r = r ^ 2 % m
//
@@ -1359,8 +1153,7 @@ namespace Mono.Math
if (!(resultNum.length < mod.length))
BarrettReduction(resultNum);
- if (exp.TestBit(pos))
- {
+ if (exp.testBit(pos)) {
//
// r = r * b % m
@@ -1371,25 +1164,20 @@ namespace Mono.Math
uint i = 0;
ulong mc = 0;
- do
- {
+ do {
mc += (ulong)resultNum.data[u + i] * (ulong)b;
resultNum.data[u + i] = (uint)mc;
mc >>= 32;
} while (++i < resultNum.length);
- if (resultNum.length < mod.length)
- {
- if (mc != 0)
- {
+ if (resultNum.length < mod.length) {
+ if (mc != 0) {
resultNum.data[u + i] = (uint)mc;
resultNum.length++;
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
}
- }
- else if (mc != 0)
- {
+ } else if (mc != 0) {
//
// First, we estimate the quotient by dividing
@@ -1408,39 +1196,31 @@ namespace Mono.Math
i = 0;
mc = 0;
- do
- {
+ do {
mc += (ulong)mod.data[i] * (ulong)divEstimate;
t = resultNum.data[u + i];
resultNum.data[u + i] -= (uint)mc;
mc >>= 32;
- if (resultNum.data[u + i] > t)
- mc++;
+ if (resultNum.data[u + i] > t) mc++;
i++;
} while (i < resultNum.length);
cc -= (uint)mc;
- if (cc != 0)
- {
+ if (cc != 0) {
uint sc = 0, j = 0;
uint[] s = mod.data;
- do
- {
+ do {
uint a = s[j];
- if (((a += sc) < sc) | ((resultNum.data[u + j] -= a) > ~a))
- sc = 1;
- else
- sc = 0;
+ if (((a += sc) < sc) | ((resultNum.data[u + j] -= a) > ~a)) sc = 1;
+ else sc = 0;
j++;
} while (j < resultNum.length);
cc -= sc;
}
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
- }
- else
- {
+ } else {
while (resultNum >= mod)
Kernel.MinusEq(resultNum, mod);
}
@@ -1449,17 +1229,15 @@ namespace Mono.Math
return resultNum;
}
-#endif
- /* known to be buggy in some cases */
-#if false
- private BigInteger EvenModTwoPow(BigInteger exp)
+
+ private BigInteger EvenModTwoPow (BigInteger exp)
{
- exp.Normalize();
- uint[] wkspace = new uint[mod.length << 1 + 1];
+ exp.Normalize ();
+ uint [] wkspace = new uint [mod.length << 1 + 1];
- BigInteger resultNum = new BigInteger(2, mod.length << 1 + 1);
+ BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
- uint value = exp.data[exp.length - 1];
+ uint value = exp.data [exp.length - 1];
uint mask = 0x80000000;
// Find the first bit of the exponent
@@ -1474,17 +1252,14 @@ namespace Mono.Math
uint wPos = exp.length - 1;
- do
- {
- value = exp.data[wPos];
- do
- {
- Kernel.SquarePositive(resultNum, ref wkspace);
+ do {
+ value = exp.data [wPos];
+ do {
+ Kernel.SquarePositive (resultNum, ref wkspace);
if (resultNum.length >= mod.length)
- BarrettReduction(resultNum);
+ BarrettReduction (resultNum);
- if ((value & mask) != 0)
- {
+ if ((value & mask) != 0) {
//
// resultNum = (resultNum * 2) % mod
//
@@ -1496,8 +1271,7 @@ namespace Mono.Math
uint uu = u;
uint uuE = u + resultNum.length;
uint x, carry = 0;
- while (uu < uuE)
- {
+ while (uu < uuE) {
x = resultNum.data[uu];
resultNum.data[uu] = (x << 1) | carry;
carry = x >> (32 - 1);
@@ -1505,14 +1279,12 @@ namespace Mono.Math
}
// subtraction inlined because we know it is square
- if (carry != 0 || resultNum >= mod)
- {
+ if (carry != 0 || resultNum >= mod) {
uu = u;
uint c = 0;
uint[] s = mod.data;
uint i = 0;
- do
- {
+ do {
uint a = s[i];
if (((a += c) < c) | ((resultNum.data[uu++] -= a) > ~a))
c = 1;
@@ -1530,28 +1302,26 @@ namespace Mono.Math
return resultNum;
}
- private BigInteger OddModTwoPow(BigInteger exp)
+ private BigInteger OddModTwoPow (BigInteger exp)
{
- uint[] wkspace = new uint[mod.length << 1 + 1];
+ uint [] wkspace = new uint [mod.length << 1 + 1];
- BigInteger resultNum = Montgomery.ToMont((BigInteger)2, this.mod);
- resultNum = new BigInteger(resultNum, mod.length << 1 + 1);
+ BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
+ resultNum = new BigInteger (resultNum, mod.length << 1 +1);
- uint mPrime = Montgomery.Inverse(mod.data[0]);
+ uint mPrime = Montgomery.Inverse (mod.data [0]);
//
// TODO: eat small bits, the ones we can do with no modular reduction
//
- uint pos = (uint)exp.BitCount() - 2;
+ uint pos = (uint)exp.bitCount () - 2;
- do
- {
- Kernel.SquarePositive(resultNum, ref wkspace);
- resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
+ do {
+ Kernel.SquarePositive (resultNum, ref wkspace);
+ resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
- if (exp.TestBit(pos))
- {
+ if (exp.testBit(pos)) {
//
// resultNum = (resultNum * 2) % mod
//
@@ -1563,8 +1333,7 @@ namespace Mono.Math
uint uu = u;
uint uuE = u + resultNum.length;
uint x, carry = 0;
- while (uu < uuE)
- {
+ while (uu < uuE) {
x = resultNum.data[uu];
resultNum.data[uu] = (x << 1) | carry;
carry = x >> (32 - 1);
@@ -1572,14 +1341,12 @@ namespace Mono.Math
}
// subtraction inlined because we know it is square
- if (carry != 0 || resultNum >= mod)
- {
+ if (carry != 0 || resultNum >= mod) {
uint s = 0;
uu = u;
uint c = 0;
uint ss = s;
- do
- {
+ do {
uint a = mod.data[ss++];
if (((a += c) < c) | ((resultNum.data[uu++] -= a) > ~a))
c = 1;
@@ -1590,21 +1357,15 @@ namespace Mono.Math
}
} while (pos-- > 0);
- resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
+ resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
return resultNum;
}
-#endif
+
#endregion
}
- internal sealed class Montgomery
- {
-
- private Montgomery()
- {
- }
-
- public static uint Inverse(uint n)
+ public sealed class Montgomery {
+ public static uint Inverse (uint n)
{
uint y = n, z;
@@ -1614,10 +1375,9 @@ namespace Mono.Math
return (uint)-y;
}
- public static BigInteger ToMont(BigInteger n, BigInteger m)
+ public static BigInteger ToMont (BigInteger n, BigInteger m)
{
- n.Normalize();
- m.Normalize();
+ n.Normalize (); m.Normalize ();
n <<= (int)m.length * 32;
n %= m;
@@ -1628,8 +1388,7 @@ namespace Mono.Math
{
BigInteger A = n;
uint a = 0, mm = 0;
- for (uint i = 0; i < m.length; i++)
- {
+ for (uint i = 0; i < m.length; i++) {
// The mod here is taken care of by the CPU,
// since the multiply will overflow.
uint u_i = A.data[a] * mPrime /* % 2^32 */;
@@ -1649,8 +1408,7 @@ namespace Mono.Math
uint j = 1;
// Multiply and add
- for (; j < m.length; j++)
- {
+ for (; j < m.length; j++) {
c += (ulong)u_i * (ulong)m.data[mP++] + A.data[aSP++];
A.data[aDP++] = (uint)c;
c >>= 32;
@@ -1658,48 +1416,38 @@ namespace Mono.Math
// Account for carry
// TODO: use a better loop here, we dont need the ulong stuff
- for (; j < A.length; j++)
- {
+ for (; j < A.length; j++) {
c += A.data[aSP++];
A.data[aDP++] = (uint)c;
c >>= 32;
- if (c == 0)
- {
- j++;
- break;
- }
+ if (c == 0) { j++; break; }
}
// Copy the rest
- for (; j < A.length; j++)
- {
+ for (; j < A.length; j++) {
A.data[aDP++] = A.data[aSP++];
}
A.data[aDP++] = (uint)c;
}
- while (A.length > 1 && A.data[a + A.length - 1] == 0)
- A.length--;
+ while (A.length > 1 && A.data[a + A.length - 1] == 0) A.length--;
- if (A >= m)
- Kernel.MinusEq(A, m);
+ if (A >= m) Kernel.MinusEq(A, m);
return A;
}
-#if _NOT_USED_
+
public static BigInteger Reduce (BigInteger n, BigInteger m)
{
return Reduce (n, m, Inverse (m.data [0]));
}
-#endif
}
/// <summary>
/// Low level functions for the BigInteger
/// </summary>
- private static class Kernel
- {
-
+ private sealed class Kernel {
+ private Kernel() { }
#region Addition/Subtraction
/// <summary>
@@ -1708,144 +1456,128 @@ namespace Mono.Math
/// <param name="bi1">A BigInteger</param>
/// <param name="bi2">A BigInteger</param>
/// <returns>bi1 + bi2</returns>
- public static BigInteger AddSameSign(BigInteger bi1, BigInteger bi2)
+ public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
{
- uint[] x, y;
+ uint [] x, y;
uint yMax, xMax, i = 0;
// x should be bigger
- if (bi1.length < bi2.length)
- {
+ if (bi1.length < bi2.length) {
x = bi2.data;
xMax = bi2.length;
y = bi1.data;
yMax = bi1.length;
- }
- else
- {
+ } else {
x = bi1.data;
xMax = bi1.length;
y = bi2.data;
yMax = bi2.length;
}
+
+ BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
- BigInteger result = new BigInteger(Sign.Positive, xMax + 1);
-
- uint[] r = result.data;
+ uint [] r = result.data;
ulong sum = 0;
// Add common parts of both numbers
- do
- {
- sum = ((ulong)x[i]) + ((ulong)y[i]) + sum;
- r[i] = (uint)sum;
+ do {
+ sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
+ r [i] = (uint)sum;
sum >>= 32;
} while (++i < yMax);
// Copy remainder of longer number while carry propagation is required
bool carry = (sum != 0);
- if (carry)
- {
+ if (carry) {
- if (i < xMax)
- {
+ if (i < xMax) {
do
- carry = ((r[i] = x[i] + 1) == 0);
+ carry = ((r [i] = x [i] + 1) == 0);
while (++i < xMax && carry);
}
- if (carry)
- {
- r[i] = 1;
+ if (carry) {
+ r [i] = 1;
result.length = ++i;
return result;
}
}
// Copy the rest
- if (i < xMax)
- {
+ if (i < xMax) {
do
- r[i] = x[i];
+ r [i] = x [i];
while (++i < xMax);
}
- result.Normalize();
+ result.Normalize ();
return result;
}
- public static BigInteger Subtract(BigInteger big, BigInteger small)
+ public static BigInteger Subtract (BigInteger big, BigInteger small)
{
- BigInteger result = new BigInteger(Sign.Positive, big.length);
+ BigInteger result = new BigInteger (Sign.Positive, big.length);
- uint[] r = result.data, b = big.data, s = small.data;
+ uint [] r = result.data, b = big.data, s = small.data;
uint i = 0, c = 0;
- do
- {
+ do {
- uint x = s[i];
- if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
+ uint x = s [i];
+ if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
c = 1;
else
c = 0;
} while (++i < small.length);
- if (i == big.length)
- goto fixup;
+ if (i == big.length) goto fixup;
- if (c == 1)
- {
+ if (c == 1) {
do
- r[i] = b[i] - 1;
- while (b[i++] == 0 && i < big.length);
+ r [i] = b [i] - 1;
+ while (b [i++] == 0 && i < big.length);
- if (i == big.length)
- goto fixup;
+ if (i == big.length) goto fixup;
}
do
- r[i] = b[i];
+ r [i] = b [i];
while (++i < big.length);
- fixup:
+ fixup:
- result.Normalize();
+ result.Normalize ();
return result;
}
- public static void MinusEq(BigInteger big, BigInteger small)
+ public static void MinusEq (BigInteger big, BigInteger small)
{
- uint[] b = big.data, s = small.data;
+ uint [] b = big.data, s = small.data;
uint i = 0, c = 0;
- do
- {
- uint x = s[i];
- if (((x += c) < c) | ((b[i] -= x) > ~x))
+ do {
+ uint x = s [i];
+ if (((x += c) < c) | ((b [i] -= x) > ~x))
c = 1;
else
c = 0;
} while (++i < small.length);
- if (i == big.length)
- goto fixup;
+ if (i == big.length) goto fixup;
- if (c == 1)
- {
+ if (c == 1) {
do
- b[i]--;
- while (b[i++] == 0 && i < big.length);
+ b [i]--;
+ while (b [i++] == 0 && i < big.length);
}
- fixup:
+ fixup:
- // Normalize length
- while (big.length > 0 && big.data[big.length - 1] == 0)
- big.length--;
+ // Normalize length
+ while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
// Check for zero
if (big.length == 0)
@@ -1853,72 +1585,64 @@ namespace Mono.Math
}
- public static void PlusEq(BigInteger bi1, BigInteger bi2)
+ public static void PlusEq (BigInteger bi1, BigInteger bi2)
{
- uint[] x, y;
+ uint [] x, y;
uint yMax, xMax, i = 0;
bool flag = false;
// x should be bigger
- if (bi1.length < bi2.length)
- {
+ if (bi1.length < bi2.length){
flag = true;
x = bi2.data;
xMax = bi2.length;
y = bi1.data;
yMax = bi1.length;
- }
- else
- {
+ } else {
x = bi1.data;
xMax = bi1.length;
y = bi2.data;
yMax = bi2.length;
}
- uint[] r = bi1.data;
+ uint [] r = bi1.data;
ulong sum = 0;
// Add common parts of both numbers
- do
- {
- sum += ((ulong)x[i]) + ((ulong)y[i]);
- r[i] = (uint)sum;
+ do {
+ sum += ((ulong)x [i]) + ((ulong)y [i]);
+ r [i] = (uint)sum;
sum >>= 32;
} while (++i < yMax);
// Copy remainder of longer number while carry propagation is required
bool carry = (sum != 0);
- if (carry)
- {
+ if (carry){
- if (i < xMax)
- {
+ if (i < xMax) {
do
- carry = ((r[i] = x[i] + 1) == 0);
+ carry = ((r [i] = x [i] + 1) == 0);
while (++i < xMax && carry);
}
- if (carry)
- {
- r[i] = 1;
+ if (carry) {
+ r [i] = 1;
bi1.length = ++i;
return;
}
}
// Copy the rest
- if (flag && i < xMax - 1)
- {
+ if (flag && i < xMax - 1) {
do
- r[i] = x[i];
+ r [i] = x [i];
while (++i < xMax);
}
bi1.length = xMax + 1;
- bi1.Normalize();
+ bi1.Normalize ();
}
#endregion
@@ -1931,27 +1655,22 @@ namespace Mono.Math
/// <param name="bi1">A BigInteger</param>
/// <param name="bi2">A BigInteger</param>
/// <returns>The sign of bi1 - bi2</returns>
- public static Sign Compare(BigInteger bi1, BigInteger bi2)
+ public static Sign Compare (BigInteger bi1, BigInteger bi2)
{
//
// Step 1. Compare the lengths
//
uint l1 = bi1.length, l2 = bi2.length;
- while (l1 > 0 && bi1.data[l1 - 1] == 0)
- l1--;
- while (l2 > 0 && bi2.data[l2 - 1] == 0)
- l2--;
+ while (l1 > 0 && bi1.data [l1-1] == 0) l1--;
+ while (l2 > 0 && bi2.data [l2-1] == 0) l2--;
- if (l1 == 0 && l2 == 0)
- return Sign.Zero;
+ if (l1 == 0 && l2 == 0) return Sign.Zero;
// bi1 len < bi2 len
- if (l1 < l2)
- return Sign.Negative;
+ if (l1 < l2) return Sign.Negative;
// bi1 len > bi2 len
- else if (l1 > l2)
- return Sign.Positive;
+ else if (l1 > l2) return Sign.Positive;
//
// Step 2. Compare the bits
@@ -1959,12 +1678,11 @@ namespace Mono.Math
uint pos = l1 - 1;
- while (pos != 0 && bi1.data[pos] == bi2.data[pos])
- pos--;
-
- if (bi1.data[pos] < bi2.data[pos])
+ while (pos != 0 && bi1.data [pos] == bi2.data [pos]) pos--;
+
+ if (bi1.data [pos] < bi2.data [pos])
return Sign.Negative;
- else if (bi1.data[pos] > bi2.data[pos])
+ else if (bi1.data [pos] > bi2.data [pos])
return Sign.Positive;
else
return Sign.Zero;
@@ -1982,133 +1700,123 @@ namespace Mono.Math
/// <param name="n">A BigInteger, upon exit this will hold n / d</param>
/// <param name="d">The divisor</param>
/// <returns>n % d</returns>
- public static uint SingleByteDivideInPlace(BigInteger n, uint d)
+ public static uint SingleByteDivideInPlace (BigInteger n, uint d)
{
ulong r = 0;
uint i = n.length;
- while (i-- > 0)
- {
+ while (i-- > 0) {
r <<= 32;
- r |= n.data[i];
- n.data[i] = (uint)(r / d);
+ r |= n.data [i];
+ n.data [i] = (uint)(r / d);
r %= d;
}
- n.Normalize();
+ n.Normalize ();
return (uint)r;
}
- public static uint DwordMod(BigInteger n, uint d)
+ public static uint DwordMod (BigInteger n, uint d)
{
ulong r = 0;
uint i = n.length;
- while (i-- > 0)
- {
+ while (i-- > 0) {
r <<= 32;
- r |= n.data[i];
+ r |= n.data [i];
r %= d;
}
return (uint)r;
}
- public static BigInteger DwordDiv(BigInteger n, uint d)
+ public static BigInteger DwordDiv (BigInteger n, uint d)
{
- BigInteger ret = new BigInteger(Sign.Positive, n.length);
+ BigInteger ret = new BigInteger (Sign.Positive, n.length);
ulong r = 0;
uint i = n.length;
- while (i-- > 0)
- {
+ while (i-- > 0) {
r <<= 32;
- r |= n.data[i];
- ret.data[i] = (uint)(r / d);
+ r |= n.data [i];
+ ret.data [i] = (uint)(r / d);
r %= d;
}
- ret.Normalize();
+ ret.Normalize ();
return ret;
}
- public static BigInteger[] DwordDivMod(BigInteger n, uint d)
+ public static BigInteger [] DwordDivMod (BigInteger n, uint d)
{
- BigInteger ret = new BigInteger(Sign.Positive, n.length);
+ BigInteger ret = new BigInteger (Sign.Positive , n.length);
ulong r = 0;
uint i = n.length;
- while (i-- > 0)
- {
+ while (i-- > 0) {
r <<= 32;
- r |= n.data[i];
- ret.data[i] = (uint)(r / d);
+ r |= n.data [i];
+ ret.data [i] = (uint)(r / d);
r %= d;
}
- ret.Normalize();
+ ret.Normalize ();
BigInteger rem = (uint)r;
- return new BigInteger[] { ret, rem };
+ return new BigInteger [] {ret, rem};
}
- #endregion
+ #endregion
#region BigNum
- public static BigInteger[] multiByteDivide(BigInteger bi1, BigInteger bi2)
+ public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
{
- if (Kernel.Compare(bi1, bi2) == Sign.Negative)
- return new BigInteger[2] { 0, new BigInteger(bi1) };
+ if (Kernel.Compare (bi1, bi2) == Sign.Negative)
+ return new BigInteger [2] { 0, new BigInteger (bi1) };
- bi1.Normalize();
- bi2.Normalize();
+ bi1.Normalize (); bi2.Normalize ();
if (bi2.length == 1)
- return DwordDivMod(bi1, bi2.data[0]);
+ return DwordDivMod (bi1, bi2.data [0]);
uint remainderLen = bi1.length + 1;
int divisorLen = (int)bi2.length + 1;
uint mask = 0x80000000;
- uint val = bi2.data[bi2.length - 1];
+ uint val = bi2.data [bi2.length - 1];
int shift = 0;
int resultPos = (int)bi1.length - (int)bi2.length;
- while (mask != 0 && (val & mask) == 0)
- {
- shift++;
- mask >>= 1;
+ while (mask != 0 && (val & mask) == 0) {
+ shift++; mask >>= 1;
}
- BigInteger quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
+ BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
BigInteger rem = (bi1 << shift);
- uint[] remainder = rem.data;
+ uint [] remainder = rem.data;
bi2 = bi2 << shift;
int j = (int)(remainderLen - bi2.length);
int pos = (int)remainderLen - 1;
- uint firstDivisorByte = bi2.data[bi2.length - 1];
- ulong secondDivisorByte = bi2.data[bi2.length - 2];
+ uint firstDivisorByte = bi2.data [bi2.length-1];
+ ulong secondDivisorByte = bi2.data [bi2.length-2];
- while (j > 0)
- {
- ulong dividend = ((ulong)remainder[pos] << 32) + (ulong)remainder[pos - 1];
+ while (j > 0) {
+ ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
ulong q_hat = dividend / (ulong)firstDivisorByte;
ulong r_hat = dividend % (ulong)firstDivisorByte;
- do
- {
+ do {
if (q_hat == 0x100000000 ||
- (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))
- {
+ (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
q_hat--;
r_hat += (ulong)firstDivisorByte;
@@ -2130,50 +1838,44 @@ namespace Mono.Math
int nPos = pos - divisorLen + 1;
ulong mc = 0;
uint uint_q_hat = (uint)q_hat;
- do
- {
- mc += (ulong)bi2.data[dPos] * (ulong)uint_q_hat;
- t = remainder[nPos];
- remainder[nPos] -= (uint)mc;
+ do {
+ mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
+ t = remainder [nPos];
+ remainder [nPos] -= (uint)mc;
mc >>= 32;
- if (remainder[nPos] > t)
- mc++;
- dPos++;
- nPos++;
+ if (remainder [nPos] > t) mc++;
+ dPos++; nPos++;
} while (dPos < divisorLen);
nPos = pos - divisorLen + 1;
dPos = 0;
// Overestimate
- if (mc != 0)
- {
+ if (mc != 0) {
uint_q_hat--;
ulong sum = 0;
- do
- {
- sum = ((ulong)remainder[nPos]) + ((ulong)bi2.data[dPos]) + sum;
- remainder[nPos] = (uint)sum;
+ do {
+ sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
+ remainder [nPos] = (uint)sum;
sum >>= 32;
- dPos++;
- nPos++;
+ dPos++; nPos++;
} while (dPos < divisorLen);
}
- quot.data[resultPos--] = (uint)uint_q_hat;
+ quot.data [resultPos--] = (uint)uint_q_hat;
pos--;
j--;
}
- quot.Normalize();
- rem.Normalize();
- BigInteger[] ret = new BigInteger[2] { quot, rem };
+ quot.Normalize ();
+ rem.Normalize ();
+ BigInteger [] ret = new BigInteger [2] { quot, rem };
if (shift != 0)
- ret[1] >>= shift;
+ ret [1] >>= shift;
return ret;
}
@@ -2183,72 +1885,61 @@ namespace Mono.Math
#endregion
#region Shift
- public static BigInteger LeftShift(BigInteger bi, int n)
+ public static BigInteger LeftShift (BigInteger bi, int n)
{
- if (n == 0)
- return new BigInteger(bi, bi.length + 1);
+ if (n == 0) return new BigInteger (bi, bi.length + 1);
int w = n >> 5;
n &= ((1 << 5) - 1);
- BigInteger ret = new BigInteger(Sign.Positive, bi.length + 1 + (uint)w);
+ BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
uint i = 0, l = bi.length;
- if (n != 0)
- {
+ if (n != 0) {
uint x, carry = 0;
- while (i < l)
- {
- x = bi.data[i];
- ret.data[i + w] = (x << n) | carry;
+ while (i < l) {
+ x = bi.data [i];
+ ret.data [i + w] = (x << n) | carry;
carry = x >> (32 - n);
i++;
}
- ret.data[i + w] = carry;
- }
- else
- {
- while (i < l)
- {
- ret.data[i + w] = bi.data[i];
+ ret.data [i + w] = carry;
+ } else {
+ while (i < l) {
+ ret.data [i + w] = bi.data [i];
i++;
}
}
- ret.Normalize();
+ ret.Normalize ();
return ret;
}
- public static BigInteger RightShift(BigInteger bi, int n)
+ public static BigInteger RightShift (BigInteger bi, int n)
{
- if (n == 0)
- return new BigInteger(bi);
+ if (n == 0) return new BigInteger (bi);
int w = n >> 5;
int s = n & ((1 << 5) - 1);
- BigInteger ret = new BigInteger(Sign.Positive, bi.length - (uint)w + 1);
+ BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
uint l = (uint)ret.data.Length - 1;
- if (s != 0)
- {
+ if (s != 0) {
uint x, carry = 0;
- while (l-- > 0)
- {
- x = bi.data[l + w];
- ret.data[l] = (x >> n) | carry;
+ while (l-- > 0) {
+ x = bi.data [l + w];
+ ret.data [l] = (x >> n) | carry;
carry = x << (32 - n);
}
- }
- else
- {
+ } else {
while (l-- > 0)
- ret.data[l] = bi.data[l + w];
+ ret.data [l] = bi.data [l + w];
}
- ret.Normalize();
+ ret.Normalize ();
return ret;
}
@@ -2256,21 +1947,20 @@ namespace Mono.Math
#region Multiply
- public static BigInteger MultiplyByDword(BigInteger n, uint f)
+ public static BigInteger MultiplyByDword (BigInteger n, uint f)
{
- BigInteger ret = new BigInteger(Sign.Positive, n.length + 1);
+ BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
uint i = 0;
ulong c = 0;
- do
- {
- c += (ulong)n.data[i] * (ulong)f;
- ret.data[i] = (uint)c;
+ do {
+ c += (ulong)n.data [i] * (ulong)f;
+ ret.data [i] = (uint)c;
c >>= 32;
} while (++i < n.length);
- ret.data[i] = (uint)c;
- ret.Normalize();
+ ret.data [i] = (uint)c;
+ ret.Normalize ();
return ret;
}
@@ -2289,17 +1979,14 @@ namespace Mono.Math
yE = yB + yLen,
dB = dd + dOffset;
- for (; xP < xE; xP++, dB++)
- {
+ for (; xP < xE; xP++, dB++) {
- if (x[xP] == 0)
- continue;
+ if (x[xP] == 0) continue;
ulong mcarry = 0;
uint dP = dB;
- for (uint yP = yB; yP < yE; yP++, dP++)
- {
+ for (uint yP = yB; yP < yE; yP++, dP++) {
mcarry += ((ulong)x[xP] * (ulong)y[yP]) + (ulong)d[dP];
d[dP] = (uint)mcarry;
@@ -2329,8 +2016,7 @@ namespace Mono.Math
for (; xP < xE; xP++, dB++)
{
- if (x[xP] == 0)
- continue;
+ if (x[xP] == 0) continue;
ulong mcarry = 0;
uint dP = dB;
@@ -2347,9 +2033,7 @@ namespace Mono.Math
}
}
-#if UNUSED
- public static void SquarePositive(BigInteger bi, ref uint[] wkSpace)
- {
+ public static void SquarePositive(BigInteger bi, ref uint[] wkSpace) {
uint[] t = wkSpace;
wkSpace = bi.data;
uint[] d = bi.data;
@@ -2365,8 +2049,7 @@ namespace Mono.Math
uint dP = dd, tP = tt;
- for (uint i = 0; i < dl; i++, dP++)
- {
+ for (uint i = 0; i < dl; i++, dP++) {
if (d[dP] == 0)
continue;
@@ -2375,8 +2058,7 @@ namespace Mono.Math
uint dP2 = dP + 1, tP2 = tP + 2 * i + 1;
- for (uint j = i + 1; j < dl; j++, tP2++, dP2++)
- {
+ for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
// k = i + j
mcarry += ((ulong)bi1val * (ulong)d[dP2]) + t[tP2];
@@ -2393,34 +2075,30 @@ namespace Mono.Math
tP = tt;
uint x, carry = 0;
- while (tP < ttE)
- {
+ while (tP < ttE) {
x = t[tP];
t[tP] = (x << 1) | carry;
carry = x >> (32 - 1);
tP++;
}
- if (carry != 0)
- t[tP] = carry;
+ if (carry != 0) t[tP] = carry;
// Add in the diagnals
dP = dd;
tP = tt;
- for (uint dE = dP + dl; (dP < dE); dP++, tP++)
- {
+ for (uint dE = dP + dl; (dP < dE); dP++, tP++) {
ulong val = (ulong)d[dP] * (ulong)d[dP] + t[tP];
t[tP] = (uint)val;
val >>= 32;
t[(++tP)] += (uint)val;
- if (t[tP] < (uint)val)
- {
+ if (t[tP] < (uint)val) {
uint tP3 = tP;
// Account for the first carry
(t[++tP3])++;
// Keep adding until no carry
- while ((t[tP3++]) == 0)
+ while ((t[tP3++]) == 0x0)
(t[tP3])++;
}
@@ -2429,47 +2107,42 @@ namespace Mono.Math
bi.length <<= 1;
// Normalize length
- while (t[tt + bi.length - 1] == 0 && bi.length > 1)
- bi.length--;
+ while (t[tt + bi.length - 1] == 0 && bi.length > 1) bi.length--;
}
+#if UNUSED
+ public static bool Double (uint [] u, int l)
+ {
+ uint x, carry = 0;
+ uint i = 0;
+ while (i < l) {
+ x = u [i];
+ u [i] = (x << 1) | carry;
+ carry = x >> (32 - 1);
+ i++;
+ }
+ if (carry != 0) u [l] = carry;
+ return carry != 0;
+ }
#endif
- /*
- * Never called in BigInteger (and part of a private class)
- * public static bool Double (uint [] u, int l)
- {
- uint x, carry = 0;
- uint i = 0;
- while (i < l) {
- x = u [i];
- u [i] = (x << 1) | carry;
- carry = x >> (32 - 1);
- i++;
- }
- if (carry != 0) u [l] = carry;
- return carry != 0;
- }*/
-
#endregion
#region Number Theory
- public static BigInteger gcd(BigInteger a, BigInteger b)
+ public static BigInteger gcd (BigInteger a, BigInteger b)
{
BigInteger x = a;
BigInteger y = b;
BigInteger g = y;
- while (x.length > 1)
- {
+ while (x.length > 1) {
g = x;
x = y % x;
y = g;
}
- if (x == 0)
- return g;
+ if (x == 0) return g;
// TODO: should we have something here if we can convert to long?
@@ -2478,23 +2151,17 @@ namespace Mono.Math
// as it should be faster.
//
- uint yy = x.data[0];
+ uint yy = x.data [0];
uint xx = y % yy;
int t = 0;
- while (((xx | yy) & 1) == 0)
- {
- xx >>= 1;
- yy >>= 1;
- t++;
+ while (((xx | yy) & 1) == 0) {
+ xx >>= 1; yy >>= 1; t++;
}
- while (xx != 0)
- {
- while ((xx & 1) == 0)
- xx >>= 1;
- while ((yy & 1) == 0)
- yy >>= 1;
+ while (xx != 0) {
+ while ((xx & 1) == 0) xx >>= 1;
+ while ((yy & 1) == 0) yy >>= 1;
if (xx >= yy)
xx = (xx - yy) >> 1;
else
@@ -2504,13 +2171,12 @@ namespace Mono.Math
return yy << t;
}
- public static uint modInverse(BigInteger bi, uint modulus)
+ public static uint modInverse (BigInteger bi, uint modulus)
{
uint a = modulus, b = bi % modulus;
uint p0 = 0, p1 = 1;
- while (b != 0)
- {
+ while (b != 0) {
if (b == 1)
return p1;
p0 += (a / b) * p1;
@@ -2519,7 +2185,7 @@ namespace Mono.Math
if (a == 0)
break;
if (a == 1)
- return modulus - p0;
+ return modulus-p0;
p1 += (b / a) * p0;
b %= a;
@@ -2527,50 +2193,44 @@ namespace Mono.Math
}
return 0;
}
-
- public static BigInteger modInverse(BigInteger bi, BigInteger modulus)
+
+ public static BigInteger modInverse (BigInteger bi, BigInteger modulus)
{
- if (modulus.length == 1)
- return modInverse(bi, modulus.data[0]);
+ if (modulus.length == 1) return modInverse (bi, modulus.data [0]);
- BigInteger[] p = { 0, 1 };
- BigInteger[] q = new BigInteger[2]; // quotients
- BigInteger[] r = { 0, 0 }; // remainders
+ BigInteger [] p = { 0, 1 };
+ BigInteger [] q = new BigInteger [2]; // quotients
+ BigInteger [] r = { 0, 0 }; // remainders
int step = 0;
BigInteger a = modulus;
BigInteger b = bi;
- ModulusRing mr = new ModulusRing(modulus);
+ ModulusRing mr = new ModulusRing (modulus);
- while (b != 0)
- {
+ while (b != 0) {
- if (step > 1)
- {
+ if (step > 1) {
- BigInteger pval = mr.Difference(p[0], p[1] * q[0]);
- p[0] = p[1];
- p[1] = pval;
+ BigInteger pval = mr.Difference (p [0], p [1] * q [0]);
+ p [0] = p [1]; p [1] = pval;
}
- BigInteger[] divret = multiByteDivide(a, b);
+ BigInteger [] divret = multiByteDivide (a, b);
- q[0] = q[1];
- q[1] = divret[0];
- r[0] = r[1];
- r[1] = divret[1];
+ q [0] = q [1]; q [1] = divret [0];
+ r [0] = r [1]; r [1] = divret [1];
a = b;
- b = divret[1];
+ b = divret [1];
step++;
}
- if (r[0] != 1)
- throw (new ArithmeticException("No inverse!"));
+ if (r [0] != 1)
+ throw (new ArithmeticException ("No inverse!"));
- return mr.Difference(p[0], p[1] * q[0]);
+ return mr.Difference (p [0], p [1] * q [0]);
}
#endregion
diff --git a/src/DotNetOpenId/DiffieHellman/mono/ConfidenceFactor.cs b/src/DotNetOpenId/DiffieHellman/mono/ConfidenceFactor.cs
index 0235a74..9bb5f53 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/ConfidenceFactor.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/ConfidenceFactor.cs
@@ -1,63 +1,42 @@
-//
-// Mono.Math.Prime.ConfidenceFactor.cs - Confidence factor for prime generation
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-
-namespace Mono.Math.Prime {
- /// <summary>
- /// A factor of confidence.
- /// </summary>
- internal enum ConfidenceFactor {
- /// <summary>
- /// Only suitable for development use, probability of failure may be greater than 1/2^20.
- /// </summary>
- ExtraLow,
- /// <summary>
- /// Suitable only for transactions which do not require forward secrecy. Probability of failure about 1/2^40
- /// </summary>
- Low,
- /// <summary>
- /// Designed for production use. Probability of failure about 1/2^80.
- /// </summary>
- Medium,
- /// <summary>
- /// Suitable for sensitive data. Probability of failure about 1/2^160.
- /// </summary>
- High,
- /// <summary>
- /// Use only if you have lots of time! Probability of failure about 1/2^320.
- /// </summary>
- ExtraHigh,
- /// <summary>
- /// Only use methods which generate provable primes. Not yet implemented.
- /// </summary>
- Provable
- }
-}
+//
+// Mono.Math.Prime.ConfidenceFactor.cs - Confidence factor for prime generation
+//
+// Authors:
+// Ben Maurer
+//
+// Copyright (c) 2003 Ben Maurer. All rights reserved
+//
+
+using System;
+
+namespace Mono.Math.Prime {
+ /// <summary>
+ /// A factor of confidence.
+ /// </summary>
+ internal enum ConfidenceFactor {
+ /// <summary>
+ /// Only suitable for development use, probability of failure may be greater than 1/2^20.
+ /// </summary>
+ ExtraLow,
+ /// <summary>
+ /// Suitable only for transactions which do not require forward secrecy. Probability of failure about 1/2^40
+ /// </summary>
+ Low,
+ /// <summary>
+ /// Designed for production use. Probability of failure about 1/2^80.
+ /// </summary>
+ Medium,
+ /// <summary>
+ /// Suitable for sensitive data. Probability of failure about 1/2^160.
+ /// </summary>
+ High,
+ /// <summary>
+ /// Use only if you have lots of time! Probability of failure about 1/2^320.
+ /// </summary>
+ ExtraHigh,
+ /// <summary>
+ /// Only use methods which generate provable primes. Not yet implemented.
+ /// </summary>
+ Provable
+ }
+}
diff --git a/src/DotNetOpenId/DiffieHellman/mono/NextPrimeFinder.cs b/src/DotNetOpenId/DiffieHellman/mono/NextPrimeFinder.cs
index dfa0917..e3405f1 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/NextPrimeFinder.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/NextPrimeFinder.cs
@@ -1,50 +1,28 @@
-//
-// Mono.Math.Prime.Generator.NextPrimeFinder.cs - Prime Generator
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-
-namespace Mono.Math.Prime.Generator {
-
- /// <summary>
- /// Finds the next prime after a given number.
- /// </summary>
- internal class NextPrimeFinder : SequentialSearchPrimeGeneratorBase {
-
- protected override BigInteger GenerateSearchBase (int bits, object Context)
- {
- if (Context == null)
- throw new ArgumentNullException ("Context");
-
- BigInteger ret = new BigInteger ((BigInteger)Context);
- ret.SetBit (0);
- return ret;
- }
- }
-}
+//
+// Mono.Math.Prime.Generator.NextPrimeFinder.cs - Prime Generator
+//
+// Authors:
+// Ben Maurer
+//
+// Copyright (c) 2003 Ben Maurer. All rights reserved
+//
+
+using System;
+
+namespace Mono.Math.Prime.Generator {
+
+ /// <summary>
+ /// Finds the next prime after a given number.
+ /// </summary>
+ //[CLSCompliant(false)]
+ internal class NextPrimeFinder : SequentialSearchPrimeGeneratorBase {
+
+ protected override BigInteger GenerateSearchBase (int bits, object Context)
+ {
+ if (Context == null) throw new ArgumentNullException ("Context");
+ BigInteger ret = new BigInteger ((BigInteger)Context);
+ ret.setBit (0);
+ return ret;
+ }
+ }
+}
diff --git a/src/DotNetOpenId/DiffieHellman/mono/PrimalityTests.cs b/src/DotNetOpenId/DiffieHellman/mono/PrimalityTests.cs
index 2bb84d3..32901b3 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/PrimalityTests.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/PrimalityTests.cs
@@ -1,208 +1,176 @@
-//
-// Mono.Math.Prime.PrimalityTests.cs - Test for primality
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-
-namespace Mono.Math.Prime {
-
- internal delegate bool PrimalityTest (BigInteger bi, ConfidenceFactor confidence);
-
- internal sealed class PrimalityTests {
-
- private PrimalityTests ()
- {
- }
-
- #region SPP Test
-
- private static int GetSPPRounds (BigInteger bi, ConfidenceFactor confidence)
- {
- int bc = bi.BitCount();
-
- int Rounds;
-
- // Data from HAC, 4.49
- if (bc <= 100 ) Rounds = 27;
- else if (bc <= 150 ) Rounds = 18;
- else if (bc <= 200 ) Rounds = 15;
- else if (bc <= 250 ) Rounds = 12;
- else if (bc <= 300 ) Rounds = 9;
- else if (bc <= 350 ) Rounds = 8;
- else if (bc <= 400 ) Rounds = 7;
- else if (bc <= 500 ) Rounds = 6;
- else if (bc <= 600 ) Rounds = 5;
- else if (bc <= 800 ) Rounds = 4;
- else if (bc <= 1250) Rounds = 3;
- else Rounds = 2;
-
- switch (confidence) {
- case ConfidenceFactor.ExtraLow:
- Rounds >>= 2;
- return Rounds != 0 ? Rounds : 1;
- case ConfidenceFactor.Low:
- Rounds >>= 1;
- return Rounds != 0 ? Rounds : 1;
- case ConfidenceFactor.Medium:
- return Rounds;
- case ConfidenceFactor.High:
- return Rounds << 1;
- case ConfidenceFactor.ExtraHigh:
- return Rounds << 2;
- case ConfidenceFactor.Provable:
- throw new Exception ("The Rabin-Miller test can not be executed in a way such that its results are provable");
- default:
- throw new ArgumentOutOfRangeException ("confidence");
- }
- }
-
- public static bool Test (BigInteger n, ConfidenceFactor confidence)
- {
- // Rabin-Miller fails with smaller primes (at least with our BigInteger code)
- if (n.BitCount () < 33)
- return SmallPrimeSppTest (n, confidence);
- else
- return RabinMillerTest (n, confidence);
- }
-
- /// <summary>
- /// Probabilistic prime test based on Rabin-Miller's test
- /// </summary>
- /// <param name="n" type="BigInteger.BigInteger">
- /// <para>
- /// The number to test.
- /// </para>
- /// </param>
- /// <param name="confidence" type="int">
- /// <para>
- /// The number of chosen bases. The test has at least a
- /// 1/4^confidence chance of falsely returning True.
- /// </para>
- /// </param>
- /// <returns>
- /// <para>
- /// True if "this" is a strong pseudoprime to randomly chosen bases.
- /// </para>
- /// <para>
- /// False if "this" is definitely NOT prime.
- /// </para>
- /// </returns>
- public static bool RabinMillerTest (BigInteger n, ConfidenceFactor confidence)
- {
- int bits = n.BitCount ();
- int t = GetSPPRounds (bits, confidence);
-
- // n - 1 == 2^s * r, r is odd
- BigInteger n_minus_1 = n - 1;
- int s = n_minus_1.LowestSetBit ();
- BigInteger r = n_minus_1 >> s;
-
- BigInteger.ModulusRing mr = new BigInteger.ModulusRing (n);
-
- // Applying optimization from HAC section 4.50 (base == 2)
- // not a really random base but an interesting (and speedy) one
- BigInteger y = null;
- // FIXME - optimization disable for small primes due to bug #81857
- if (n.BitCount () > 100)
- y = mr.Pow (2, r);
-
- // still here ? start at round 1 (round 0 was a == 2)
- for (int round = 0; round < t; round++) {
-
- if ((round > 0) || (y == null)) {
- BigInteger a = null;
-
- // check for 2 <= a <= n - 2
- // ...but we already did a == 2 previously as an optimization
- do {
- a = BigInteger.GenerateRandom (bits);
- } while ((a <= 2) && (a >= n_minus_1));
-
- y = mr.Pow (a, r);
- }
-
- if (y == 1)
- continue;
-
- for (int j = 0; ((j < s) && (y != n_minus_1)); j++) {
-
- y = mr.Pow (y, 2);
- if (y == 1)
- return false;
- }
-
- if (y != n_minus_1)
- return false;
- }
- return true;
- }
-
- public static bool SmallPrimeSppTest (BigInteger bi, ConfidenceFactor confidence)
- {
- int Rounds = GetSPPRounds (bi, confidence);
-
- // calculate values of s and t
- BigInteger p_sub1 = bi - 1;
- int s = p_sub1.LowestSetBit ();
-
- BigInteger t = p_sub1 >> s;
-
-
- BigInteger.ModulusRing mr = new BigInteger.ModulusRing (bi);
-
- for (int round = 0; round < Rounds; round++) {
-
- BigInteger b = mr.Pow (BigInteger.smallPrimes [round], t);
-
- if (b == 1) continue; // a^t mod p = 1
-
- bool result = false;
- for (int j = 0; j < s; j++) {
-
- if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
- result = true;
- break;
- }
-
- b = (b * b) % bi;
- }
-
- if (result == false)
- return false;
- }
- return true;
- }
-
- #endregion
-
- // TODO: Implement the Lucus test
- // TODO: Implement other new primality tests
- // TODO: Implement primality proving
- }
-}
+//
+// Mono.Math.Prime.PrimalityTests.cs - Test for primality
+//
+// Authors:
+// Ben Maurer
+//
+// Copyright (c) 2003 Ben Maurer. All rights reserved
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Math.Prime {
+
+ //[CLSCompliant(false)]
+ internal delegate bool PrimalityTest (BigInteger bi, ConfidenceFactor confidence);
+
+ //[CLSCompliant(false)]
+ internal sealed class PrimalityTests {
+
+ #region SPP Test
+
+ private static int GetSPPRounds (BigInteger bi, ConfidenceFactor confidence)
+ {
+ int bc = bi.bitCount();
+
+ int Rounds;
+
+ // Data from HAC, 4.49
+ if (bc <= 100 ) Rounds = 27;
+ else if (bc <= 150 ) Rounds = 18;
+ else if (bc <= 200 ) Rounds = 15;
+ else if (bc <= 250 ) Rounds = 12;
+ else if (bc <= 300 ) Rounds = 9;
+ else if (bc <= 350 ) Rounds = 8;
+ else if (bc <= 400 ) Rounds = 7;
+ else if (bc <= 500 ) Rounds = 6;
+ else if (bc <= 600 ) Rounds = 5;
+ else if (bc <= 800 ) Rounds = 4;
+ else if (bc <= 1250) Rounds = 3;
+ else Rounds = 2;
+
+ switch (confidence) {
+ case ConfidenceFactor.ExtraLow:
+ Rounds >>= 2;
+ return Rounds != 0 ? Rounds : 1;
+ case ConfidenceFactor.Low:
+ Rounds >>= 1;
+ return Rounds != 0 ? Rounds : 1;
+ case ConfidenceFactor.Medium:
+ return Rounds;
+ case ConfidenceFactor.High:
+ return Rounds <<= 1;
+ case ConfidenceFactor.ExtraHigh:
+ return Rounds <<= 2;
+ case ConfidenceFactor.Provable:
+ throw new Exception ("The Rabin-Miller test can not be executed in a way such that its results are provable");
+ default:
+ throw new ArgumentOutOfRangeException ("confidence");
+ }
+ }
+
+ /// <summary>
+ /// Probabilistic prime test based on Rabin-Miller's test
+ /// </summary>
+ /// <param name="bi" type="BigInteger.BigInteger">
+ /// <para>
+ /// The number to test.
+ /// </para>
+ /// </param>
+ /// <param name="confidence" type="int">
+ /// <para>
+ /// The number of chosen bases. The test has at least a
+ /// 1/4^confidence chance of falsely returning True.
+ /// </para>
+ /// </param>
+ /// <returns>
+ /// <para>
+ /// True if "this" is a strong pseudoprime to randomly chosen bases.
+ /// </para>
+ /// <para>
+ /// False if "this" is definitely NOT prime.
+ /// </para>
+ /// </returns>
+ public static bool RabinMillerTest (BigInteger bi, ConfidenceFactor confidence)
+ {
+ int Rounds = GetSPPRounds (bi, confidence);
+
+ // calculate values of s and t
+ BigInteger p_sub1 = bi - 1;
+ int s = p_sub1.LowestSetBit ();
+
+ BigInteger t = p_sub1 >> s;
+
+ int bits = bi.bitCount ();
+ BigInteger a = null;
+ RandomNumberGenerator rng = RandomNumberGenerator.Create ();
+ BigInteger.ModulusRing mr = new BigInteger.ModulusRing (bi);
+
+ for (int round = 0; round < Rounds; round++) {
+ while (true) { // generate a < n
+ a = BigInteger.genRandom (bits, rng);
+
+ // make sure "a" is not 0
+ if (a > 1 && a < bi)
+ break;
+ }
+
+ if (a.gcd (bi) != 1) return false;
+
+ BigInteger b = mr.Pow (a, t);
+
+ if (b == 1) continue; // a^t mod p = 1
+
+ bool result = false;
+ for (int j = 0; j < s; j++) {
+
+ if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
+ result = true;
+ break;
+ }
+
+ b = (b * b) % bi;
+ }
+
+ if (result == false)
+ return false;
+ }
+ return true;
+ }
+
+ public static bool SmallPrimeSppTest (BigInteger bi, ConfidenceFactor confidence)
+ {
+ int Rounds = GetSPPRounds (bi, confidence);
+
+ // calculate values of s and t
+ BigInteger p_sub1 = bi - 1;
+ int s = p_sub1.LowestSetBit ();
+
+ BigInteger t = p_sub1 >> s;
+
+
+ BigInteger.ModulusRing mr = new BigInteger.ModulusRing (bi);
+
+ for (int round = 0; round < Rounds; round++) {
+
+ BigInteger b = mr.Pow (BigInteger.smallPrimes [round], t);
+
+ if (b == 1) continue; // a^t mod p = 1
+
+ bool result = false;
+ for (int j = 0; j < s; j++) {
+
+ if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
+ result = true;
+ break;
+ }
+
+ b = (b * b) % bi;
+ }
+
+ if (result == false)
+ return false;
+ }
+ return true;
+
+ }
+
+ #endregion
+
+
+ // TODO: Implement the Lucus test
+ // TODO: Implement other new primality tests
+ // TODO: Implement primality proving
+ }
+}
diff --git a/src/DotNetOpenId/DiffieHellman/mono/PrimeGeneratorBase.cs b/src/DotNetOpenId/DiffieHellman/mono/PrimeGeneratorBase.cs
index b0f0ed0..5d7f0e9 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/PrimeGeneratorBase.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/PrimeGeneratorBase.cs
@@ -7,60 +7,27 @@
// Copyright (c) 2003 Ben Maurer. All rights reserved
//
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
using System;
-namespace Mono.Math.Prime.Generator
-{
- internal abstract class PrimeGeneratorBase
- {
+namespace Mono.Math.Prime.Generator {
- public virtual ConfidenceFactor Confidence
- {
- get
- {
-#if DEBUG
- return ConfidenceFactor.ExtraLow;
-#else
- return ConfidenceFactor.Medium;
-#endif
+ //[CLSCompliant(false)]
+ internal abstract class PrimeGeneratorBase {
+
+ public virtual ConfidenceFactor Confidence {
+ get {
+ return ConfidenceFactor.Medium;
}
}
- public virtual Prime.PrimalityTest PrimalityTest
- {
- get
- {
- return new Prime.PrimalityTest(PrimalityTests.RabinMillerTest);
+ public virtual Prime.PrimalityTest PrimalityTest {
+ get {
+ return new Prime.PrimalityTest (PrimalityTests.SmallPrimeSppTest);
}
}
- public virtual int TrialDivisionBounds
- {
- get
- {
- return 4000;
- }
+ public virtual int TrialDivisionBounds {
+ get { return 4000; }
}
/// <summary>
@@ -69,11 +36,11 @@ namespace Mono.Math.Prime.Generator
/// <param name="bi">A BigInteger that has been subjected to and passed trial division</param>
/// <returns>False if bi is composite, true if it may be prime.</returns>
/// <remarks>The speed of this method is dependent on Confidence</remarks>
- protected bool PostTrialDivisionTests(BigInteger bi)
+ protected bool PostTrialDivisionTests (BigInteger bi)
{
- return PrimalityTest(bi, this.Confidence);
+ return PrimalityTest (bi, this.Confidence);
}
- public abstract BigInteger GenerateNewPrime(int bits);
+ public abstract BigInteger GenerateNewPrime (int bits);
}
}
diff --git a/src/DotNetOpenId/DiffieHellman/mono/SequentialSearchPrimeGeneratorBase.cs b/src/DotNetOpenId/DiffieHellman/mono/SequentialSearchPrimeGeneratorBase.cs
index 1e4cf9a..c476edd 100644
--- a/src/DotNetOpenId/DiffieHellman/mono/SequentialSearchPrimeGeneratorBase.cs
+++ b/src/DotNetOpenId/DiffieHellman/mono/SequentialSearchPrimeGeneratorBase.cs
@@ -5,121 +5,92 @@
// Ben Maurer
//
// Copyright (c) 2003 Ben Maurer. All rights reserved
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-namespace Mono.Math.Prime.Generator
-{
- internal class SequentialSearchPrimeGeneratorBase : PrimeGeneratorBase
- {
+using System;
+using Mono.Math.Prime;
+
+namespace Mono.Math.Prime.Generator {
+
+ //[CLSCompliant(false)]
+ internal class SequentialSearchPrimeGeneratorBase : PrimeGeneratorBase {
- protected virtual BigInteger GenerateSearchBase(int bits, object context)
+ protected virtual BigInteger GenerateSearchBase (int bits, object Context)
{
- BigInteger ret = BigInteger.GenerateRandom(bits);
- ret.SetBit(0);
+ BigInteger ret = BigInteger.genRandom (bits);
+ ret.setBit (0);
return ret;
}
- public override BigInteger GenerateNewPrime(int bits)
+ public override BigInteger GenerateNewPrime (int bits)
{
- return GenerateNewPrime(bits, null);
+ return GenerateNewPrime (bits, null);
}
- public virtual BigInteger GenerateNewPrime(int bits, object context)
+ public virtual BigInteger GenerateNewPrime (int bits, object Context)
{
//
// STEP 1. Find a place to do a sequential search
//
- BigInteger curVal = GenerateSearchBase(bits, context);
+ BigInteger curVal = GenerateSearchBase (bits, Context);
- const uint primeProd1 = 3u * 5u * 7u * 11u * 13u * 17u * 19u * 23u * 29u;
+ const uint primeProd1 = 3u* 5u * 7u * 11u * 13u * 17u * 19u * 23u * 29u;
uint pMod1 = curVal % primeProd1;
int DivisionBound = TrialDivisionBounds;
uint[] SmallPrimes = BigInteger.smallPrimes;
+ PrimalityTest PostTrialDivisionTest = this.PrimalityTest;
//
// STEP 2. Search for primes
//
- while (true)
- {
+ while (true) {
//
// STEP 2.1 Sieve out numbers divisible by the first 9 primes
//
- if (pMod1 % 3 == 0)
- goto biNotPrime;
- if (pMod1 % 5 == 0)
- goto biNotPrime;
- if (pMod1 % 7 == 0)
- goto biNotPrime;
- if (pMod1 % 11 == 0)
- goto biNotPrime;
- if (pMod1 % 13 == 0)
- goto biNotPrime;
- if (pMod1 % 17 == 0)
- goto biNotPrime;
- if (pMod1 % 19 == 0)
- goto biNotPrime;
- if (pMod1 % 23 == 0)
- goto biNotPrime;
- if (pMod1 % 29 == 0)
- goto biNotPrime;
+ if (pMod1 % 3 == 0) goto biNotPrime;
+ if (pMod1 % 5 == 0) goto biNotPrime;
+ if (pMod1 % 7 == 0) goto biNotPrime;
+ if (pMod1 % 11 == 0) goto biNotPrime;
+ if (pMod1 % 13 == 0) goto biNotPrime;
+ if (pMod1 % 17 == 0) goto biNotPrime;
+ if (pMod1 % 19 == 0) goto biNotPrime;
+ if (pMod1 % 23 == 0) goto biNotPrime;
+ if (pMod1 % 29 == 0) goto biNotPrime;
//
// STEP 2.2 Sieve out all numbers divisible by the primes <= DivisionBound
//
- for (int p = 10; p < SmallPrimes.Length && SmallPrimes[p] <= DivisionBound; p++)
- {
- if (curVal % SmallPrimes[p] == 0)
+ for (int p = 9; p < SmallPrimes.Length && SmallPrimes [p] <= DivisionBound; p++) {
+ if (curVal % SmallPrimes [p] == 0)
goto biNotPrime;
}
//
// STEP 2.3 Is the potential prime acceptable?
//
- if (!IsPrimeAcceptable(curVal, context))
- goto biNotPrime;
+ if (!IsPrimeAcceptable (curVal, Context)) goto biNotPrime;
//
// STEP 2.4 Filter out all primes that pass this step with a primality test
//
- if (PrimalityTest(curVal, Confidence))
- return curVal;
+ if (PrimalityTest (curVal, Confidence)) return curVal;
+
//
- // STEP 2.4
- //
+ // STEP 2.4
+ //
biNotPrime:
pMod1 += 2;
- if (pMod1 >= primeProd1)
- pMod1 -= primeProd1;
- curVal.Incr2();
+ if (pMod1 >= primeProd1) pMod1 -= primeProd1;
+ curVal.Incr2 ();
}
}
- protected virtual bool IsPrimeAcceptable(BigInteger bi, object context)
+ protected virtual bool IsPrimeAcceptable (BigInteger bi, object Context)
{
return true;
}