Home | History | Annotate | Download | only in util
      1 package org.bouncycastle.util;
      2 
      3 import java.math.BigInteger;
      4 import java.security.SecureRandom;
      5 
      6 /**
      7  * BigInteger utilities.
      8  */
      9 public 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