Java Fermat Factorisation algorithm BigInteger not working - java

I'm implementing Fermat Factorization algorithm using BigInteger so I can factor. But at the moment, the code is not working; it hangs for some reason. Could someone direct me to where the issue is, or let me know if my algorithm is incorrect? BigInteger makes life difficult, so I had to look for a square root method.
import java.math.BigInteger;
import java.util.Scanner;
public class Fermat
{
/** Fermat factor **/
public void FermatFactor(BigInteger N)
{
BigInteger a = sqrt(N);
BigInteger b2 = a.multiply(a).subtract(N);
while (!isSquare(b2)) {
a = a.add(a);
b2 = a.multiply(a).subtract(N);
}
BigInteger r1 = a.subtract(sqrt(b2));
BigInteger r2 = N.divide(r1);
display(r1, r2);
}
/** function to display roots **/
public void display(BigInteger r1, BigInteger r2) {
System.out.println("\nRoots = "+ r1 +" , "+ r2);
}
/** function to check if N is a perfect square or not **/
public boolean isSquare(BigInteger N) {
BigInteger ONE = new BigInteger("1");
BigInteger sqr = sqrt(N);
if (sqr.multiply(sqr) == N || (sqr.add(ONE)).multiply(sqr.add(ONE)) == N)
return true;
return false;
}
public static BigInteger sqrt(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 == BigInteger.ZERO || x == 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);
}
} // end bigIntSqRootCeil
/** main method **/
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Fermat Factorization Test\n");
System.out.println("Enter odd number");
BigInteger N = scan.nextBigInteger();
Fermat ff = new Fermat();
ff.FermatFactor(N);
scan.close();
}
}
I know I have a lot of mistakes, but any help is appreciated. Thanks.

Your "for" loop :
for (y = x.divide(two);
y.compareTo(x.divide(y)) > 0;
y = ((x.divide(y)).add(y)).divide(two));
does not terminate. Perhaps you could keep track of the values of the variable 'y', to guess when you have to stop.
Edit : that was wrong (see comments). The problem is in the line
a = a.add(a)
inside procedure FermatFactor. It should rather be
a = a.add(ONE)
In my machine I also had troubles with testing equalities using 'A == B'. The method 'A.equals(B)' fixed it.

Related

How to quickly break RSA encryption with very large numbers in Java with the Modulus and Exponent/Public Key

I was given a task to make a program to break the RSA encryption with the modulus and public keys of both parties and the cipher text. I have found solutions that brute force to find the prime values that are multiplied for the modulus. However with the size of the numbers that I have to use, it doesn't seem like it can even finish processing.(the modulus is 30 digits long or so)
This is the example data we were given:
{
"alice": {
"modulus": "66056083785421544972111685239",
"publicKey": "38933338385103628492607145193"
},
"bob": {
"modulus": "71994651332404115788173195239",
"publicKey": "28763302913765661132800185637"
},
"cipherText": "5b8sot9g2168mp3nw51"
}
This is the solution I'm currently trying, using the Fermat algorithm to try and find the primes faster:
import java.math.BigInteger;
public class ferr
{
static BigInteger r1;
static BigInteger r2;
static BigInteger aliceModulus = new BigInteger("107182711767121947041078387099");
public static void main (){
System.out.println("running");
ferr x = new ferr();
x.fermat(aliceModulus);
}
public void fermat(BigInteger N)
{
BigInteger a = calcSQR(N);
BigInteger b2 = (a.multiply(a).subtract(N));
while(Square(b2) == false) {
a = a.add(BigInteger.valueOf(1));
b2 = (a.multiply(a).subtract(N));
} // end while
r1 = a.subtract(calcSQR(b2));
r2 = N.divide(r1);
System.out.println("Roots = ("+ r1 +") , ("+ r2 +")");
}
public boolean Square(BigInteger N)
{
BigInteger sqRoot = calcSQR(N);
if(sqRoot.multiply(sqRoot).equals(N)) {
return true;
} // end if
else {
return false;
} // end else
}
public BigInteger calcSQR(BigInteger N)
{
if(N == BigInteger.ZERO || N == BigInteger.ONE) {
return N;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger x;
// Starting with x = N/2 avoids magnitude issues with x squared
for(x = N.divide(two); x.compareTo(N.divide(x)) > 0; x = ((N.divide(x)).add(x)).divide(two)) {
if(N.compareTo(x.multiply(x)) == 0) {
return x;
} // end if
else {
return x.add(BigInteger.ONE);
} // end else
} // end for-loop
return null;
}
}
Is there any faster solution to break the encryption? I've left this program running for a few hours and it's still no where near the end.
As you noticed, Brute-Forcing the prime numbers is quite slow.
But there are easier ways.
Notice that you have two modulo, one for Bob, one for Alice.
A trivial shot is to calculate the greatest common divisor of both:
BigInteger bobM = new BigInteger("66056083785421544972111685239");
BigInteger aliceM = new BigInteger("71994651332404115788173195239");
System.out.println(bobM.gcd(aliceM));
This will output 535006138814359, which is one factor of both Bob and Alice.
It might be pure luck that this works here, or it could be crafted that way by your instructor.
Use a faster factorization method.
One of those is Pollard's Rho algorithm, which is quite easy to implement.
private static BigInteger pollardroh(BigInteger n, BigInteger x) {
BigInteger y = x;
BigInteger d = BigInteger.ONE;
while (d.equals(BigInteger.ONE)) {
x = x.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
y = y.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
y = y.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
d = x.subtract(y).abs().gcd(n);
}
return d;
}
Use it with a starting value of x = BigInteger.TWO.
This will run for ~ 1 minute on my machine, and output 134567897654321 for Alice's modulo.
In the end, here are the factorization of both Alice & Bob's modulo:
Bob:
p1: 535006138814359
p2: 123467898764321
Alice:
p1: 535006138814359
p2: 134567897654321
The second primes look a bit suspicions, and not randomly selected at all.

How can I turn this code from long into BigInteger

It is a code that gets prime numbers, I have made it as efficient as I could, but the problem is that I can't transform it to BigInteger, as long can't hold that much information; here the code:
public class p3{
static long perfectNumber;
static long mersenne;
public static void main(String[] args) {
long p = 2;
while (true) {
if( p % 2 == 0&&p!=2){
p++;
}
else{
if (isPrime(p) == true) {
mersenne = (long) (Math.pow(2, p) - 1);
if (isPrime(mersenne) == true) {
perfectNumber = (long) Math.pow(2, (p - 1)) * mersenne;
System.out.println(perfectNumber);
}
}
p+=1;
}
}
}
private static boolean isPrime(long testPrime) {
for (long i = 3; i < Math.sqrt(testPrime); i += 2) {
if (testPrime % i == 0) {
return false;
}
}
return true;
}
}
I've tried to use BigInteger but code is not working, as I can't use
BigInteger exponents with pow
You don't need to. The exponents don't need to be nearly as large as the mersenne primes and perfect numbers. They can have their own independent isPrime() test. In fact, they need to be int, instead of long, to satisfy BigInteger.pow().
Below is what you asked for, but may not be what you want. I doubt you'll get more then one additional perfect number beyond your original code due to time constraints which is why #WJS is pushing you in a different direction.
import java.math.BigInteger;
public class p3 {
static BigInteger TWO = new BigInteger("2");
static BigInteger THREE = new BigInteger("3");
public static void main(String[] args) {
int p = 2;
while (true) {
if (isPrime(p)) {
BigInteger mersenne = TWO.pow(p).subtract(BigInteger.ONE);
if (isPrime(mersenne)) {
System.out.println(TWO.pow(p - 1).multiply(mersenne));
}
}
p += (p == 2) ? 1 : 2;
}
}
private static boolean isPrime(BigInteger number) {
if (number.mod(TWO).equals(BigInteger.ZERO)) {
return number.equals(TWO);
}
for (BigInteger i = THREE; number.compareTo(i.multiply(i)) >= 0; i = i.add(TWO)) {
if (number.mod(i).equals(BigInteger.ZERO)) {
return false;
}
}
return true;
}
private static boolean isPrime(int number) {
if (number % 2 == 0) {
return number == 2;
}
for (int i = 3; number >= i * i; i += 2) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
OUTPUT
> java p3
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176
Your original code outputs 0 in place of the final (37 digit) number above. So the immediate issue really is that long can't hold enough information. But beyond this point, you simply can't calculate fast enough with the above algorithm.
If we do something simple-minded to my above code, like replace this line:
if (isPrime(mersenne)) {
with:
if (mersenne.isProbablePrime(10)) {
The code will spit out the first 20 perfect numbers before slowing to a crawl. Tune the certainty argument of isProbablePrime() as you see fit.

What does the method prod() do in this Java program?

public class Prod {
public static void main(String[] args) {
System.out.println(prod(1, 4));
}
public static int prod(int m, int n) {
if (m == n) {
return n;
} else {
int recurse = prod(m, n-1);
int result = n * recurse;
return result;
}
}
}
This is an exercise in the book I am stumped on. Why would the program not just recurse until the two numbers are equal and then return n ? Also, where it says,
int result = n * recurse;
How does it multiply int n by recurse which would be (int, int)? How can it multiply one integer by a set of two integers?
In what way am I misunderstanding this program?
EDIT: This is a different question because I am not using factorials
prod(x,y) is equivalent to y! when x=1.
If x is different from 1, then its doing recursive multiplication (y * (y- 1) * (y -2) .... ) until y = x.
Assuming y > x.
By the way, if x > y then prod() will crash.

Combinations with BigInteger in java

I am working on an assignment where I have to implement a recursive way to calculate the combination of two numbers. For example, 5C3 would be 10. That is, there are 10 combinations of 3 objects out of 5 total. However, I would like to implement a way to use the BigInteger class so I can calculate larger combinations, such is 2400 pick 3. For some reason, my code still returns a negative number, much like the behavior if it were to be regular integers. I've included my code below. Could someone please tell me where I am going wrong?
import java.math.BigInteger;
public class Combination {
public static BigInteger[][] memo = new BigInteger[3000][3000];
public static BigInteger choose(BigInteger n, BigInteger k) {
if (n.intValue() == 0 && k.intValue() > 0) {
return BigInteger.ZERO;
} else if (k.intValue() == 0 && n.intValue() >= 0) {
return BigInteger.ONE;
} else if (memo[n.intValue()][k.intValue()] != null) {
return memo[n.intValue()][k.intValue()];
} else {
memo[n.intValue()][k.intValue()] = choose(n.subtract(BigInteger.ONE), k.subtract(BigInteger.ONE)).add(choose(n.subtract(BigInteger.ONE), k));
}
return memo[n.intValue()][k.intValue()];
}
public static void main(String args[]) {
if (args.length < 1) {
System.out.println("Usage: java Combination <N> <K>");
System.exit(0);
}
int H = Integer.parseInt(args[0]);
int R = Integer.parseInt(args[1]);
BigInteger N = BigInteger.valueOf(H);
BigInteger K = BigInteger.valueOf(R);
System.out.println(choose(N, K).intValue());
}
}
System.out.println(choose(N, K).intValue());
should be
System.out.println(choose(N, K).toString());

Check if BigInteger is not a perfect square

I have a BigInteger value, let's say it is 282 and is inside the variable x. I now want to write a while loop that states:
while b2 isn't a perfect square:
a ← a + 1
b2 ← a*a - N
endwhile
How would I do such a thing using BigInteger?
EDIT: The purpose for this is so I can write this method. As the article states one must check if b2 is not square.
Compute the integer square root, then check that its square is your number. Here is my method of computing the square root using Heron's method:
private static final BigInteger TWO = BigInteger.valueOf(2);
/**
* Computes the integer square root of a number.
*
* #param n The number.
*
* #return The integer square root, i.e. the largest number whose square
* doesn't exceed n.
*/
public static BigInteger sqrt(BigInteger n)
{
if (n.signum() >= 0)
{
final int bitLength = n.bitLength();
BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
while (!isSqrt(n, root))
{
root = root.add(n.divide(root)).divide(TWO);
}
return root;
}
else
{
throw new ArithmeticException("square root of negative number");
}
}
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I found a sqrt method used here, and simplified the square test.
private static final BigInteger b100 = new BigInteger("100");
private static final boolean[] isSquareResidue;
static{
isSquareResidue = new boolean[100];
for(int i =0;i<100;i++){
isSquareResidue[(i*i)%100]=true;
}
}
public static boolean isSquare(final BigInteger r) {
final int y = (int) r.mod(b100).longValue();
boolean check = false;
if (isSquareResidue[y]) {
final BigInteger temp = sqrt(r);
if (r.compareTo(temp.pow(2)) == 0) {
check = true;
}
}
return check;
}
public static BigInteger sqrt(final BigInteger val) {
final BigInteger two = BigInteger.valueOf(2);
BigInteger a = BigInteger.ONE.shiftLeft(val.bitLength() / 2);
BigInteger b;
do {
b = val.divide(a);
a = (a.add(b)).divide(two);
} while (a.subtract(b).abs().compareTo(two) >= 0);
return a;
}
public static Boolean PerfectSQR(BigInteger A){BigInteger B=A.sqrt(), C=B.multiply(B);return (C.equals(A));}
DON'T use this...
BigInteger n = ...;
double n_as_double = n.doubleValue();
double n_sqrt = Math.sqrt(n_as_double);
BigInteger n_sqrt_as_int = new BigDecimal(n_sqrt).toBigInteger();
if (n_sqrt_as_int.pow(2).equals(n)) {
// number is perfect square
}
As Christian Semrau commented below - this doesn't work. I am sorry for posting incorrect answer.
using System.Numerics; // needed for BigInteger
/* Variables */
BigInteger a, b, b2, n, p, q;
int flag;
/* Assign Data */
n = 10147;
a = iSqrt(n);
/* Algorithm */
do
{ a = a + 1;
b2 = (a * a) – n;
b = iSqrt(b2);
flag = BigInteger.Compare(b * b, b2);
} while(flag != 0);
/* Output Data */
p = a + b;
q = a – b;
/* Method */
private static BigInteger iSqrt(BigInteger num)
{ // Finds the integer square root of a positive number
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) / 2;
while (n1 < n)
{ n = n1;
n1 = (n + (num / n)) / 2;
}
return n;
} // end iSqrt()
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I tried the above using JavaScript BigInt:
function isPerfectSqrt(n, root) {
const lowerBound = root**2n;
const upperBound = (root+1n)**2n
return lowerBound <= n && n < upperBound;
}
And found it was only about 60% as fast (in Node V8) as the one-liner:
function isPerfectSqrt(n, root) {
return (n/root === root && n%root === 0n)
}
The number you want to do a perfect square test on is A. B is the integer square root of A and the .sqrt() function returns the integer lower floor of the square root. The Boolean of B*B=A is returned. The Boolean return is "true" if it is a perfect square and "false" if it is not a perfect square.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger B = A.sqrt();
return B.multiply(B).equals(A);
}
An alternative is to use the sqrtAndRemainder() function. If the remainder, B[1], is zero it is a perfect square. The boolean TRUE then is returned as shown below.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger [] B=A.sqrtAndRemainder();
return B[1].equals(BigInteger.ZERO);
}

Categories

Resources