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 final RandomUtils INSECURE = new RandomUtils(ThreadLocalRandom::current); 074 075 private static final 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 final 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>; for more secure processing use {@link #secure()} or {@link #secureStrong()}. 092 * <p> 093 * The method {@link ThreadLocalRandom#current()} is called on-demand. 094 * </p> 095 * 096 * @return The singleton instance based on {@link ThreadLocalRandom#current()}. 097 * @see ThreadLocalRandom#current() 098 * @see #secure() 099 * @see #secureStrong() 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 Thrown 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 {@link Double#MAX_VALUE} ({@value 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 * <p> 147 * If the bounds are equal, returns the common bound. If {@code startInclusive} is finite and {@code endExclusive} is positive infinity, returns 148 * {@link Double#MAX_VALUE}. 149 * </p> 150 * 151 * @param startInclusive The smallest value that can be returned, must be non-negative. 152 * @param endExclusive The upper bound (not included). 153 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 154 * @return The random double. 155 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 156 */ 157 @Deprecated 158 public static double nextDouble(final double startInclusive, final double endExclusive) { 159 return secure().randomDouble(startInclusive, endExclusive); 160 } 161 162 /** 163 * Generates a random float between 0 (inclusive) and {@link Float#MAX_VALUE} ({@value Float#MAX_VALUE} exclusive). 164 * 165 * @return The random float. 166 * @see #nextFloat(float, float) 167 * @since 3.5 168 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 169 */ 170 @Deprecated 171 public static float nextFloat() { 172 return secure().randomFloat(); 173 } 174 175 /** 176 * Generates a random float within the specified range. 177 * 178 * <p>If the bounds are equal, returns the common bound. If {@code startInclusive} is finite and {@code endExclusive} is positive infinity, 179 * returns {@link Float#MAX_VALUE}.</p> 180 * 181 * @param startInclusive The smallest value that can be returned, must be non-negative. 182 * @param endExclusive The upper bound (not included). 183 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 184 * @return The random float. 185 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 186 */ 187 @Deprecated 188 public static float nextFloat(final float startInclusive, final float endExclusive) { 189 return secure().randomFloat(startInclusive, endExclusive); 190 } 191 192 /** 193 * Generates a random int between 0 (inclusive) and {@link Integer#MAX_VALUE} ({@value Integer#MAX_VALUE} exclusive). 194 * 195 * @return The random integer. 196 * @see #nextInt(int, int) 197 * @since 3.5 198 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 199 */ 200 @Deprecated 201 public static int nextInt() { 202 return secure().randomInt(); 203 } 204 205 /** 206 * Generates a random integer within the specified range. 207 * 208 * @param startInclusive The smallest value that can be returned, must be non-negative. 209 * @param endExclusive The upper bound (not included). 210 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 211 * @return The random integer. 212 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 213 */ 214 @Deprecated 215 public static int nextInt(final int startInclusive, final int endExclusive) { 216 return secure().randomInt(startInclusive, endExclusive); 217 } 218 219 /** 220 * Generates a random long between 0 (inclusive) and {@link Long#MAX_VALUE} ({@value Long#MAX_VALUE} exclusive). 221 * 222 * @return The random long. 223 * @see #nextLong(long, long) 224 * @since 3.5 225 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 226 */ 227 @Deprecated 228 public static long nextLong() { 229 return secure().randomLong(); 230 } 231 232 /** 233 * Generates a random long within the specified range. 234 * 235 * @param startInclusive The smallest value that can be returned, must be non-negative. 236 * @param endExclusive The upper bound (not included). 237 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 238 * @return The random long. 239 * @deprecated Use {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}. 240 */ 241 @Deprecated 242 public static long nextLong(final long startInclusive, final long endExclusive) { 243 return secure().randomLong(startInclusive, endExclusive); 244 } 245 246 /** 247 * Gets the singleton instance based on {@link SecureRandom#SecureRandom()} which uses the default algorithm 248 * and provider of {@link SecureRandom}. 249 * <p> 250 * The method {@link SecureRandom#SecureRandom()} is called on-demand. 251 * </p> 252 * 253 * @return The singleton instance based on {@link SecureRandom#SecureRandom()}. 254 * @see SecureRandom#SecureRandom() 255 * @since 3.16.0 256 */ 257 public static RandomUtils secure() { 258 return SECURE; 259 } 260 261 static SecureRandom secureRandom() { 262 return SECURE_RANDOM_STRONG.get(); 263 } 264 265 /** 266 * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers 267 * specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 268 * <p> 269 * The method {@link SecureRandom#getInstanceStrong()} is called on-demand. 270 * </p> 271 * 272 * @return The singleton instance based on {@link SecureRandom#getInstanceStrong()}. 273 * @see SecureRandom#getInstanceStrong() 274 * @since 3.17.0 275 */ 276 public static RandomUtils secureStrong() { 277 return SECURE_STRONG; 278 } 279 280 private final Supplier<Random> random; 281 282 /** 283 * {@link RandomUtils} instances should NOT be constructed in standard programming. Instead, the class should be 284 * used as {@code RandomUtils.nextBytes(5);}. 285 * <p> 286 * This constructor is public to permit tools that require a JavaBean instance to operate. 287 * </p> 288 * 289 * @deprecated TODO Make private in 4.0. 290 */ 291 @Deprecated 292 public RandomUtils() { 293 this(SECURE_STRONG_SUPPLIER); 294 } 295 296 private RandomUtils(final Supplier<Random> random) { 297 this.random = random; 298 } 299 300 Random random() { 301 return random.get(); 302 } 303 304 /** 305 * Generates a random boolean value. 306 * 307 * @return The random boolean. 308 * @since 3.16.0 309 */ 310 public boolean randomBoolean() { 311 return random().nextBoolean(); 312 } 313 314 /** 315 * Generates an array of random bytes. 316 * 317 * @param count The size of the returned array. 318 * @return The random byte array. 319 * @throws IllegalArgumentException Thrown if {@code count} is negative. 320 * @since 3.16.0 321 */ 322 public byte[] randomBytes(final int count) { 323 Validate.isTrue(count >= 0, "Count cannot be negative."); 324 final byte[] result = new byte[count]; 325 random().nextBytes(result); 326 return result; 327 } 328 329 /** 330 * Generates a random double between 0 (inclusive) and {@link Double#MAX_VALUE} ({@value Double#MAX_VALUE} exclusive). 331 * 332 * @return The random double. 333 * @see #randomDouble(double, double) 334 * @since 3.16.0 335 */ 336 public double randomDouble() { 337 return randomDouble(0, Double.MAX_VALUE); 338 } 339 340 /** 341 * Generates a random double within the specified range. 342 * 343 * <p>If the bounds are equal, returns the common bound. If {@code startInclusive} is finite and {@code endExclusive} is positive infinity, 344 * returns {@link Double#MAX_VALUE}.</p> 345 * 346 * @param startInclusive The smallest value that can be returned, must be non-negative. 347 * @param endExclusive The upper bound (not included). 348 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 349 * @return The random double. 350 * @since 3.16.0 351 */ 352 public double randomDouble(final double startInclusive, final double endExclusive) { 353 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 354 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 355 if (startInclusive == endExclusive) { 356 return startInclusive; 357 } 358 final double result = startInclusive + (endExclusive - startInclusive) * random().nextDouble(); 359 // Rounding in the scaling above can reach endExclusive; clamp to the greatest value below endExclusive. 360 return result < endExclusive ? result : Math.nextDown(endExclusive); 361 } 362 363 /** 364 * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive). 365 * 366 * @return The random float. 367 * @see #randomFloat(float, float) 368 * @since 3.16.0 369 */ 370 public float randomFloat() { 371 return randomFloat(0, Float.MAX_VALUE); 372 } 373 374 /** 375 * Generates a random float within the specified range. 376 * 377 * <p>If the bounds are equal, returns the common bound. If {@code startInclusive} is finite and {@code endExclusive} is positive infinity, 378 * returns {@link Float#MAX_VALUE}.</p> 379 * 380 * @param startInclusive The smallest value that can be returned, must be non-negative. 381 * @param endExclusive The upper bound (not included). 382 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 383 * @return The random float. 384 * @since 3.16.0 385 */ 386 public float randomFloat(final float startInclusive, final float endExclusive) { 387 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 388 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 389 if (startInclusive == endExclusive) { 390 return startInclusive; 391 } 392 final float result = startInclusive + (endExclusive - startInclusive) * random().nextFloat(); 393 // Rounding in the scaling above can reach endExclusive; clamp to the greatest value below endExclusive. 394 return result < endExclusive ? result : Math.nextDown(endExclusive); 395 } 396 397 /** 398 * Generates a random int between 0 (inclusive) and {@link Integer#MAX_VALUE} ({@value Integer#MAX_VALUE} exclusive). 399 * 400 * @return The random integer. 401 * @see #randomInt(int, int) 402 * @since 3.16.0 403 */ 404 public int randomInt() { 405 return randomInt(0, Integer.MAX_VALUE); 406 } 407 408 /** 409 * Generates a random integer within the specified range. 410 * 411 * @param startInclusive The smallest value that can be returned, must be non-negative. 412 * @param endExclusive The upper bound (not included). 413 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 414 * @return The random integer. 415 * @since 3.16.0 416 */ 417 public int randomInt(final int startInclusive, final int endExclusive) { 418 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 419 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 420 if (startInclusive == endExclusive) { 421 return startInclusive; 422 } 423 return startInclusive + random().nextInt(endExclusive - startInclusive); 424 } 425 426 /** 427 * Generates a random long between 0 (inclusive) and {@link Long#MAX_VALUE} ({@value Long#MAX_VALUE}, exclusive). 428 * 429 * @return The random long. 430 * @see #randomLong(long, long) 431 * @since 3.16.0 432 */ 433 public long randomLong() { 434 return randomLong(Long.MAX_VALUE); 435 } 436 437 /** 438 * Generates a {@code long} value between 0 (inclusive) and the specified value (exclusive). 439 * 440 * @param n Bound on the random number to be returned. Must be positive. 441 * @return A random {@code long} value between 0 (inclusive) and {@code n} (exclusive). 442 */ 443 private long randomLong(final long n) { 444 // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long) 445 long bits; 446 long val; 447 do { 448 bits = random().nextLong() >>> 1; 449 val = bits % n; 450 } while (bits - val + n - 1 < 0); 451 return val; 452 } 453 454 /** 455 * Generates a random long within the specified range. 456 * 457 * @param startInclusive The smallest value that can be returned, must be non-negative. 458 * @param endExclusive The upper bound (not included). 459 * @throws IllegalArgumentException Thrown if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative. 460 * @return The random long. 461 * @since 3.16.0 462 */ 463 public long randomLong(final long startInclusive, final long endExclusive) { 464 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 465 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 466 if (startInclusive == endExclusive) { 467 return startInclusive; 468 } 469 return startInclusive + randomLong(endExclusive - startInclusive); 470 } 471 472 @Override 473 public String toString() { 474 return "RandomUtils [random=" + random() + "]"; 475 } 476 477}