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 * https://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
19 import java.security.NoSuchAlgorithmException;
20 import java.security.SecureRandom;
21 import java.security.Security;
22 import java.util.Random;
23 import java.util.concurrent.ThreadLocalRandom;
24 import java.util.function.Supplier;
25
26 import org.apache.commons.lang3.exception.UncheckedException;
27
28 /**
29 * Supplements the standard {@link Random} class.
30 * <p>
31 * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator implementing the
32 * default random number algorithm.
33 * </p>
34 * <p>
35 * Use {@link #secureStrong()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an instance that was selected by using
36 * the algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
37 * </p>
38 * <p>
39 * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()} <strong>which is not cryptographically secure</strong>. In addition,
40 * instances do not use a cryptographically random seed unless the {@linkplain System#getProperty system property} {@code java.util.secureRandomSeed} is set to
41 * {@code true}.
42 * </p>
43 * <p>
44 * Starting in version 3.17.0, the method {@link #secure()} uses {@link SecureRandom#SecureRandom()} instead of {@link SecureRandom#getInstanceStrong()}, and
45 * adds {@link #secureStrong()}.
46 * </p>
47 * <p>
48 * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}.
49 * </p>
50 * <p>
51 * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods.
52 * </p>
53 * <p>
54 * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not cryptographically secure.
55 * </p>
56 * <p>
57 * Please note that the Apache Commons project provides a component dedicated to pseudo-random number generation, namely
58 * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a>, that may be a better choice for applications with more stringent requirements
59 * (performance and/or correctness).
60 * </p>
61 *
62 * @see #secure()
63 * @see #secureStrong()
64 * @see #insecure()
65 * @see SecureRandom#SecureRandom()
66 * @see SecureRandom#getInstanceStrong()
67 * @see ThreadLocalRandom#current()
68 * @see RandomStringUtils
69 * @since 3.3
70 */
71 public class RandomUtils {
72
73 private static RandomUtils INSECURE = new RandomUtils(ThreadLocalRandom::current);
74
75 private static RandomUtils SECURE = new RandomUtils(SecureRandom::new);
76
77 private static final Supplier<Random> SECURE_STRONG_SUPPLIER = () -> RandomUtils.SECURE_RANDOM_STRONG.get();
78
79 private static RandomUtils SECURE_STRONG = new RandomUtils(SECURE_STRONG_SUPPLIER);
80
81 private static final ThreadLocal<SecureRandom> SECURE_RANDOM_STRONG = ThreadLocal.withInitial(() -> {
82 try {
83 return SecureRandom.getInstanceStrong();
84 } catch (final NoSuchAlgorithmException e) {
85 throw new UncheckedException(e);
86 }
87 });
88
89 /**
90 * Gets the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not cryptographically
91 * secure</b>; use {@link #secure()} to use an algorithms/providers specified in the
92 * {@code securerandom.strongAlgorithms} {@link Security} property.
93 * <p>
94 * The method {@link ThreadLocalRandom#current()} is called on-demand.
95 * </p>
96 *
97 * @return the singleton instance based on {@link ThreadLocalRandom#current()}.
98 * @see ThreadLocalRandom#current()
99 * @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 }