BigIntegers.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
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 the passed in value as an unsigned byte array.
39     *
40     * @param value value to be converted.
41     * @return a byte array without a leading zero byte if present in the signed encoding.
42     */
43    public static byte[] asUnsignedByteArray(int length, BigInteger value)
44    {
45        byte[] bytes = value.toByteArray();
46        if (bytes.length == length)
47        {
48            return bytes;
49        }
50
51        int start = bytes[0] == 0 ? 1 : 0;
52        int count = bytes.length - start;
53
54        if (count > length)
55        {
56            throw new IllegalArgumentException("standard length exceeded for value");
57        }
58
59        byte[] tmp = new byte[length];
60        System.arraycopy(bytes, start, tmp, tmp.length - count, count);
61        return tmp;
62    }
63
64    /**
65     * Return a random BigInteger not less than 'min' and not greater than 'max'
66     *
67     * @param min the least value that may be generated
68     * @param max the greatest value that may be generated
69     * @param random the source of randomness
70     * @return a random BigInteger value in the range [min,max]
71     */
72    public static BigInteger createRandomInRange(
73        BigInteger      min,
74        BigInteger      max,
75        SecureRandom    random)
76    {
77        int cmp = min.compareTo(max);
78        if (cmp >= 0)
79        {
80            if (cmp > 0)
81            {
82                throw new IllegalArgumentException("'min' may not be greater than 'max'");
83            }
84
85            return min;
86        }
87
88        if (min.bitLength() > max.bitLength() / 2)
89        {
90            return createRandomInRange(ZERO, max.subtract(min), random).add(min);
91        }
92
93        for (int i = 0; i < MAX_ITERATIONS; ++i)
94        {
95            BigInteger x = new BigInteger(max.bitLength(), random);
96            if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
97            {
98                return x;
99            }
100        }
101
102        // fall back to a faster (restricted) method
103        return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
104    }
105
106    public static BigInteger fromUnsignedByteArray(byte[] buf)
107    {
108        return new BigInteger(1, buf);
109    }
110
111    public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length)
112    {
113        byte[] mag = buf;
114        if (off != 0 || length != buf.length)
115        {
116            mag = new byte[length];
117            System.arraycopy(buf, off, mag, 0, length);
118        }
119        return new BigInteger(1, mag);
120    }
121}
122