Checker Random

belongs to group Basic
Identify uses of insecure random number generators

Frameworks supported by this checker

  • java up to 11
  • android up to API level 28
  • dotnet

Warnings generated by this checker

  • InsecureRandomWarning: an insecure random number generator is used instead of a secure one [ CWE330 ]
  • SuboptimalRandomNumberWarning: a random number generator is recreated just before its use [ CWE332 ]
  • UseOfFixedSeedWarning: a fixed seed is used instead of a random one [ CWE330 ]

Options accepted by this checker

  • none

Annotations understood by this checker

  • none


Description

Random number con be generated with both the java.util.Random and the java.security.SecureRandom class. However, the latter generates cryptographically secure random numbers and is hence preferred. Moreover, recreating the random generator every time that a random number is needed results in a waste of resources.

Action: Use java.security.SecureRandom instead of java.util.Random. Store the random generator in a field instead of a local variable.

In .Net, the Random number can be generated with both the System.Random (cryptographically insecure) an the System.Security.Cryptography.RNGCryptoServiceProvide (cryptographically secure) class. However, the latter generates cryptographically secure random numbers and is hence preferred.

Action: Use System.Security.Cryptography.RNGCryptoServiceProvider instead of System.Random. Store the random generator in a field instead of a local variable.

Examples

Consider the following program:

import java.util.Random;
import java.security.SecureRandom;

public class Main {
  public static void main(String[] args) {
    Random r = new Random();
    int[] array = mkRandomArray(Math.abs(r.nextInt() % 1000));
    for (int i: array)
      System.out.println(i);
      
      
  	Random sr = new SecureRandom(new byte[]{1,1,1,1});

  }

  private static int[] mkRandomArray(int length) {
    int[] result = new int[length];
    for (int pos = 0; pos < length; pos++)
      result[pos] = new Random().nextInt();

    return result;
  }
}

This checker issues the following warnings:

Main.java:6: [Random: InsecureRandomWarning] Use of unsafe random number generator. Use java.security.SecureRandom instead
Main.java:7: [Random: SuboptimalRandomNumberWarning] Suboptimal generation of random value: the random number generator is recreated each time
Main.java:12: [Random: UseOfFixedSeedWarning] Fixed seed used instead of a random one. The fixed seed is typically used for testing but is unsafe because causes the generation of a predictable sequence of numbers
Main.java:19: [Random: InsecureRandomWarning] Use of unsafe random number generator. Use java.security.SecureRandom instead
Main.java:19: [Random: SuboptimalRandomNumberWarning] Suboptimal generation of random value: the random number generator is recreated each time

since a non-cryptographically safe random number generator is used and since the random number generator is recreated each time a random number is needed. In this cases is advisable instance only one a static secure random generator and use it for generate all random values of the class. At line 12, a safe random generator is instantiated but it set as seed a constant byte array. The use of fixed seed is not recommended because causes the generation of a predictable sequence of numbers. In order to fix the issue of constant seed, it is advisable to create a random seed or use a constructor without the seed parameter because typically if not specified the constructor creates an instance that already contains a seed randomly generated by default, as in the case of java.security.SecureRandom.

In this example, the program could be modified as follows:

import java.security.SecureRandom;
import java.util.Random;

public class Main {
  private final static Random r = new SecureRandom();

  public static void main(String[] args) {
    int[] array = mkRandomArray(Math.abs(r.nextInt() % 1000));
    for (int i: array)
      System.out.println(i);
      
      
      Random sr = new SecureRandom();
  }

  private static int[] mkRandomArray(int length) {
    int[] result = new int[length];
    for (int pos = 0; pos < length; pos++)
      result[pos] = r.nextInt();

    return result;
  }
}

Consider the following program:

using System;
using System.Security.Cryptography;

namespace Random
{
    public class Random
    {
        public static void Main(string[] args)
        {
            System.Random r = new System.Random();
            int[] array = MkRandomArray(Math.Abs(r.Next() % 1000));
            foreach (int i in array)
                Console.WriteLine(i);


            System.Random r2 = new System.Random(15);
            for(int i = 0; i < 10; i++)
          		Console.WriteLine("Random value with fixed seed: "+r.Next());

        }
        private static int[] MkRandomArray(int length)
        {
            int[] result = new int[length];
            for (int pos = 0; pos < length; pos++)
                result[pos] = new System.Random().Next();
            return result;
        }
    }
}

This checker issues the following warnings:

Random.cs:10: [Random: InsecureRandomWarning] Use of unsafe random number generator. Use a secure implementation instead
Random.cs:11: [Random: SuboptimalRandomNumberWarning] Suboptimal generation of random value: the random number generator is recreated each time
Random.cs:16: [Random: InsecureRandomWarning] Use of unsafe random number generator. Use a secure implementation instead
Random.cs:16: [Random: UseOfFixedSeedWarning] Fixed seed used instead of a random one. The fixed seed is typically used for testing but is unsafe because causes the generation of a predictable sequence of numbers
Random.cs:18: [Random: SuboptimalRandomNumberWarning] Suboptimal generation of random value: the random number generator is recreated each time
Random.cs:25: [Random: InsecureRandomWarning] Use of unsafe random number generator. Use a secure implementation instead
Random.cs:25: [Random: SuboptimalRandomNumberWarning] Suboptimal generation of random value: the random number generator is recreated each time

since a non-cryptographically safe random number generator is used and since the random number generator is recreated each time a random number is needed. In this cases is advisable instance only one a static secure random generator and use it for generate all random values of the class. The use of fixed seed is not recommended because causes the generation of a predictable sequence of numbers. In order to fix the issue of constant seed, it is advisable to create a random seed or use a constructor without the seed parameter because typically if not specified the constructor creates an instance that already contains a seed randomly generated by default, as in the case of System.Random.

In this example, the program could be modified as follows:

using System.Security.Cryptography;

private static RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

public static void Main(string[] args)
{

	int[] array = MkRandomArray(Math.Abs(getRandomInt() % 1000));
	foreach (int i in array)
		Console.WriteLine(i);
}
private static int[] MkRandomArray(int length)
{
	int[] result = new int[length];
	for (int pos = 0; pos < length; pos++)
	{
		result[pos] = getRandomInt(); 
	}
    return result;
}

private static int getRandomInt() {
	byte[] buffer = new byte[4];
	rng.GetBytes(buffer);
	return BitConverter.ToInt32(buffer, 0);
}