<br />

**OWASP category:** [MASVS-CRYPTO: Cryptography](https://mas.owasp.org/MASVS/06-MASVS-CRYPTO)

## Overview

A pseudorandom number generator (PRNG) is an algorithm that generates
predictable number sequences based on a starting value called a *seed* . A
PRNG-generated number sequence has **approximately** the same properties as a
truly random number sequence, but is faster and less computationally expensive
to create.

In other words, PRNGs have higher assurances than weak RNGs (e.g.
`java.math.Random`) in terms of evenness of entropy distribution, which emulate
truly random number sequences. Truly random number generation requires
specialized equipment and is often outside the scope of normal development. This
document does not cover truly random number generation, and focuses only on
PRNGs as they are the standard methodology in use.

Weak PRNG vulnerabilities occur when developers use a regular PRNG for
cryptographic purposes, instead of a cryptographically-secure PRNG (CSPRNG).
CSPRNGs have stricter requirements, and when the seed is unknown, they must give
an attacker only an insignificant advantage in differentiating an output
sequence from an actual random sequence.

Attackers may also be able to guess the generated number sequence when
predictable seeds -- such as those hard coded by the developer -- are used to
initialize a PRNG or CSPRNG, as the attacker can guess the seed and thus predict
the output generated by the PRNG.

## Impact

If a non-cryptographically secure PRNG is used in a security context like
authentication, an attacker may be able to guess the randomly-generated numbers
and gain access to privileged data or features.

## Mitigations

### General

- Use [`java.security.SecureRandom`](https://developer.android.com/reference/java/security/SecureRandom) when there are *security implications*
- Use [`java.util.Random`](https://developer.android.com/reference/java/util/Random) for any other cases
- **Never** use [`Math.random`](https://developer.android.com/reference/java/lang/Math#random())!

### java.security.SecureRandom

**Recommended** for security uses. If the Linux kernel version is 5.17+ *or*
blocking the thread is acceptable, wait for enough entropy to accumulate before
you generate the random numbers (i.e. use `/dev/random`). To do so, call
`getInstanceStrong()`:  

### Kotlin

    val rand = SecureRandom.getInstanceStrong()

### Java

    SecureRandom rand = SecureRandom.getInstanceStrong();

Otherwise, on Linux kernel versions prior to 5.17 when blocking the thread is
unacceptable when generating random numbers, then the `SecureRandom` constructor
should be called directly:  

### Kotlin

    import java.security.SecureRandom

    object generateRandom {
        @JvmStatic
        fun main(args: Array<String>) {
            // Create instance of SecureRandom class
            val rand = SecureRandom()

            // Generate random integers in range 0 to 999
            val rand_int = rand.nextInt(1000)

            // Use rand_int for security & authentication
        }
    }

### Java

    import java.security.SecureRandom;

    public class generateRandom {

        public static void main(String args[])
        {
            // Create instance of SecureRandom class
            SecureRandom rand = new SecureRandom();

            // Generate random integers in range 0 to 999
            int rand_int = rand.nextInt(1000);

            // Use rand_int for security & authentication
        }
    }

`SecureRandom` gets the default seed from `/dev/urandom`, and is automatically
used when the object is constructed or obtained, so there is no need to
explicitly seed the PRNG. In general, any deterministic usage of `SecureRandom`
is discouraged (especially if this leads to hard coding a seed value, which
anyone decompiling the app can see). Developers who want to generate
reproducible pseudorandom output should use more appropriate primitives such as
HMAC, HKDF, and SHAKE.

### java.util.Random

**Avoid** for security / authentication purposes, acceptable to use for anything
else.  

### Kotlin

    import java.util.Random

    object generateRandom {
        @JvmStatic
        fun main(args: Array<String>) {
            // Create instance of SecureRandom class
            val rand = Random()

            // Generate random integers in range 0 to 999
            val rand_int = rand.nextInt(1000)
        }
    }

### Java

    import java.util.Random;

    public class generateRandom {

        public static void main(String args[])
        {
            // Create instance of Random class
            Random rand = new Random();

            // Generate random integers in range 0 to 999
            int rand_int = rand.nextInt(1000);
        }
    }

## Resources

- [java.security.SecureRandom](https://developer.android.com/reference/java/security/SecureRandom)
- [java.util.Random](https://developer.android.com/reference/java/util/Random)
- [Math.random](https://developer.android.com/reference/java/lang/Math#random())
- [Predictable Seed CWE](https://cwe.mitre.org/data/definitions/337.html)
- [Cryptographically Weak PRNG CWE](https://cwe.mitre.org/data/definitions/338.html)
- [Java Secure Random](https://www.baeldung.com/java-secure-random)
- [Java Random versus SecureRandom](https://www.geeksforgeeks.org/random-vs-secure-random-numbers-java/)
- [How to use SecureRandom](https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/)
- [Python PRNG security guidance](https://rules.sonarsource.com/python/RSPEC-2245)
- [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation)
- [CVE-2013-6386: Weak PRNG vuln in Drupal](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-6386)
- [CVE-2006-3419: Weak PRNG vuln in Tor](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-3419)
- [CVE-2008-4102: Predictable Seed in Joomla](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4102)
- [Linux Kernel random patch](https://lwn.net/Articles/884875/)