BigIntegers.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.util;
2
3import java.math.BigInteger;
4import java.security.SecureRandom;
5
6/**
7 * BigInteger utilities.
8 */
9public final class BigIntegers
10{
11    private static final int MAX_ITERATIONS = 1000;
12    private static final BigInteger ZERO = BigInteger.valueOf(0);
13
14    /**
15     * Return the passed in value as an unsigned byte array.
16     *
17     * @param value value to be converted.
18     * @return a byte array without a leading zero byte if present in the signed encoding.
19     */
20    public static byte[] asUnsignedByteArray(
21        BigInteger value)
22    {
23        byte[] bytes = value.toByteArray();
24
25        if (bytes[0] == 0)
26        {
27            byte[] tmp = new byte[bytes.length - 1];
28
29            System.arraycopy(bytes, 1, tmp, 0, tmp.length);
30
31            return tmp;
32        }
33
34        return bytes;
35    }
36
37    /**
38     * Return a random BigInteger not less than 'min' and not greater than 'max'
39     *
40     * @param min the least value that may be generated
41     * @param max the greatest value that may be generated
42     * @param random the source of randomness
43     * @return a random BigInteger value in the range [min,max]
44     */
45    public static BigInteger createRandomInRange(
46        BigInteger      min,
47        BigInteger      max,
48        SecureRandom    random)
49    {
50        int cmp = min.compareTo(max);
51        if (cmp >= 0)
52        {
53            if (cmp > 0)
54            {
55                throw new IllegalArgumentException("'min' may not be greater than 'max'");
56            }
57
58            return min;
59        }
60
61        if (min.bitLength() > max.bitLength() / 2)
62        {
63            return createRandomInRange(ZERO, max.subtract(min), random).add(min);
64        }
65
66        for (int i = 0; i < MAX_ITERATIONS; ++i)
67        {
68            BigInteger x = new BigInteger(max.bitLength(), random);
69            if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
70            {
71                return x;
72            }
73        }
74
75        // fall back to a faster (restricted) method
76        return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
77    }
78}
79