package org.bouncycastle.util;

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

/**
 * BigInteger utilities.
 */
public final class BigIntegers
{
    private static final int MAX_ITERATIONS = 1000;
    private static final BigInteger ZERO = BigInteger.valueOf(0);

    /**
     * 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 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(
        int        length,
        BigInteger value)
    {
        byte[] bytes = value.toByteArray();

        if (bytes[0] == 0)
        {
            if (bytes.length - 1 > length)
            {
                throw new IllegalArgumentException("standard length exceeded for value");
            }

            byte[] tmp = new byte[length];

            System.arraycopy(bytes, 1, tmp, tmp.length - (bytes.length - 1), bytes.length - 1);

            return tmp;
        }
        else
        {
            if (bytes.length == length)
            {
                return bytes;
            }

            if (bytes.length > length)
            {
                throw new IllegalArgumentException("standard length exceeded for value");
            }

            byte[] tmp = new byte[length];

            System.arraycopy(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,
        SecureRandom    random)
    {
        int cmp = min.compareTo(max);
        if (cmp >= 0)
        {
            if (cmp > 0)
            {
                throw new IllegalArgumentException("'min' may not be greater than 'max'");
            }

            return min;
        }

        if (min.bitLength() > max.bitLength() / 2)
        {
            return createRandomInRange(ZERO, max.subtract(min), random).add(min);
        }

        for (int i = 0; i < MAX_ITERATIONS; ++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);
    }

    public static BigInteger fromUnsignedByteArray(byte[] buf)
    {
        return new BigInteger(1, buf);
    }

    public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length)
    {
        byte[] mag = buf;
        if (off != 0 || length != buf.length)
        {
            mag = new byte[length];
            System.arraycopy(buf, off, mag, 0, length);
        }
        return new BigInteger(1, mag);
    }
}

@@ -1140,43 +1140,19 @@
 ray(
-%0A        int        length,%0A       
+int length,
  Big
@@ -1220,50 +1220,8 @@
 ();%0A
-%0A        if (bytes%5B0%5D == 0)%0A        %7B%0A    
     
@@ -1245,13 +1245,10 @@
 gth 
-- 1 %3E
+==
  len
@@ -1252,36 +1252,32 @@
 length)%0A        
-    
 %7B%0A              
@@ -1278,407 +1278,127 @@
     
- 
-   throw new IllegalArgumentException(%22standard length exceeded for value%22);%0A            %7D%0A%0A            byte%5B%5D tmp = new byte%5Blength%5D;%0A%0A            System.arraycopy(bytes, 1, tmp, tmp.length - (bytes.length - 1), bytes.length - 1);%0A%0A            return tmp;%0A        %7D%0A        else%0A        %7B%0A            if (bytes.length == length)%0A            %7B%0A                return bytes;%0A            %7D%0A%0A 
+return bytes;%0A        %7D%0A%0A        int start = bytes%5B0%5D == 0 ? 1 : 0;%0A        int count = bytes.length - start;%0A%0A
         
    i
@@ -1393,35 +1393,25 @@
         
-   
 if (
-bytes.length
+count
  %3E lengt
@@ -1417,33 +1417,26 @@
 th)%0A        
-    %7B%0A   
+%7B%0A
             
@@ -1427,33 +1427,32 @@
   %7B%0A            
- 
 throw new Illega
@@ -1517,34 +1517,27 @@
         
-    %7D%0A%0A   
+%7D%0A%0A
         
  byte%5B%5D 
@@ -1520,33 +1520,32 @@
      %7D%0A%0A        
- 
 byte%5B%5D tmp = new
@@ -1559,27 +1559,24 @@
 ength%5D;%0A
-%0A  
         
   System
@@ -1559,34 +1559,32 @@
 ength%5D;%0A        
-  
 System.arraycopy
@@ -1591,17 +1591,21 @@
 (bytes, 
-0
+start
 , tmp, t
@@ -1620,42 +1620,23 @@
 h - 
-bytes.length, bytes.length);%0A%0A    
+count, count);%0A
     
@@ -1647,34 +1647,24 @@
 return tmp;%0A
-        %7D%0A
     %7D%0A%0A    /

Simplify BigIntegers.asUnsignedByteArray implementation