Overgram/lib/src/main/java/io/github/lonamiwebs/overgram/utils/Utils.java

114 lines
3.4 KiB
Java

package io.github.lonamiwebs.overgram.utils;
import javafx.util.Pair;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class Utils {
private static MessageDigest sha1;
private static SecureRandom random;
static {
random = new SecureRandom();
try {
sha1 = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ignored) {
}
}
public static BigInteger randomBigInteger(final BigInteger max) {
BigInteger result;
do {
result = new BigInteger(max.bitLength(), random);
} while (result.compareTo(max) >= 0);
return result;
}
public static byte[] randomBytes(final int size) {
final byte[] result = new byte[size];
random.nextBytes(result);
return result;
}
// Note that this reverses IN PLACE and returns the same pointer
public static byte[] reversed(final byte[] bytes) {
for (int i = bytes.length / 2; i-- != 0; ) {
final byte temp = bytes[i];
bytes[i] = bytes[bytes.length - i - 1];
bytes[bytes.length - i - 1] = temp;
}
return bytes;
}
public static Pair<BigInteger, BigInteger> factorize(final BigInteger pq) {
final BigInteger two = new BigInteger("2");
if (pq.mod(two).equals(BigInteger.ZERO)) {
return new Pair<>(two, pq.divide(two));
}
BigInteger y = BigInteger.ONE.add(randomBigInteger(pq.subtract(two)));
BigInteger c = BigInteger.ONE.add(randomBigInteger(pq.subtract(two)));
BigInteger m = BigInteger.ONE.add(randomBigInteger(pq.subtract(two)));
BigInteger g = BigInteger.ONE;
BigInteger r = BigInteger.ONE;
BigInteger q = BigInteger.ONE;
BigInteger x = BigInteger.ZERO;
BigInteger ys = BigInteger.ZERO;
BigInteger countDown;
while (g.equals(BigInteger.ONE)) {
x = y;
countDown = r;
while (!countDown.equals(BigInteger.ZERO)) {
countDown = countDown.subtract(BigInteger.ONE);
y = (y.modPow(two, pq).add(c)).mod(pq);
}
BigInteger k = BigInteger.ZERO;
while (k.compareTo(r) < 0 && g.equals(BigInteger.ONE)) {
ys = y;
countDown = m.min(r.subtract(k));
while (!countDown.equals(BigInteger.ZERO)) {
countDown = countDown.subtract(BigInteger.ONE);
y = y.modPow(two, pq).add(c).mod(pq);
q = q.multiply(x.subtract(y).abs()).mod(pq);
}
g = q.gcd(pq);
k = k.add(m);
}
r = r.multiply(two);
}
if (g.equals(pq)) {
do {
ys = ys.modPow(two, pq).add(c).mod(pq);
g = x.subtract(ys).abs().gcd(pq);
} while (g.compareTo(BigInteger.ONE) <= 0);
}
x = g;
y = pq.divide(g);
return new Pair<>(x.min(y), x.max(y));
}
public static byte[] sha1digest(final byte[] data) throws SecurityException {
if (sha1 == null) {
throw new SecurityException("SHA-1 is required but not available");
}
final byte[] result = sha1.digest(data);
sha1.reset();
return result;
}
}