summaryrefslogtreecommitdiff
path: root/repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java
diff options
context:
space:
mode:
Diffstat (limited to 'repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java')
-rw-r--r--repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java149
1 files changed, 140 insertions, 9 deletions
diff --git a/repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java b/repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java
index 93e1a779..8b06237d 100644
--- a/repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java
+++ b/repackaged/bcprov/src/main/java/com/android/org/bouncycastle/util/BigIntegers.java
@@ -4,6 +4,9 @@ package com.android.org.bouncycastle.util;
import java.math.BigInteger;
import java.security.SecureRandom;
+import com.android.org.bouncycastle.math.raw.Mod;
+import com.android.org.bouncycastle.math.raw.Nat;
+
/**
* BigInteger utilities.
* @hide This class is not part of the Android public SDK API
@@ -12,8 +15,8 @@ public final class BigIntegers
{
public static final BigInteger ZERO = BigInteger.valueOf(0);
public static final BigInteger ONE = BigInteger.valueOf(1);
+ public static final BigInteger TWO = BigInteger.valueOf(2);
- private static final BigInteger TWO = BigInteger.valueOf(2);
private static final BigInteger THREE = BigInteger.valueOf(3);
private static final int MAX_ITERATIONS = 1000;
@@ -21,7 +24,7 @@ public final class BigIntegers
/**
* Return the passed in value as an unsigned byte array.
*
- * @param value value to be converted.
+ * @param value the value to be converted.
* @return a byte array without a leading zero byte if present in the signed encoding.
*/
public static byte[] asUnsignedByteArray(
@@ -29,7 +32,7 @@ public final class BigIntegers
{
byte[] bytes = value.toByteArray();
- if (bytes[0] == 0)
+ if (bytes[0] == 0 && bytes.length != 1)
{
byte[] tmp = new byte[bytes.length - 1];
@@ -42,10 +45,14 @@ public final class BigIntegers
}
/**
- * Return the passed in value as an unsigned byte array.
+ * Return the passed in value as an unsigned byte array of the specified length, padded with
+ * leading zeros as necessary..
*
- * @param value value to be converted.
- * @return a byte array without a leading zero byte if present in the signed encoding.
+ * @param length
+ * the fixed length of the result
+ * @param value
+ * the value to be converted.
+ * @return a byte array padded to a fixed length with leading zeros.
*/
public static byte[] asUnsignedByteArray(int length, BigInteger value)
{
@@ -55,7 +62,7 @@ public final class BigIntegers
return bytes;
}
- int start = bytes[0] == 0 ? 1 : 0;
+ int start = (bytes[0] == 0 && bytes.length != 1) ? 1 : 0;
int count = bytes.length - start;
if (count > length)
@@ -69,6 +76,41 @@ public final class BigIntegers
}
/**
+ * Write the passed in value as unsigned bytes to the specified buffer range, padded with
+ * leading zeros as necessary.
+ *
+ * @param value
+ * the value to be converted.
+ * @param buf
+ * the buffer to which the value is written.
+ * @param off
+ * the start offset in array <code>buf</code> at which the data is written.
+ * @param len
+ * the fixed length of data written (possibly padded with leading zeros).
+ */
+ public static void asUnsignedByteArray(BigInteger value, byte[] buf, int off, int len)
+ {
+ byte[] bytes = value.toByteArray();
+ if (bytes.length == len)
+ {
+ System.arraycopy(bytes, 0, buf, off, len);
+ return;
+ }
+
+ int start = (bytes[0] == 0 && bytes.length != 1) ? 1 : 0;
+ int count = bytes.length - start;
+
+ if (count > len)
+ {
+ throw new IllegalArgumentException("standard length exceeded for value");
+ }
+
+ int padLen = len - count;
+ Arrays.fill(buf, off, off + padLen, (byte)0x00);
+ System.arraycopy(bytes, start, buf, off + padLen, count);
+ }
+
+ /**
* Return a random BigInteger not less than 'min' and not greater than 'max'
*
* @param min the least value that may be generated
@@ -126,8 +168,97 @@ public final class BigIntegers
return new BigInteger(1, mag);
}
+ public static int intValueExact(BigInteger x)
+ {
+ // Since Java 1.8 could use BigInteger.intValueExact instead
+ if (x.bitLength() > 31)
+ {
+ throw new ArithmeticException("BigInteger out of int range");
+ }
+
+ return x.intValue();
+ }
+
+ public static long longValueExact(BigInteger x)
+ {
+ // Since Java 1.8 could use BigInteger.longValueExact instead
+ if (x.bitLength() > 63)
+ {
+ throw new ArithmeticException("BigInteger out of long range");
+ }
+
+ return x.longValue();
+ }
+
+ public static BigInteger modOddInverse(BigInteger M, BigInteger X)
+ {
+ if (!M.testBit(0))
+ {
+ throw new IllegalArgumentException("'M' must be odd");
+ }
+ if (M.signum() != 1)
+ {
+ throw new ArithmeticException("BigInteger: modulus not positive");
+ }
+ if (X.signum() < 0 || X.compareTo(M) >= 0)
+ {
+ X = X.mod(M);
+ }
+
+ int bits = M.bitLength();
+ int[] m = Nat.fromBigInteger(bits, M);
+ int[] x = Nat.fromBigInteger(bits, X);
+ int len = m.length;
+ int[] z = Nat.create(len);
+ if (0 == Mod.modOddInverse(m, x, z))
+ {
+ throw new ArithmeticException("BigInteger not invertible.");
+ }
+ return Nat.toBigInteger(len, z);
+ }
+
+ public static BigInteger modOddInverseVar(BigInteger M, BigInteger X)
+ {
+ if (!M.testBit(0))
+ {
+ throw new IllegalArgumentException("'M' must be odd");
+ }
+ if (M.signum() != 1)
+ {
+ throw new ArithmeticException("BigInteger: modulus not positive");
+ }
+ if (M.equals(ONE))
+ {
+ return ZERO;
+ }
+ if (X.signum() < 0 || X.compareTo(M) >= 0)
+ {
+ X = X.mod(M);
+ }
+ if (X.equals(ONE))
+ {
+ return ONE;
+ }
+
+ int bits = M.bitLength();
+ int[] m = Nat.fromBigInteger(bits, M);
+ int[] x = Nat.fromBigInteger(bits, X);
+ int len = m.length;
+ int[] z = Nat.create(len);
+ if (!Mod.modOddInverseVar(m, x, z))
+ {
+ throw new ArithmeticException("BigInteger not invertible.");
+ }
+ return Nat.toBigInteger(len, z);
+ }
+
public static int getUnsignedByteLength(BigInteger n)
{
+ if (n.equals(ZERO))
+ {
+ return 1;
+ }
+
return (n.bitLength() + 7) / 8;
}
@@ -150,7 +281,7 @@ public final class BigIntegers
+ "ce86165a978d719ebf647f362d33fca29cd179fb42401cbaf3df0c614056f9c8"
+ "f3cfd51e474afb6bc6974f78db8aba8e9e517fded658591ab7502bd41849462f",
16);
- private static final int SQR_MAX_SMALL = 20; // bitlength of 743 * 743
+ private static final int MAX_SMALL = BigInteger.valueOf(743).bitLength(); // bitlength of 743 * 743
/**
* Return a prime number candidate of the specified bit length.
@@ -185,7 +316,7 @@ public final class BigIntegers
base[base.length - 1] |= 0x01;
rv = new BigInteger(1, base);
- if (bitLength > SQR_MAX_SMALL)
+ if (bitLength > MAX_SMALL)
{
while (!rv.gcd(SMALL_PRIMES_PRODUCT).equals(ONE))
{