Java Secure Random Number Example
Secure Random Number Generation in Java | Lucideus
Introduction
This blog gives a brief understanding of the main two classes used in java used to generate random numbers. Random number generation can be used for various tasks that may require much security like creating a random password, generating an initialization vector, nonce or a cryptographic key or a session identifier. According to OWASP, Insecure Randomness occurs when a function that can produce predictable values is used as a source of randomness in security-sensitive context. Usage of java.util.Random class makes the random number generation cryptographically weak. Hence, it is recommended to use java.security.SecureRandom class for random number generation.
Insecure Implementation — java.util.Random
One of the API's used to generate Random numbers in java is java.util.Random. It uses 48 bit seed ( a seed can be considered as a starting point or the initial value). Following is the block-diagram implementation of java.util.Random.
Fig 1: java.util.Random implementation
The Random() in the block above uses Linear Congruential Formula of the form
X1 = a*x0 + c mod m , where a, m & c are constants
It is clear from the formula above that the next number generated from this can be predicted by applying the formula (if the starting seed is known). If two instances of Random are created with the same seed and same sequence of method call is made, they will always generate identical sequence of numbers.
The following is an example of vulnerable code that generates predictable random numbers
Import java.util.Random
public static int generateRandomInt(int upperRange)
{
Random random = new Random();
return random.nextInt(upperRange);
}
This code uses the random.nextInt() to generate random number which is considered as a statistically PRNG (Pseudo Random Number generator) which can be predicted easily.
Secure Implementation — java.security.SecureRandom
A secure Random number generator is the one that exhibits the following properties:-
- It appears random
- Its value is unpredictable
- It cannot be reliably produced after generation
Java's SecureRandom class provides the above mentioned properties. The secureRandom class uses entropy to generate random numbers. Entropy is using unpredictable input as a source. It could be either using hardware or OS implementation or using system process such as timing events or interrupts. The following is the block diagram implementation for the same.
Fig 2: java.security.SecureRandom implementation
The following care must be taken in the above implementation- never explicitly seed (i.e don't use setSeed method before a call to next* method).
If you want complete assurance of randomness for a given OS, it is recommended to use "Windows-PRNG" algorithm for Windows environment and "NativePRNG" for unix like environments (However, code portability would be affected). In windows, default implementation will return SHA1PRNG algorithm.
The following is an example of using Java's Securerandom for generating cryptographically secure random numbers
Import java.security.SecureRandom
public static int generateRandom(int maximumValue)
{
SecureRandom ranGen = new SecureRandom();
return ranGen.nextInt(maximumValue);
}
Tips for Developers while generating Secure Random Number Generators
- Don't use Math.random for random number generation as it is cryptographically insecure.
- Source of Entropy should be carefully chosen. A cryptographically secure random number generation depends on
- CSPRNG Algorithm (Native, Windows-PRNG, SHA1PRNG etc)
- Source of randomness at least during initial seeding.
- A pseudo random number output.
Thus, strength of CSPRNG depends on entropy. The most practically unpredictable source of entropy is using OS implementation such as system files. In unix, we can use
file://dev/random and file://dev/urandom files as they are continuously updated with random external OS dependent events. The file://dev/random comes with blocking source and blocks the application until it finds sufficient source of entropy.Hence, it is advised to use file://dev/random (as it is non-blocking source).
- Secure Random randomizer should always be self seeded. Never, ever explicitly seed a SHA1PRNG algorithm. In Windows, SHA1PRNG is the default implementation used.
Safe implementation for Windows like systems
SecureRandom secRan = SecureRandom.getInstance("Windows-PRNG") ; // Default constructor would have returned insecure SHA1PRNG algorithm, so make an explicit call.
byte[] b = new byte[NO_OF_RANDOM_BYTES] ;
secRan.nextBytes(b);
Safe implementation for Unix like systems
SecureRandom secRan = new SecureRandom() ; // In Unix like systems, default constructor uses NativePRNG, seeded by securerandom.source property
byte[] b = new byte[NO_OF_RANDOM_BYTES] ;
secRan.nextBytes(b);
References
[1] https://www.owasp.org/index.php/Insecure_Randomness
[2] https://resources.infosecinstitute.com/random-number-generation-java/#gref
[3] https://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html
[4] https://www.geeksforgeeks.org/random-vs-secure-random-numbers-java/
[5] https://developer.android.com/reference/java/security/SecureRandom
gourleynaticepled.blogspot.com
Source: https://medium.com/@lucideus/secure-random-number-generation-in-java-lucideus-5f5fb5151bde
0 Response to "Java Secure Random Number Example"
Enregistrer un commentaire