BigIntegers.cs
2.83 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Utilities
{
/**
* BigInteger utilities.
*/
public abstract class BigIntegers
{
private const int MaxIterations = 1000;
/**
* 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 the passed in value as an unsigned byte array of specified length, zero-extended as necessary.
*
* @param length desired length of result array.
* @param n value to be converted.
* @return a byte array of specified length, with leading zeroes as necessary given the size of n.
*/
public static byte[] AsUnsignedByteArray(int length, BigInteger n)
{
byte[] bytes = n.ToByteArrayUnsigned();
if (bytes.Length > length)
throw new ArgumentException("standard length exceeded", "n");
if (bytes.Length == length)
return bytes;
byte[] tmp = new byte[length];
Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
return tmp;
}
/**
* 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);
}
}
}