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