<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/)