Java - BigInteger strange behaviour - java

Something strange is going on with BigInteger. I'm trying to implement my own RSA for an assignment.
The code is as follows, and work great with small numbers.
If I choose p=11, q=5, e=7 and d=23 then the output on the terminal is
Original message is: 19
Encryption of message is: 24
Decryption of message is: 19
If I change the numbers with bigger ones, though, it does not work anymore. The following code:
import java.math.BigInteger;
class RSAdumb{
public static void main(String[] args) {
BigInteger m = new BigInteger("19");
BigInteger p = new BigInteger("99989");
BigInteger q = new BigInteger("99991");
BigInteger n = p.multiply(q);
BigInteger e = new BigInteger("65537");
BigInteger d = new BigInteger("4232182107");
BigInteger c = m.modPow(e,n); //Returns a BigInteger whose value is (this^e mod n)
BigInteger check = c.modPow(d,n);
System.out.println("Original message is: "+m.toString());
System.out.println("Encryption of message is: "+c.toString());
System.out.println("Decryption of message is: "+check.toString());
}
}
Outputs this:
Original message is: 19
Encryption of message is: 5609974360
Decryption of message is: 2710593036
I already checked, twice, that the numbers are good for RSA. Precisely
e*d = 4232182107 * 65537 = 1 mod 9998000099
where
9998000099 = 99989 * 99991 (both primes)
Now, from my understanding BigInteger should be unlimited so it should not be a boundary issue... than what could be? I can always implement this with small numbers for my assignment but it's quite ridiculous...

The requirement for e and d isn't that their product is congruent to 1 (mod n), it's that their product must be congruent to 1 (mod φ(n)), according to the Wikipedia page on RSA.
That is the totient function, which for the 2 primes multiplied is (p - 1)(q - 1), or 997800120.
The result of ed (mod φ(n)) is not 1, it's 32589339.
The reason that your smaller numbers worked is because φ(n) for 5 and 11 is 4 * 10 = 40, and 7 * 23 (mod 40) is 1.
You will need to choose a proper d constant for your larger numbers. This is the modular inverse of e with respect to φ(n), which can be calculated with BigInteger's modInverse method.
BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
BigInteger d = e.modInverse(phi);
This reveals d to be 2598113033. Using d yields the proper output.
Original message is: 19
Encryption of message is: 5609974360
Decryption of message is: 19

You've made an error calculating the private exponent d.
First you need to calculate phi of n: φ(n) = φ(p)φ(q) = (p − 1)(q − 1) = n - (p + q -1)
BigInteger phi = n.subtract(p.add(q).subtract(BigInteger.ONE));
and then you need to take the modular inverse of e with phi as the modulus to get d:
d = e.modInverse(phi);
which results in d = 2598113033.
For reference: Wikipedia

Related

how to find number of digits in factorial of 42?

factorial of 42 is going beyond the final limit of long data type in java. that's why I can't find digits.
42!
The factorial of 42 is of 51 digits while the max limit of long datatype in Java is 9,223,372,036,854,775,807 i.e only 20 digits. But don't worry, Java has a Big Integer class to store large numbers such as 100!. But it's a bit slower than primitive data types such as int, long etc because it stores integers in the form of arrays. There are many ways to implement the Big Integer class but here's the most used way. This code calculates the factorial of 42 and prints the same-
// Java program to find large factorials using BigInteger
import java.math.BigInteger;
public class Factorial
{
// Returns Factorial of N
static BigInteger factorial(int N)
{
BigInteger fact = new BigInteger("1"); // Or BigInteger.ONE
// Multiply f with 2, 3, ...N
for (int i = 2; i <= N; i++)
fact = fact.multiply(BigInteger.valueOf(i));
return fact;
}
public static void main(String args[])
{
int N = 42;
System.out.println(factorial(N));
}
}
Output:
1405006117752879898543142606244511569936384000000000
Explanation
We have to import the Big Integer class, which is stored in java.math package. I have named my file Factorial.java, so my class name is Factorial.
In this method, I've created a function, if you want the code without function, just comment below. Now in this syntax-
BigInteger f = new BigInteger("1");
I've assigned fact as Big integer which is equal to 1. In the for loop,
i value is set to 2 s 1*1=1.
fact = fact.multiply(BigInteger.valueOf(i));
The above syntax is for the multiplication of Big integers. This multiplies the Biginteger fact by i.
Have a look at this GeeksforGeeks article- https://www.geeksforgeeks.org/biginteger-class-in-java/
If you only care about the number of digits, I would recommend taking a more mathematical approach. There are ways to compute this number without actually computing the factorial itself. This would not require so big a variable and would be a lot faster.
You could think it this way:
Digits(n!) = floor(log10(n!)) + 1 = floor(log10(n * (n - 1) * ... * 1)) + 1 =floor(\sum_{i = 1}^{n}log10(i)) + 1
A picture of this expression: expression
This would still require iteration, but it deals with much smaller numbers.
If you still want O(1) complexity for this task, you can go with a pretty good approximation I've just tried.
Digits(n!) ~ floor(\int_{1}^{x}log10(x) dx) + 1 = floor(\frac{-x + x*ln(x) + 1}{ln(10)}) + 1
Another image of this formula: approximate expression
Of course, the latter is no absolutely exact since we are now integrating a continuous function. However, it will probably be worth implementing.
Digits(42!) = floor(50.37...) + 1 = 50 + 1 = 51

RSA digital signature failing

I am trying to implement the RSA Blind digital signature scheme, using the BigInteger class for generating large prime numbers. Samantha generates the public key, the private key, chooses a message, masks it, then signs it and then Victor verifies the signature.
Problem: As long as I use the modular exponentiation method modPow from the BigInteger class, everything works perfectly (the verification algorithm returns true everytime). However, I have built a custom class where I have implemented several algebraic algorithms on my own; when I switch the modPow call with my modExp method, I keep getting false returns from the verification algorithm (about 50-60 % of the time), even though I should not. If instead of using large, random integers, I set small, hardcoded numbers for testing purposes, I get the correct result.
Question: As a consequence, I am pretty sure that my modExp method is the problem, however I can't seem to find out did I do wrong, even after changing the algorithm several times. What is the problem?
My code so far:
RSA_test() -- Method used for the precomputation step and testing
public static void RSA_test(){
// The Signer (Samantha) picks p and q, 1024 bit primes
Random rng = new SecureRandom();
BigInteger p = BigInteger.probablePrime(1024, rng);
BigInteger q = BigInteger.probablePrime(1024, rng);
/*BigInteger p = BigInteger.valueOf(7);
BigInteger q = BigInteger.valueOf(13);*/
// The RSA modulus is computed
BigInteger n = p.multiply(q);
// phi(n) is computed
BigInteger phiN = (p.subtract(BigInteger.ONE)
.multiply(q.subtract(BigInteger.ONE)));
// Samantha chooses her message, m
BigInteger m = new BigInteger("22");
// Samantha computes her public exponent
BigInteger v;
while(true){
v = new BigInteger(phiN.bitLength(), rng);
if(v.compareTo(BigInteger.ONE) > 0 &&
v.compareTo(phiN) < 0 &&
ModularArithmetic.gcd(v, phiN).equals(BigInteger.ONE))
break;
}
// v = BigInteger.valueOf(5);
// Samantha generates the blinding factor and masks her message
BigInteger r;
while(true){
r = new BigInteger(512, rng);
if(ModularArithmetic.gcd(r, n).equals(BigInteger.ONE))
break;
}
// r = BigInteger.valueOf(10);
BigInteger mBlinded = m.multiply(ModularArithmetic.modExp(r, v, n));
// Samantha signs her message
BigInteger SBlinded = Cryptography.RSASignature(mBlinded, n, phiN, v);
// Samantha removes the blinding factor, obtaining S
BigInteger S = SBlinded.multiply(ModularArithmetic.modInv(r, n));
// Victor verifies the signature
boolean result = Cryptography.RSAVerification(S, m, n, v);
String s = (result == true) ? "The signature has been verified" : "The signature has not been verified";
System.out.println(s);
}
As the signature and verification methods are irrelevant for the question, as I am certain that they are correct, I will omit them. Also, here is my modExp method:
public static BigInteger modExp(BigInteger base, BigInteger exponent, BigInteger modulus){
if(exponent.equals(BigInteger.ZERO))
return (modulus.equals(BigInteger.ONE)) ? BigInteger.ZERO : BigInteger.ONE;
if(base.equals(BigInteger.ONE))
return (modulus.equals(BigInteger.ONE)) ? BigInteger.ZERO : BigInteger.ONE;
if(exponent.equals(BigInteger.ONE))
return base.mod(modulus);
if(modulus.equals(BigInteger.ONE))
return BigInteger.ZERO;
// The case when base does not have a multiplicative inverse
if((modulus.compareTo(BigInteger.ZERO) <= 0) ||
((exponent.compareTo(BigInteger.ZERO) < 0 && !(gcd(base,modulus).compareTo(BigInteger.ONE) == 0))))
throw new ArithmeticException("BigInteger: modulus not positive");
BigInteger result = BigInteger.ONE;
while(exponent.compareTo(BigInteger.ZERO) > 0){
if(exponent.testBit(0))
result = (result.multiply(base).mod(modulus));
exponent = exponent.shiftRight(1);
base = (base.multiply(base)).mod(modulus);
}
return result.mod(modulus);
}
You don't handle negative exponents correctly, except to check that gcd(base, modulus) == 1. The following snippet shows one correct way to do it.
if (exponent.signum() < 0 && gcd(base,modulus).equals(BigInteger.ONE)) {
return modExp(base.modInverse(modulus), exponent.negate(), modulus);
}
Observe that the signum() method may be more convenient for comparing big integers to zero.

Finding a generator of a subgroup for ElGamal algorithm in java?

I am trying to find a generator which is smaller than 1024 bits.
p is a random 1024 bit prime number.
q is a random 160 bit prime that divides p-1.
I have already found the values of p and q. But the generator always ends up being 0 or 1.
Help is much appreciated.
BigInteger alpha=new BigInteger(1022,rand);//finding a biginteger smaller than 1024 bits
BigInteger modInverseQ= q.modInverse(p); // (q^-1) mod(p)
BigInteger y = p.subtract(one); //p-1
BigInteger z = y.multiply(modInverseQ); //(p-1)*(q^-1)
BigInteger g = alpha.modPow(z, p); // a^(p-1)*(q^-1) mod(p)
int comp = g.compareTo(one); // checking if generator is equal to 1
while(comp == 0) //if generator is 1 find a new generator
{
alpha=new BigInteger(1022,rand);
g = alpha.modPow(z, p);
comp = g.compareTo(one);
}
You could have a look at the implementation of the following class: org.bouncycastle.crypto.generators.DSAParametersGenerator .
It is a class of Bouncy Castle (https://www.bouncycastle.org/java.html), a Java cryptographic provider.
Within it, there are several private methods that could be very useful for what you need.

How to calculate ((Integer)^(double)) % (Integer) in java?

I am trying to calculate the value of (10^5.102103)%24 that is 10 raised to power 5.102103 modulus 24 in Java ?
Which is the best and accurate method to do because
int a;
double b;
int m;
Calculate (a^b)%m
Where a can be very large like upto 10^9
b can be any double or float value which can be large
and m is any Integer
Example ---How you can calculate the value of
(10^10002.3443)%10000007
I know Math.pow(a,b) function works for small a and b only
While BigInteger function Uses only modPow(a,b) where a and b should be integer only(Correct me if i am wrong)
Unfortunately, it's not possible using the normal Java data types to get a correct answer to this. If you use double to store the exponent, you introduce an error, because double won't store most decimal numbers exactly. When you write double b = 10002.3443; the number that is stored in b is actually 10002.34430000000065774656832218170166015625. Even though it looks like 10002.3443 when you print it, that's a trick of the way Java prints numbers - basically it chooses the decimal number with the least number of decimal places that would be represented by that double.
Now this difference looks insignificant. But the difference between 10^10002.3443 and 10^10002.34430000000065774656832218170166015625 is approximately 3.346 x 10^9990, which is a 9991-digit number. Now, what will this difference become when we apply the modulus operator?
(10^10002.34430000000065774656832218170166015625 % 10000007) - (10^10002.3443 % 10000007)
= (10^10002.34430000000065774656832218170166015625 - 10^10002.3443) % 10000007
= (3.346 x 10^9990) % 10000007 (approximately)
Now, it's anybody's guess what that actually comes to. But you've got a better chance of being struck by lightning than of getting the correct answer, if you use double at any point in the calculation.
The other option might be BigDecimal. But the problem is that 10^10002.3443 is irrational - it's not a terminating decimal, so it can't be represented correctly in a BigDecimal.
So Java doesn't have a data type that will allow you to perform the calculation that you want to perform.
You are going to have to invent your own data type, then work out how to do all the bit-crunching to implement exponentiation and modulus. This is a huge project, and I suggest you start out by getting yourself a PhD in mathematics.
(Note: Obviously, I am using ^ to indicate exponentiation and x to indicate multiplication in the above, even though this is not the normal Java convention)
Let's think back to discrete math!
Given y = a b (mod m), we know that
y = ((a mod m)^b) mod m
For example, if we have
a = 2, b = 6, m = 5
a raised to the power of b is 64. 64 mod m is 64 % 5 == 4. Let's check our algorithm:
4 == ((a mod m)^b) mod m
4 == ((2 mod 5)^6) mod 5
...
4 == 64 % 5
4 == 4
This doesn't really help us all too much (in its current form), so let's use modular arithmetic at every step to save the day.
int a = 10;
int m = 10000007;
double b = 10002.3443;
int holder = (int) b;
double delta = b - holder; // as close as we're going to get
int total = 1;
for (int i = 0; i < holder; i++) {
total *= (a % m); // multiply by the modulus
total %= m; // take the modulus again
}
total *= (Math.round(Math.pow(a, delta)) % m);
total %= m;

How to avoid java.lang.OutOfMemoryError?

I have two simple java codes.The first one defines constant power as power = a.pow(b);
import java.math.BigInteger;
public class FermatOne
{
public static void main(String[] args)
{
BigInteger a = new BigInteger ("2");
BigInteger k = new BigInteger ("15");
BigInteger c = new BigInteger ("1");
int b = 332192810;
BigInteger n = new BigInteger ("2");
BigInteger power;
power = a.pow(b);
BigInteger exponent;
exponent = k.multiply(power);
BigInteger mod;
mod = exponent.add(c);
BigInteger result = n.modPow(exponent,mod);
System.out.println("Result is ==> " + result);
}
}
The second one defines constant power as power = BigInteger.ONE.shiftLeft(b)
import java.math.BigInteger;
public class FermatOne
{
public static void main(String[] args)
{
BigInteger k = new BigInteger ("15");
BigInteger c = new BigInteger ("1");
int b = 332192810;
BigInteger n = new BigInteger ("2");
BigInteger power;
power = BigInteger.ONE.shiftLeft(b);
BigInteger exponent;
exponent = k.multiply(power);
BigInteger mod;
mod = exponent.add(c);
BigInteger result = n.modPow(exponent,mod);
System.out.println("Result is ==> " + result);
}
}
Setting the memory flag -Xmx1024m in the command line the first code works fine , but for the second code I am getting error : java.lang.OutOfMemoryError :Java heap space
My question : What should I change in the second code to avoid java.lang.OutOfMemoryError ?
You're trying to calculate a number like 2 ^ (15 * 2 ^ 332192809). I don't know if you could even fit such a number in the universe!! Or maybe, the answer is simply... 42 ? ;-)
On a more serious note, you'll really have trouble, calculating this number. Encoded in bits, 15 * 2 ^ 332192810 would require almost a gigabyte by itself. Then raising 2 to that power again, I don't want to know...
On a more serious note, when you dig into the implementation of java.math.BigInteger, I think that you just run into such an error faster with the left shift, as that is implemented much more efficiently, than the power method. Having said this, have you tried to force garbage collection in your code, using System.gc()?
UPDATE: My original reasoning might've been wrong. 2 ^ 332192809 can be calculated with 1GB. And the overall result might be "modded" efficiently by java.math.BigInteger, although I believe that this calculation might take a while...
It's just a guess, but BigInteger.ONE.shiftLeft(332192810); will internally create an int array of length x + 10381025. Since an int is 4 bytes big you'll get about 40 mega bytes of data just for that one call. I assume the other calls copy that data around and thus you get that high a memory consumption.

Categories

Resources