RandomUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.lang3;

  18. import java.security.NoSuchAlgorithmException;
  19. import java.security.SecureRandom;
  20. import java.security.Security;
  21. import java.util.Random;
  22. import java.util.concurrent.ThreadLocalRandom;
  23. import java.util.function.Supplier;

  24. import org.apache.commons.lang3.exception.UncheckedException;

  25. /**
  26.  * Supplements the standard {@link Random} class.
  27.  * <p>
  28.  * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator implementing the
  29.  * default random number algorithm.
  30.  * </p>
  31.  * <p>
  32.  * Use {@link #secureStrong()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an instance that was selected by using
  33.  * the algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
  34.  * </p>
  35.  * <p>
  36.  * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()} <b>which is not cryptographically secure</b>. In addition,
  37.  * instances do not use a cryptographically random seed unless the {@linkplain System#getProperty system property} {@code java.util.secureRandomSeed} is set to
  38.  * {@code true}.
  39.  * </p>
  40.  * <p>
  41.  * Starting in version 3.17.0, the method {@link #secure()} uses {@link SecureRandom#SecureRandom()} instead of {@link SecureRandom#getInstanceStrong()}, and
  42.  * adds {@link #secureStrong()}.
  43.  * </p>
  44.  * <p>
  45.  * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}.
  46.  * </p>
  47.  * <p>
  48.  * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods.
  49.  * </p>
  50.  * <p>
  51.  * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not cryptographically secure.
  52.  * </p>
  53.  * <p>
  54.  * Please note that the Apache Commons project provides a component dedicated to pseudo-random number generation, namely
  55.  * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a>, that may be a better choice for applications with more stringent requirements
  56.  * (performance and/or correctness).
  57.  * </p>
  58.  *
  59.  * @see #secure()
  60.  * @see #secureStrong()
  61.  * @see #insecure()
  62.  * @see SecureRandom#SecureRandom()
  63.  * @see SecureRandom#getInstanceStrong()
  64.  * @see ThreadLocalRandom#current()
  65.  * @see RandomStringUtils
  66.  * @since 3.3
  67.  */
  68. public class RandomUtils {

  69.     private static RandomUtils INSECURE = new RandomUtils(ThreadLocalRandom::current);

  70.     private static RandomUtils SECURE = new RandomUtils(SecureRandom::new);

  71.     private static final Supplier<Random> SECURE_STRONG_SUPPLIER = () -> RandomUtils.SECURE_RANDOM_STRONG.get();

  72.     private static RandomUtils SECURE_STRONG = new RandomUtils(SECURE_STRONG_SUPPLIER);

  73.     private static final ThreadLocal<SecureRandom> SECURE_RANDOM_STRONG = ThreadLocal.withInitial(() -> {
  74.         try {
  75.             return SecureRandom.getInstanceStrong();
  76.         } catch (final NoSuchAlgorithmException e) {
  77.             throw new UncheckedException(e);
  78.         }
  79.     });

  80.     /**
  81.      * Gets the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not cryptographically
  82.      * secure</b>; use {@link #secure()} to use an algorithms/providers specified in the
  83.      * {@code securerandom.strongAlgorithms} {@link Security} property.
  84.      * <p>
  85.      * The method {@link ThreadLocalRandom#current()} is called on-demand.
  86.      * </p>
  87.      *
  88.      * @return the singleton instance based on {@link ThreadLocalRandom#current()}.
  89.      * @see ThreadLocalRandom#current()
  90.      * @see #secure()
  91.      * @since 3.17.0
  92.      */
  93.     public static RandomUtils insecure() {
  94.         return INSECURE;
  95.     }

  96.     /**
  97.      * Generates a random boolean value.
  98.      *
  99.      * @return the random boolean
  100.      * @since 3.5
  101.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  102.      */
  103.     @Deprecated
  104.     public static boolean nextBoolean() {
  105.         return secure().randomBoolean();
  106.     }

  107.     /**
  108.      * Generates an array of random bytes.
  109.      *
  110.      * @param count the size of the returned array
  111.      * @return the random byte array
  112.      * @throws IllegalArgumentException if {@code count} is negative
  113.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  114.      */
  115.     @Deprecated
  116.     public static byte[] nextBytes(final int count) {
  117.         return secure().randomBytes(count);
  118.     }

  119.     /**
  120.      * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive).
  121.      *
  122.      * @return the random double
  123.      * @see #nextDouble(double, double)
  124.      * @since 3.5
  125.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  126.      */
  127.     @Deprecated
  128.     public static double nextDouble() {
  129.         return secure().randomDouble();
  130.     }

  131.     /**
  132.      * Generates a random double within the specified range.
  133.      *
  134.      * @param startInclusive the smallest value that can be returned, must be non-negative
  135.      * @param endExclusive   the upper bound (not included)
  136.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  137.      *                                  negative
  138.      * @return the random double
  139.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  140.      */
  141.     @Deprecated
  142.     public static double nextDouble(final double startInclusive, final double endExclusive) {
  143.         return secure().randomDouble(startInclusive, endExclusive);
  144.     }

  145.     /**
  146.      * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive).
  147.      *
  148.      * @return the random float
  149.      * @see #nextFloat(float, float)
  150.      * @since 3.5
  151.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  152.      */
  153.     @Deprecated
  154.     public static float nextFloat() {
  155.         return secure().randomFloat();
  156.     }

  157.     /**
  158.      * Generates a random float within the specified range.
  159.      *
  160.      * @param startInclusive the smallest value that can be returned, must be non-negative
  161.      * @param endExclusive   the upper bound (not included)
  162.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  163.      *                                  negative
  164.      * @return the random float
  165.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  166.      */
  167.     @Deprecated
  168.     public static float nextFloat(final float startInclusive, final float endExclusive) {
  169.         return secure().randomFloat(startInclusive, endExclusive);
  170.     }

  171.     /**
  172.      * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive).
  173.      *
  174.      * @return the random integer
  175.      * @see #nextInt(int, int)
  176.      * @since 3.5
  177.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  178.      */
  179.     @Deprecated
  180.     public static int nextInt() {
  181.         return secure().randomInt();
  182.     }

  183.     /**
  184.      * Generates a random integer within the specified range.
  185.      *
  186.      * @param startInclusive the smallest value that can be returned, must be non-negative
  187.      * @param endExclusive   the upper bound (not included)
  188.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  189.      *                                  negative
  190.      * @return the random integer
  191.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  192.      */
  193.     @Deprecated
  194.     public static int nextInt(final int startInclusive, final int endExclusive) {
  195.         return secure().randomInt(startInclusive, endExclusive);
  196.     }

  197.     /**
  198.      * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive).
  199.      *
  200.      * @return the random long
  201.      * @see #nextLong(long, long)
  202.      * @since 3.5
  203.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  204.      */
  205.     @Deprecated
  206.     public static long nextLong() {
  207.         return secure().randomLong();
  208.     }

  209.     /**
  210.      * Generates a random long within the specified range.
  211.      *
  212.      * @param startInclusive the smallest value that can be returned, must be non-negative
  213.      * @param endExclusive   the upper bound (not included)
  214.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  215.      *                                  negative
  216.      * @return the random long
  217.      * @deprecated Use {@link #secure()}, {@link #secureStrong()},or {@link #insecure()}.
  218.      */
  219.     @Deprecated
  220.     public static long nextLong(final long startInclusive, final long endExclusive) {
  221.         return secure().randomLong(startInclusive, endExclusive);
  222.     }

  223.     /**
  224.      * Gets the singleton instance based on {@link SecureRandom#SecureRandom()} which uses an algorithms/providers
  225.      * specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
  226.      * <p>
  227.      * The method {@link SecureRandom#SecureRandom()} is called on-demand.
  228.      * </p>
  229.      *
  230.      * @return the singleton instance based on {@link SecureRandom#SecureRandom()}.
  231.      * @see SecureRandom#SecureRandom()
  232.      * @since 3.16.0
  233.      */
  234.     public static RandomUtils secure() {
  235.         return SECURE;
  236.     }

  237.     static SecureRandom secureRandom() {
  238.         return SECURE_RANDOM_STRONG.get();
  239.     }

  240.     /**
  241.      * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers
  242.      * specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
  243.      * <p>
  244.      * The method {@link SecureRandom#getInstanceStrong()} is called on-demand.
  245.      * </p>
  246.      *
  247.      * @return the singleton instance based on {@link SecureRandom#getInstanceStrong()}.
  248.      * @see SecureRandom#getInstanceStrong()
  249.      * @since 3.17.0
  250.      */
  251.     public static RandomUtils secureStrong() {
  252.         return SECURE_STRONG;
  253.     }

  254.     private final Supplier<Random> random;

  255.     /**
  256.      * {@link RandomUtils} instances should NOT be constructed in standard programming. Instead, the class should be
  257.      * used as {@code RandomUtils.nextBytes(5);}.
  258.      * <p>
  259.      * This constructor is public to permit tools that require a JavaBean instance to operate.
  260.      * </p>
  261.      *
  262.      * @deprecated TODO Make private in 4.0.
  263.      */
  264.     @Deprecated
  265.     public RandomUtils() {
  266.         this(SECURE_STRONG_SUPPLIER);
  267.     }

  268.     private RandomUtils(final Supplier<Random> random) {
  269.         this.random = random;
  270.     }

  271.     Random random() {
  272.         return random.get();
  273.     }

  274.     /**
  275.      * Generates a random boolean value.
  276.      *
  277.      * @return the random boolean
  278.      * @since 3.16.0
  279.      */
  280.     public boolean randomBoolean() {
  281.         return random().nextBoolean();
  282.     }

  283.     /**
  284.      * Generates an array of random bytes.
  285.      *
  286.      * @param count the size of the returned array
  287.      * @return the random byte array
  288.      * @throws IllegalArgumentException if {@code count} is negative
  289.      * @since 3.16.0
  290.      */
  291.     public byte[] randomBytes(final int count) {
  292.         Validate.isTrue(count >= 0, "Count cannot be negative.");
  293.         final byte[] result = new byte[count];
  294.         random().nextBytes(result);
  295.         return result;
  296.     }

  297.     /**
  298.      * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive).
  299.      *
  300.      * @return the random double
  301.      * @see #randomDouble(double, double)
  302.      * @since 3.16.0
  303.      */
  304.     public double randomDouble() {
  305.         return randomDouble(0, Double.MAX_VALUE);
  306.     }

  307.     /**
  308.      * Generates a random double within the specified range.
  309.      *
  310.      * @param startInclusive the smallest value that can be returned, must be non-negative
  311.      * @param endExclusive   the upper bound (not included)
  312.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  313.      *                                  negative
  314.      * @return the random double
  315.      * @since 3.16.0
  316.      */
  317.     public double randomDouble(final double startInclusive, final double endExclusive) {
  318.         Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value.");
  319.         Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
  320.         if (startInclusive == endExclusive) {
  321.             return startInclusive;
  322.         }
  323.         return startInclusive + (endExclusive - startInclusive) * random().nextDouble();
  324.     }

  325.     /**
  326.      * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive).
  327.      *
  328.      * @return the random float
  329.      * @see #randomFloat(float, float)
  330.      * @since 3.16.0
  331.      */
  332.     public float randomFloat() {
  333.         return randomFloat(0, Float.MAX_VALUE);
  334.     }

  335.     /**
  336.      * Generates a random float within the specified range.
  337.      *
  338.      * @param startInclusive the smallest value that can be returned, must be non-negative
  339.      * @param endExclusive   the upper bound (not included)
  340.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  341.      *                                  negative
  342.      * @return the random float
  343.      */
  344.     public float randomFloat(final float startInclusive, final float endExclusive) {
  345.         Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value.");
  346.         Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
  347.         if (startInclusive == endExclusive) {
  348.             return startInclusive;
  349.         }
  350.         return startInclusive + (endExclusive - startInclusive) * random().nextFloat();
  351.     }

  352.     /**
  353.      * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive).
  354.      *
  355.      * @return the random integer
  356.      * @see #randomInt(int, int)
  357.      * @since 3.16.0
  358.      */
  359.     public int randomInt() {
  360.         return randomInt(0, Integer.MAX_VALUE);
  361.     }

  362.     /**
  363.      * Generates a random integer within the specified range.
  364.      *
  365.      * @param startInclusive the smallest value that can be returned, must be non-negative
  366.      * @param endExclusive   the upper bound (not included)
  367.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  368.      *                                  negative
  369.      * @return the random integer
  370.      * @since 3.16.0
  371.      */
  372.     public int randomInt(final int startInclusive, final int endExclusive) {
  373.         Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value.");
  374.         Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
  375.         if (startInclusive == endExclusive) {
  376.             return startInclusive;
  377.         }
  378.         return startInclusive + random().nextInt(endExclusive - startInclusive);
  379.     }

  380.     /**
  381.      * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive).
  382.      *
  383.      * @return the random long
  384.      * @see #randomLong(long, long)
  385.      * @since 3.16.0
  386.      */
  387.     public long randomLong() {
  388.         return randomLong(Long.MAX_VALUE);
  389.     }

  390.     /**
  391.      * Generates a {@code long} value between 0 (inclusive) and the specified value (exclusive).
  392.      *
  393.      * @param n Bound on the random number to be returned. Must be positive.
  394.      * @return a random {@code long} value between 0 (inclusive) and {@code n} (exclusive).
  395.      */
  396.     private long randomLong(final long n) {
  397.         // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long)
  398.         long bits;
  399.         long val;
  400.         do {
  401.             bits = random().nextLong() >>> 1;
  402.             val = bits % n;
  403.         } while (bits - val + n - 1 < 0);
  404.         return val;
  405.     }

  406.     /**
  407.      * Generates a random long within the specified range.
  408.      *
  409.      * @param startInclusive the smallest value that can be returned, must be non-negative
  410.      * @param endExclusive   the upper bound (not included)
  411.      * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is
  412.      *                                  negative
  413.      * @return the random long
  414.      * @since 3.16.0
  415.      */
  416.     public long randomLong(final long startInclusive, final long endExclusive) {
  417.         Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value.");
  418.         Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
  419.         if (startInclusive == endExclusive) {
  420.             return startInclusive;
  421.         }
  422.         return startInclusive + randomLong(endExclusive - startInclusive);
  423.     }

  424.     @Override
  425.     public String toString() {
  426.         return "RandomUtils [random=" + random() + "]";
  427.     }

  428. }