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