package org.bouncycastle.util;

import java.math.BigInteger;
import java.security.SecureRandom;

/**
 * BigInteger utilities.
 */
public final class 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 value)
    {
        byte[] bytes = value.toByteArray();
        
        if (bytes[0] == 0)
        {
            byte[] tmp = new byte[bytes.length - 1];
            
            System.arraycopy(bytes, 1, tmp, 0, tmp.length);
            
            return tmp;
        }
        
        return bytes;
    }

    /**
     * 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,
        SecureRandom    random)
    {
        BigInteger x;
        do
        {
            x = new BigInteger(max.bitLength(), random);
        }
        while (x.compareTo(min) < 0 || x.compareTo(max) > 0);
        return x;
    }
}

@@ -156,16 +156,135 @@
 egers%0A%7B%0A
+    private static final int MAX_ITERATIONS = 1000;%0A    private static final BigInteger ZERO = BigInteger.valueOf(0);%0A%0A
     /**%0A
@@ -1357,36 +1357,432 @@
     
-    BigInteger x;%0A        do
+%09int cmp = min.compareTo(max);%0A        if (cmp %3E= 0)%0A        %7B%0A        %09if (cmp %3E 0)%0A        %09%7B%0A            %09throw new IllegalArgumentException(%22'min' may not be greater than 'max'%22);%0A        %09%7D%0A%0A%09%09%09return min;%0A        %7D%0A%0A        if (min.bitLength() %3E max.bitLength() / 2)%0A        %7B%0A            return createRandomInRange(ZERO, max.subtract(min), random).add(min);%0A        %7D%0A%0A        for (int i = 0; i %3C MAX_ITERATIONS; ++i)
 %0A   
@@ -1800,16 +1800,27 @@
         
+BigInteger 
 x = new 
@@ -1868,23 +1868,14 @@
     
-%7D%0A        while
+    if
  (x.
@@ -1893,14 +1893,15 @@
 in) 
-%3C 0 %7C%7C
+%3E= 0 &&
  x.c
@@ -1918,30 +1918,213 @@
 ax) 
-%3E 0);%0A        return x
+%3C= 0)%0A            %7B%0A                return x;%0A            %7D%0A        %7D%0A%0A        // fall back to a faster (restricted) method%0A        return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min)
 ;%0A  

Add iteration limit, argument checks and improved handling of small ranges to createRandomInRange