问题
Specifically, I just want to generate a cryptographically secure random number between 0 and some number x.
In OpenSSL this is done with the function bn_range.
I can implement it myself using Java's BigInteger(int bits, Random r) constructor (which generates a number from 0 to 2bits). But I would like, if possible, to use a better tested algorithm for the sake of security.
Is there a standard way to do this in Java?
P.S. I am actually using Android, but I don't know how to do it in standard Java.
EDIT: x is a large integer stored as a BigInteger.
回答1:
Java provides a subclass of the Random class, the SecureRandom class. The description includes:
This class provides a cryptographically strong random number generator (RNG). Many implementations are in the form of a pseudo-random number generator (PRNG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a true random seed. Other implementations may produce true random numbers and yet others may use a combination of both techniques
Java provides just one implementation, the SHA1PRNG function, which it details as a pseudo-random number generation (PRNG) algorithm:
This implementation follows the IEEE P1363 standard, Appendix G.7: "Expansion of source bits", and uses SHA-1 as the foundation of the PRNG. It computes the SHA-1 hash over a true-random seed value concatenated with a 64-bit counter which is incremented by 1 for each operation. From the 160-bit SHA-1 output, only 64 bits are used.
It should also be noted that the bn_rand_range function from OpenSSL is also considered to use a pseudo-random number generation (PRNG) algorithm, though I could not find details as for to what algorithm the function implements.
Because SecureRandom is a subclass of the Random class, SecureRandom objects can use all the methods of Random including the .nextInt(int n) method. The nextInt method provides:
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
Therefore, to generate a cryptography strong pseudo-random number in the range of (0,100] you can use code like the following:
import java.security.SecureRandom;
class secure{
public static void main(String[] args) throws Exception{
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
System.out.println(random.nextInt(100));
}
}
回答2:
As far as I can tell, this functionality is not provided. But it is easy enough to implement yourself.
Random r = new SecureRandom();
BigInteger q = something_big;
BigInteger ans;
do
ans = BigInteger(bits_in_q, r);
while (ans.compareTo(q) >= 0); // bn_rand_range generates numbers < q
来源:https://stackoverflow.com/questions/9441598/is-there-a-java-equivalent-to-openssls-bn-rand-range