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 */ asUnsignedByteArray( BigInteger value)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 */ asUnsignedByteArray(int length, BigInteger value)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 */ createRandomInRange( BigInteger min, BigInteger max, SecureRandom random)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 fromUnsignedByteArray(byte[] buf)106 public static BigInteger fromUnsignedByteArray(byte[] buf) 107 { 108 return new BigInteger(1, buf); 109 } 110 fromUnsignedByteArray(byte[] buf, int off, int length)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