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