package com.beowulfe.hap.impl.pairing;
import java.math.BigInteger;
import java.security.SecureRandom;
/**
* This class is modified from the nimbus SRP library to provide methods that are compatible
* with some pecularities of Homekit. Namely, the need for a 3072 bit private value
*
* @author Vladimir Dzhuvinov
*/
public class HomekitSRP6Routines {
public static BigInteger generatePrivateValue(BigInteger N, SecureRandom random) {
final int minBits = Math.min(3072, N.bitLength() / 2);
BigInteger min = BigInteger.ONE.shiftLeft(minBits - 1);
BigInteger max = N.subtract(BigInteger.ONE);
return createRandomBigIntegerInRange(min, max, random);
}
/**
* Returns a random big integer in the specified range [min, max].
*
* @param min The least value that may be generated. Must not be
* {@code null}.
* @param max The greatest value that may be generated. Must not be
* {@code null}.
* @param random Source of randomness. Must not be {@code null}.
*
* @return A random big integer in the range [min, max].
*/
protected static BigInteger createRandomBigIntegerInRange(final BigInteger min,
final BigInteger max,
final SecureRandom random) {
final 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 createRandomBigIntegerInRange(BigInteger.ZERO, max.subtract(min), random).add(min);
final int MAX_ITERATIONS = 1000;
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);
}
}