summary refs log tree commit diff
path: root/Crypto/src/util/BigIntegers.cs
blob: df82e1f22adcb3223691e1c103b36006f2999eec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System;

using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;

namespace Org.BouncyCastle.Utilities
{
	/**
	 * BigInteger utilities.
	 */
	public sealed class BigIntegers
	{
		private const int MaxIterations = 1000;

		private BigIntegers()
		{
		}

		/**
		* Return the passed in value as an unsigned byte array.
		*
		* @param value value to be converted.
		* @return a byte array without a leading zero byte if present in the signed encoding.
		*/
		public static byte[] AsUnsignedByteArray(
			BigInteger n)
		{
			return n.ToByteArrayUnsigned();
		}

		/**
		* Return a random BigInteger not less than 'min' and not greater than 'max'
		* 
		* @param min the least value that may be generated
		* @param max the greatest value that may be generated
		* @param random the source of randomness
		* @return a random BigInteger value in the range [min,max]
		*/
		public static BigInteger CreateRandomInRange(
			BigInteger		min,
			BigInteger		max,
			// TODO Should have been just Random class
			SecureRandom	random)
		{
			int cmp = min.CompareTo(max);
			if (cmp >= 0)
			{
				if (cmp > 0)
					throw new ArgumentException("'min' may not be greater than 'max'");

				return min;
			}

			if (min.BitLength > max.BitLength / 2)
			{
				return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
			}

			for (int i = 0; i < MaxIterations; ++i)
			{
				BigInteger x = new BigInteger(max.BitLength, random);
				if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
				{
					return x;
				}
			}

			// fall back to a faster (restricted) method
			return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
		}
	}
}