114 lines
3.4 KiB
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;
|
|
}
|
|
}
|