/**
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
*
* Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH
*
* Licensed under Apache License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
package de.rub.nds.tlsattacker.util;
import java.math.BigInteger;
import java.util.List;
/**
*
* @author Juraj Somorovsky <juraj.somorovsky@rub.de>
*/
public class MathHelper {
private MathHelper() {
}
public static BigInteger intfloordiv(BigInteger c, BigInteger d) {
return (c.subtract(c.mod(d))).divide(d);
}
public static BigInteger intceildiv(BigInteger c, BigInteger d) {
if (c.mod(d).equals(BigInteger.ZERO)) {
return intfloordiv(c, d);
} else {
return intfloordiv(c, d).add(BigInteger.ONE);
}
}
public static int intfloordiv(int c, int d) {
return (c - (c % d)) / d;
}
public static int intceildiv(int c, int d) {
if ((c % d) == 0) {
return intfloordiv(c, d);
} else {
return intfloordiv(c, d) + 1;
}
}
/**
*
* @param u
* @param v
* @return (c,r,s) such that c = r u + s v
*/
public static BigIntegerTripple extendedEuclid(BigInteger u, BigInteger v) {
BigInteger r = BigInteger.ONE;
BigInteger s = BigInteger.ZERO;
BigInteger c = u;
BigInteger v1 = BigInteger.ZERO;
BigInteger v2 = BigInteger.ONE;
BigInteger v3 = v;
while (!v3.equals(BigInteger.ZERO)) {
BigInteger q = c.divide(v3);
BigInteger t1 = r.subtract(q.multiply(v1));
BigInteger t2 = s.subtract(q.multiply(v2));
BigInteger t3 = c.subtract(q.multiply(v3));
r = v1;
s = v2;
c = v3;
v1 = t1;
v2 = t2;
v3 = t3;
}
return new BigIntegerTripple(c, r, s);
}
public static BigInteger gcd(BigInteger u, BigInteger v) {
return extendedEuclid(u, v).a;
}
public static BigInteger inverseMod(BigInteger a, BigInteger p) {
if (!gcd(a, p).equals(BigInteger.ONE)) {
throw new RuntimeException("does not exist");
}
BigInteger b = extendedEuclid(a, p).b;
while (b.compareTo(BigInteger.ZERO) < 0) {
b = b.add(p);
}
return b;
}
/**
* Computes Chinese Reminder Theorem: x == congs[i] mod moduli[i]
*
* @param congs
* @param moduli
* @return
*/
public static BigInteger CRT(BigInteger[] congs, BigInteger[] moduli) {
BigInteger prodModuli = BigInteger.ONE;
for (BigInteger mod : moduli) {
prodModuli = prodModuli.multiply(mod);
}
BigInteger[] M = new BigInteger[moduli.length];
for (int i = 0; i < moduli.length; i++) {
M[i] = prodModuli.divide(moduli[i]);
}
BigInteger retval = BigInteger.ZERO;
for (int i = 0; i < moduli.length; i++) {
// get s value from EEA
BigInteger tmp = extendedEuclid(moduli[i], M[i]).c;
retval = retval.add(congs[i].multiply(tmp).multiply(M[i]).mod(prodModuli));
}
return retval.mod(prodModuli);
}
/**
* Computes Chinese Reminder Theorem: x == congs[i] mod moduli[i]
*
* @param congs
* @param moduli
* @return
*/
public static BigInteger CRT(List<BigInteger> congs, List<BigInteger> moduli) {
BigInteger[] cs = ArrayConverter.convertListToArray(congs);
BigInteger[] ms = ArrayConverter.convertListToArray(moduli);
return CRT(cs, ms);
}
/**
* Computes BigInteger sqrt root of a number (floor value). From:
* http://stackoverflow
* .com/questions/4407839/how-can-i-find-the-square-root-
* of-a-java-biginteger
*
* @param x
* @return
* @throws IllegalArgumentException
*/
public static BigInteger bigIntSqRootFloor(BigInteger x) throws IllegalArgumentException {
if (x.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("Negative argument.");
}
// square roots of 0 and 1 are trivial and
// y == 0 will cause a divide-by-zero exception
if (x.equals(BigInteger.ZERO) || x.equals(BigInteger.ONE)) {
return x;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger y;
// starting with y = x / 2 avoids magnitude issues with x squared
for (y = x.divide(two); y.compareTo(x.divide(y)) > 0; y = ((x.divide(y)).add(y)).divide(two))
;
return y;
} // end bigIntSqRootFloor
/**
* Computes BigInteger sqrt root of a number (ceil value). From:
* http://stackoverflow
* .com/questions/4407839/how-can-i-find-the-square-root-
* of-a-java-biginteger
*
* @param x
* @return
* @throws IllegalArgumentException
*/
public static BigInteger bigIntSqRootCeil(BigInteger x) throws IllegalArgumentException {
if (x.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("Negative argument.");
}
// square roots of 0 and 1 are trivial and
// y == 0 will cause a divide-by-zero exception
if (x.equals(BigInteger.ZERO) || x.equals(BigInteger.ONE)) {
return x;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger y;
// starting with y = x / 2 avoids magnitude issues with x squared
for (y = x.divide(two); y.compareTo(x.divide(y)) > 0; y = ((x.divide(y)).add(y)).divide(two))
;
if (x.compareTo(y.multiply(y)) == 0) {
return y;
} else {
return y.add(BigInteger.ONE);
}
}
public static class BigIntegerTripple {
public final BigInteger a;
public final BigInteger b;
public final BigInteger c;
public BigIntegerTripple(BigInteger a, BigInteger b, BigInteger c) {
this.a = a;
this.b = b;
this.c = c;
}
}
}