I'm aware of the function BigInteger.probablePrime(int bitLength, Random rnd) that outputs probably prime number of any bit length. I want a REAL prime number in Java. Is there any FOSS library to do so with acceptable performance? Thanks in advance!
EDIT:
I'm looking at 1024 & 2048 bit primes.
use probable prime to generate a candidate
use a fast deterministic test such as the AKS primality test to check whether the candidate is indeed prime.
edit: Or, if you don't trust the isProbablePrime to be large enough certainty, use the BigInteger constructor BigInteger(int bitLength, int certainty, Random rnd) that lets you tune your certainty threshold:
certainty - a measure of the uncertainty that the caller is willing to tolerate. The probability that the new BigInteger represents a prime number will exceed (1 - 1/2certainty). The execution time of this constructor is proportional to the value of this parameter.
Probabilistic tests used for cryptographic purposes are guaranteed to bound the probability of false positives -- it's not like there's some gotcha numbers that exist that will sneak through, it's just a matter of how low you want the probability to be. If you don't trust the Java BigInteger class to use these (it would be nice if they documented what test was used), use the Rabin-Miller test.
There are some methods to generate very large primes with acceptable performance, but not with sufficient density for most purposes other than getting into the Guiness Book of Records.
Look at it like this: the likelihood that a number returned by probablePrime() is not prime is lower than the likelihood of you and everyone you know getting hit by lighting. Twice. On a single day.
Just don't worry about it.
You could also use the constructor of BigInteger to generate a real prime:
BigInteger(int bitLength, int certainty, Random rnd)
The time to execute is proportional to the certainty, but on my Core i7 it isn't a problem.
Make a method and wrap it.
BigInteger definitePrime(int bits, Random rnd) {
BigInteger prime = new BigInteger("4");
while(!isPrime(prime)) prime = BigInteger.probablePrime(bits,rnd);
return prime;
}
Random rnd = new SecureRandom();
System.out.println(BigInteger.probablePrime(bitLength, rnd));
The probability that a BigInteger returned by method probablePrime() is composite does not exceed 2^-100.
Related
I am writing some kotlin, and would like to use the Prime constructor for BigIntegers. Because I want to generate some really big prime numbers.
The documentation for the constructor looks like this:
BigInteger(int bitLength, int certainty, Random rnd)
Constructs a randomly generated positive BigInteger that is probably prime, with the specified bitLength.
My problem is here that I find it a little unspecified what these arguments actually do.
bitlength
My first assumption is that this is just the amount of bits that I want the BigInt to have. This seems simple enough, but still i'm a bit in doubt about whether this means my number will use this many bits, or if it is a maximum, minimum etc.
certainty
This one is really mystical to me. Is this the probability that the number is prime, or the probability of that is has the beforementioned bitlength.
And on top of that, which unit do we use to denote certainty? percentages, is some probability ranking system i have never heard of?
** rnd**
I assume this is just a random generator as they come standardly in java.
But what is it used for in this context? it would be nice to be able to know why I should provide one
Hope someone can help in clearing my my confusion
The rest of the documentation is here:
https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html
Can you use BigInteger.isProbablePrime() to generate cryptographically secure primes? What certainty is necessary for them to be "secure"?
I do not hold a degree in crypto, so take this with a grain of salt.
You have two major areas of concern here:
Your primes need to be unpredictably random. This means that you need to use a source such as SecureRandom to generate your primes. No matter how sure of your primality, if they are predictable, the entire cryptosystem fails to meet its goal. If you are using the BigInteger(int bitLength, int certainty, Random rnd) constructor, you can pass in your SecureRandom as it subclasses Random.
Your potential primes need to be reasonably certain of being primes (I'm assuming that you are using an algorithm that relies on the hardness of factoring). If you get a probable prime, but an attacker can, with a good probability, factor it within 5 minutes because it had a factor that never got noticed by the primality test you ran, you are somewhat out of luck with your algorithm. Rabin-Miller is generally used, and this answer states that a certainty of 15 is sufficient for 32-bit integers. A value up to 40 is recommended, and anything beyond that is meaningless.
this is the way i generated a secure BigInteger for my cryptographic application.
Here's my code:
BigInteger b = new BigInteger(25, new SecureRandom());
Since you also need it for a crypto application, in my opinion, getting a BigInteger is this way is right.
Note: Remember that SecureRandom objects are preformance-wise costly. So You should not initialize them many times.
After reading comments, it worked out further
Here's a way which assures you more certainity of getting a prime number.
BigInteger b =BigInteger.probablePrime(25, new SecureRandom(););
As #hexafraction says, you need to use SecureRandom() to generate a cryptographic quality random number. The Javadoc says that the generated prime is 2^-100 secure. If you want more security (say to 2^-128 for AES equivalent security) then run more iterations of the Miller-Rabin test on it. Each iteration gives you an extra 2^-2 security, so fourteen iterations would get you to 2^-128.
I want to generate a 160-bit prime number in java. I know that I'll have to loop through all the 160-bit numbers and for any number n, I'll have to check if they are divisible by any primes less than sqroot(n) or by any primality test like Miller-Rabin test. My questions are:
Is there any specific library which does this?
Is there any other (better) way to do this?
BigInteger.probablePrime(160, new Random()) generates a BigInteger that is almost certainly prime -- the probability that it is not a prime is less than the probability that you will get struck by lightning. In general, BigInteger already has heavily tested and optimized primality testing operations built in.
For what it's worth, the reason this won't take forever is that by the prime number theorem, a randomly chosen n-bit number has probability proportional to 1/n of being prime, so on average you only need to try O(n) different random n-bit numbers before you'll find one that's prime.
I discovered something strange with the generation of random numbers using Java's Random class.
Basically, if you create multiple Random objects using close seeds (for example between 1 and 1000) the first value generated by each generator will be almost the same, but the next values looks fine (i didn't search further).
Here are the two first generated doubles with seeds from 0 to 9 :
0 0.730967787376657 0.24053641567148587
1 0.7308781907032909 0.41008081149220166
2 0.7311469360199058 0.9014476240300544
3 0.731057369148862 0.07099203475193139
4 0.7306094602878371 0.9187140138555101
5 0.730519863614471 0.08825840967622589
6 0.7307886238322471 0.5796252073129174
7 0.7306990420600421 0.7491696031336331
8 0.7302511331990172 0.5968915822372118
9 0.7301615514268123 0.7664359929590888
And from 991 to 1000 :
991 0.7142160704801332 0.9453385235522973
992 0.7109015598097105 0.21848118381994108
993 0.7108119780375055 0.38802559454181795
994 0.7110807233541204 0.8793923921785096
995 0.7109911564830766 0.048936787999225295
996 0.7105432327208906 0.896658767102804
997 0.7104536509486856 0.0662031629235198
998 0.7107223962653005 0.5575699754613725
999 0.7106328293942568 0.7271143712820883
1000 0.7101849056320707 0.574836350385667
And here is a figure showing the first value generated with seeds from 0 to 100,000.
First random double generated based on the seed :
I searched for information about this, but I didn't see anything referring to this precise problem. I know that there is many issues with LCGs algorithms, but I didn't know about this one, and I was wondering if this was a known issue.
And also, do you know if this problem only for the first value (or first few values), or if it is more general and using close seeds should be avoided?
Thanks.
You'd be best served by downloading and reading the Random source, as well as some papers on pseudo-random generators, but here are some of the relevant parts of the source. To begin with, there are three constant parameters that control the algorithm:
private final static long multiplier = 0x5DEECE66DL;
private final static long addend = 0xBL;
private final static long mask = (1L << 48) - 1;
The multiplier works out to approximately 2^34 and change, the mask 2^48 - 1, and the addend is pretty close to 0 for this analysis.
When you create a Random with a seed, the constructor calls setSeed:
synchronized public void setSeed(long seed) {
seed = (seed ^ multiplier) & mask;
this.seed.set(seed);
haveNextNextGaussian = false;
}
You're providing a seed pretty close to zero, so initial seed value that gets set is dominated by multiplier when the two are OR'ed together. In all your test cases with seeds close to zero, the seed that is used internally is roughly 2^34; but it's easy to see that even if you provided very large seed numbers, similar user-provided seeds will yield similar internal seeds.
The final piece is the next(int) method, which actually generates a random integer of the requested length based on the current seed, and then updates the seed:
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
This is called a 'linear congruential' pseudo-random generator, meaning that it generates each successive seed by multiplying the current seed by a constant multiplier and then adding a constant addend (and then masking to take the lower 48 bits, in this case). The quality of the generator is determined by the choice of multiplier and addend, but the ouput from all such generators can be easily predicted based on the current input and has a set period before it repeats itself (hence the recommendation not to use them in sensitive applications).
The reason you're seeing similar initial output from nextDouble given similar seeds is that, because the computation of the next integer only involves a multiplication and addition, the magnitude of the next integer is not much affected by differences in the lower bits. Calculation of the next double involves computing a large integer based on the seed and dividing it by another (constant) large integer, and the magnitude of the result is mostly affected by the magnitude of the integer.
Repeated calculations of the next seed will magnify the differences in the lower bits of the seed because of the repeated multiplication by the constant multiplier, and because the 48-bit mask throws out the highest bits each time, until eventually you see what looks like an even spread.
I wouldn't have called this an "issue".
And also, do you know if this problem only for the first value (or first few values), or if it is more general and using close seeds should be avoided?
Correlation patterns between successive numbers is a common problem with non-crypto PRNGs, and this is just one manifestation. The correlation (strictly auto-correlation) is inherent in the mathematics underlying the algorithm(s). If you want to understand that, you should probably start by reading the relevant part of Knuth's Art of Computer Programming Chapter 3.
If you need non-predictability you should use a (true) random seed for Random ... or let the system pick a "pretty random" one for you; e.g. using the no-args constructor. Or better still, use a real random number source or a crypto-quality PRNG instead of Random.
For the record:
The javadoc (Java 7) does not specify how Random() seeds itself.
The implementation of Random() on Java 7 for Linux, is seeded from the nanosecond clock, XORed with a 'uniquifier' sequence. The 'uniquifier' sequence is LCG which uses different multiplier, and whose state is static. This is intended to avoid auto-correlation of the seeds ...
This is a fairly typical behaviour for pseudo-random seeds - they aren't required to provide completely different random sequences, they only provide a guarantee that you can get the same sequence again if you use the same seed.
The behaviour happens because of the mathematical form of the PRNG - the Java one uses a linear congruential generator, so you are just seeing the results running the seed through one round of the linear congruential generator. This isn't enough to completely mix up all the bit patterns, hence you see similar results for similar seeds.
Your best strategy is probably just to use very different seeds - one option would be to obtain these by hashing the seed values that you are currently using.
By making random seeds (for instance, using some mathematical functions on System.currentTimeMillis() or System.nanoTime() for seed generation) you can get better random result. Also can look at here for more information
While conducting some experiments in Java, my project supervisor reminded me to seed each iteration of the experiment with a different number. He also mentioned that I should use prime numbers for the seed values. This got me thinking — why primes? Why not any other number as the seed? Also, why must the prime number be sufficiently big? Any ideas? I would've asked him this myself, but its 4am here right now, everyone's asleep, I just remembered this question and I'm burning to know the answer (I'm sure you know the feeling).
It would be nice if you could provide some references, I'm very interested in the math/concept behind all this!
EDIT:
I'm using java.util.Random.
FURTHER EDIT:
My professor comes from a C background, but I'm using Java. Don't know if that helps. It appears that using primes is his idiosyncrasy, but I think we've unearthed some interesting answers about generating random numbers. Thanks to everyone for the effort!
Well one blink at the implementation would show you that he CAN'T have any reason for that claim at all. Why? Because that's how the set seed function looks like:
synchronized public void setSeed(long seed) {
seed = (seed ^ multiplier) & mask;
this.seed.set(seed);
haveNextNextGaussian = false;
}
And that's exactly what's called from the constructor. So even if you give it a prime, it won't use it anyhow, so if at all you'd have to use a seed s where (s^ multiplier) & mask results in a prime ;)
Java uses a usual linear congruency method, i.e.:
x_n+1 = (a * x_n + c) mod m with 2 <= a < m; 0 <= c < m.
Since you want to get a maximal periode, c and m have to be relatively prime and a few other quite obscure limitations, plus a few tips how to get a practically useful version. Knuth obviously covers that in detail in part2 ;)
But anyhow, the seed doesn't influence the qualities of the generator at all. Even if the implementation would be using a Lehmer generator, it would obviously make sure that N is prime (otherwise the algorithm is practically useless; and not uniformly distributed if all random values would have to be coprime to a non prime N I wager) which makes the point moot
If the generator is a Lehmer generator, than the seed and the modulus must be co-prime; see the wiki page. One way to ensure they are co-prime is to start with a prime number.
If you are talking about java.util.Random, or one of its subclasses in the Oracle runtime, there's no reason for this. It's just a whim of your supervisor.