diff options
Diffstat (limited to 'core/src/main/java/org/bouncycastle/util/BigIntegers.java')
-rw-r--r-- | core/src/main/java/org/bouncycastle/util/BigIntegers.java | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/util/BigIntegers.java b/core/src/main/java/org/bouncycastle/util/BigIntegers.java new file mode 100644 index 00000000..e2fe590a --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/BigIntegers.java @@ -0,0 +1,123 @@ +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); + } +} |