001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.security.NoSuchAlgorithmException; 020import java.security.SecureRandom; 021import java.security.Security; 022import java.util.Random; 023import java.util.concurrent.ThreadLocalRandom; 024import java.util.function.Supplier; 025 026import org.apache.commons.lang3.exception.UncheckedException; 027 028/** 029 * Supplements the standard {@link Random} class. 030 * <p> 031 * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator implementing the 032 * default random number algorithm. 033 * </p> 034 * <p> 035 * Use {@link #secureStrong()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an instance that was selected by using 036 * the algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 037 * </p> 038 * <p> 039 * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()} <strong>which is not cryptographically secure</strong>. In addition, 040 * instances do not use a cryptographically random seed unless the {@linkplain System#getProperty system property} {@code java.util.secureRandomSeed} is set to 041 * {@code true}. 042 * </p> 043 * <p> 044 * Starting in version 3.17.0, the method {@link #secure()} uses {@link SecureRandom#SecureRandom()} instead of {@link SecureRandom#getInstanceStrong()}, and 045 * adds {@link #secureStrong()}. 046 * </p> 047 * <p> 048 * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}. 049 * </p> 050 * <p> 051 * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods. 052 * </p> 053 * <p> 054 * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not cryptographically secure. 055 * </p> 056 * <p> 057 * Please note that the Apache Commons project provides a component dedicated to pseudo-random number generation, namely 058 * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a>, that may be a better choice for applications with more stringent requirements 059 * (performance and/or correctness). 060 * </p> 061 * 062 * @see #secure() 063 * @see #secureStrong() 064 * @see #insecure() 065 * @see SecureRandom#SecureRandom() 066 * @see SecureRandom#getInstanceStrong() 067 * @see ThreadLocalRandom#current() 068 * @see RandomStringUtils 069 * @since 3.3 070 */ 071public class RandomUtils { 072 073 private static RandomUtils INSECURE = new RandomUtils(ThreadLocalRandom::current); 074 075 private static RandomUtils SECURE = new RandomUtils(SecureRandom::new); 076 077 private static final Supplier<Random> SECURE_STRONG_SUPPLIER = () -> RandomUtils.SECURE_RANDOM_STRONG.get(); 078 079 private static RandomUtils SECURE_STRONG = new RandomUtils(SECURE_STRONG_SUPPLIER); 080 081 private static final ThreadLocal<SecureRandom> SECURE_RANDOM_STRONG = ThreadLocal.withInitial(() -> { 082 try { 083 return SecureRandom.getInstanceStrong(); 084 } catch (final NoSuchAlgorithmException e) { 085 throw new UncheckedException(e); 086 } 087 }); 088 089 /** 090 * Gets the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not cryptographically 091 * secure</b>; use {@link #secure()} to use an algorithms/providers specified in the 092 * {@code securerandom.strongAlgorithms} {@link Security} property. 093 * <p> 094 * The method {@link ThreadLocalRandom#current()} is called on-demand. 095 * </p> 096 * 097 * @return the singleton instance based on {@link ThreadLocalRandom#current()}. 098 * @see ThreadLocalRandom#current() 099 * @see #secure() 100 * @since 3.17.0 101 */ 102 public static RandomUtils insecure() { 103 return INSECURE; 104 } 105 106 /** 107 * Generates a random boolean value. 108 * 109 * @return the random boolean. 110 * @since 3.5 111 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 112 */ 113 @Deprecated 114 public static boolean nextBoolean() { 115 return secure().randomBoolean(); 116 } 117 118 /** 119 * Generates an array of random bytes. 120 * 121 * @param count the size of the returned array. 122 * @return the random byte array. 123 * @throws IllegalArgumentException if {@code count} is negative. 124 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 125 */ 126 @Deprecated 127 public static byte[] nextBytes(final int count) { 128 return secure().randomBytes(count); 129 } 130 131 /** 132 * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive). 133 * 134 * @return the random double. 135 * @see #nextDouble(double, double) 136 * @since 3.5 137 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 138 */ 139 @Deprecated 140 public static double nextDouble() { 141 return secure().randomDouble(); 142 } 143 144 /** 145 * Generates a random double within the specified range. 146 * 147 * @param startInclusive the smallest value that can be returned, must be non-negative. 148 * @param endExclusive the upper bound (not included). 149 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 150 * @return the random double. 151 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 152 */ 153 @Deprecated 154 public static double nextDouble(final double startInclusive, final double endExclusive) { 155 return secure().randomDouble(startInclusive, endExclusive); 156 } 157 158 /** 159 * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive). 160 * 161 * @return the random float. 162 * @see #nextFloat(float, float) 163 * @since 3.5 164 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 165 */ 166 @Deprecated 167 public static float nextFloat() { 168 return secure().randomFloat(); 169 } 170 171 /** 172 * Generates a random float within the specified range. 173 * 174 * @param startInclusive the smallest value that can be returned, must be non-negative. 175 * @param endExclusive the upper bound (not included). 176 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 177 * @return the random float 178 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 179 */ 180 @Deprecated 181 public static float nextFloat(final float startInclusive, final float endExclusive) { 182 return secure().randomFloat(startInclusive, endExclusive); 183 } 184 185 /** 186 * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive). 187 * 188 * @return the random integer. 189 * @see #nextInt(int, int) 190 * @since 3.5 191 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 192 */ 193 @Deprecated 194 public static int nextInt() { 195 return secure().randomInt(); 196 } 197 198 /** 199 * Generates a random integer within the specified range. 200 * 201 * @param startInclusive the smallest value that can be returned, must be non-negative. 202 * @param endExclusive the upper bound (not included). 203 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 204 * @return the random integer. 205 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 206 */ 207 @Deprecated 208 public static int nextInt(final int startInclusive, final int endExclusive) { 209 return secure().randomInt(startInclusive, endExclusive); 210 } 211 212 /** 213 * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive). 214 * 215 * @return the random long. 216 * @see #nextLong(long, long) 217 * @since 3.5 218 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 219 */ 220 @Deprecated 221 public static long nextLong() { 222 return secure().randomLong(); 223 } 224 225 /** 226 * Generates a random long within the specified range. 227 * 228 * @param startInclusive the smallest value that can be returned, must be non-negative. 229 * @param endExclusive the upper bound (not included). 230 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 231 * @return the random long. 232 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 233 */ 234 @Deprecated 235 public static long nextLong(final long startInclusive, final long endExclusive) { 236 return secure().randomLong(startInclusive, endExclusive); 237 } 238 239 /** 240 * Gets the singleton instance based on {@link SecureRandom#SecureRandom()} which uses an algorithms/providers 241 * specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 242 * <p> 243 * The method {@link SecureRandom#SecureRandom()} is called on-demand. 244 * </p> 245 * 246 * @return the singleton instance based on {@link SecureRandom#SecureRandom()}. 247 * @see SecureRandom#SecureRandom() 248 * @since 3.16.0 249 */ 250 public static RandomUtils secure() { 251 return SECURE; 252 } 253 254 static SecureRandom secureRandom() { 255 return SECURE_RANDOM_STRONG.get(); 256 } 257 258 /** 259 * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers 260 * specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 261 * <p> 262 * The method {@link SecureRandom#getInstanceStrong()} is called on-demand. 263 * </p> 264 * 265 * @return the singleton instance based on {@link SecureRandom#getInstanceStrong()}. 266 * @see SecureRandom#getInstanceStrong() 267 * @since 3.17.0 268 */ 269 public static RandomUtils secureStrong() { 270 return SECURE_STRONG; 271 } 272 273 private final Supplier<Random> random; 274 275 /** 276 * {@link RandomUtils} instances should NOT be constructed in standard programming. Instead, the class should be 277 * used as {@code RandomUtils.nextBytes(5);}. 278 * <p> 279 * This constructor is public to permit tools that require a JavaBean instance to operate. 280 * </p> 281 * 282 * @deprecated TODO Make private in 4.0. 283 */ 284 @Deprecated 285 public RandomUtils() { 286 this(SECURE_STRONG_SUPPLIER); 287 } 288 289 private RandomUtils(final Supplier<Random> random) { 290 this.random = random; 291 } 292 293 Random random() { 294 return random.get(); 295 } 296 297 /** 298 * Generates a random boolean value. 299 * 300 * @return the random boolean. 301 * @since 3.16.0 302 */ 303 public boolean randomBoolean() { 304 return random().nextBoolean(); 305 } 306 307 /** 308 * Generates an array of random bytes. 309 * 310 * @param count the size of the returned array. 311 * @return the random byte array. 312 * @throws IllegalArgumentException if {@code count} is negative 313 * @since 3.16.0 314 */ 315 public byte[] randomBytes(final int count) { 316 Validate.isTrue(count >= 0, "Count cannot be negative."); 317 final byte[] result = new byte[count]; 318 random().nextBytes(result); 319 return result; 320 } 321 322 /** 323 * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive). 324 * 325 * @return the random double. 326 * @see #randomDouble(double, double) 327 * @since 3.16.0 328 */ 329 public double randomDouble() { 330 return randomDouble(0, Double.MAX_VALUE); 331 } 332 333 /** 334 * Generates a random double within the specified range. 335 * 336 * @param startInclusive the smallest value that can be returned, must be non-negative. 337 * @param endExclusive the upper bound (not included). 338 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 339 * @return the random double 340 * @since 3.16.0 341 */ 342 public double randomDouble(final double startInclusive, final double endExclusive) { 343 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 344 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 345 if (startInclusive == endExclusive) { 346 return startInclusive; 347 } 348 return startInclusive + (endExclusive - startInclusive) * random().nextDouble(); 349 } 350 351 /** 352 * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive). 353 * 354 * @return the random float. 355 * @see #randomFloat(float, float) 356 * @since 3.16.0 357 */ 358 public float randomFloat() { 359 return randomFloat(0, Float.MAX_VALUE); 360 } 361 362 /** 363 * Generates a random float 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 negative. 368 * @return the random float. 369 */ 370 public float randomFloat(final float startInclusive, final float endExclusive) { 371 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 372 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 373 if (startInclusive == endExclusive) { 374 return startInclusive; 375 } 376 return startInclusive + (endExclusive - startInclusive) * random().nextFloat(); 377 } 378 379 /** 380 * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive). 381 * 382 * @return the random integer. 383 * @see #randomInt(int, int) 384 * @since 3.16.0 385 */ 386 public int randomInt() { 387 return randomInt(0, Integer.MAX_VALUE); 388 } 389 390 /** 391 * Generates a random integer within the specified range. 392 * 393 * @param startInclusive the smallest value that can be returned, must be non-negative. 394 * @param endExclusive the upper bound (not included). 395 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 396 * @return the random integer. 397 * @since 3.16.0 398 */ 399 public int randomInt(final int startInclusive, final int endExclusive) { 400 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 401 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 402 if (startInclusive == endExclusive) { 403 return startInclusive; 404 } 405 return startInclusive + random().nextInt(endExclusive - startInclusive); 406 } 407 408 /** 409 * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive). 410 * 411 * @return the random long. 412 * @see #randomLong(long, long) 413 * @since 3.16.0 414 */ 415 public long randomLong() { 416 return randomLong(Long.MAX_VALUE); 417 } 418 419 /** 420 * Generates a {@code long} value between 0 (inclusive) and the specified value (exclusive). 421 * 422 * @param n Bound on the random number to be returned. Must be positive. 423 * @return a random {@code long} value between 0 (inclusive) and {@code n} (exclusive). 424 */ 425 private long randomLong(final long n) { 426 // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long) 427 long bits; 428 long val; 429 do { 430 bits = random().nextLong() >>> 1; 431 val = bits % n; 432 } while (bits - val + n - 1 < 0); 433 return val; 434 } 435 436 /** 437 * Generates a random long within the specified range. 438 * 439 * @param startInclusive the smallest value that can be returned, must be non-negative. 440 * @param endExclusive the upper bound (not included). 441 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 442 * @return the random long. 443 * @since 3.16.0 444 */ 445 public long randomLong(final long startInclusive, final long endExclusive) { 446 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 447 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 448 if (startInclusive == endExclusive) { 449 return startInclusive; 450 } 451 return startInclusive + randomLong(endExclusive - startInclusive); 452 } 453 454 @Override 455 public String toString() { 456 return "RandomUtils [random=" + random() + "]"; 457 } 458 459}