/*******************************************************************************
* Copyright (c) 2013 Lectorius, Inc.
* Authors:
* Vijay Pandurangan (vijayp@mitro.co)
* Evan Jones (ej@mitro.co)
* Adam Hilss (ahilss@mitro.co)
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact the authors at inbound@mitro.co.
*******************************************************************************/
package co.mitro.core.util;
import java.security.SecureRandom;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Random {
private static int fillCharRange(char start, char endInclusive, char[] output, int index) {
for (char c = start; c <= endInclusive; c++) {
output[index] = c;
index += 1;
}
return index;
}
protected static char[] makeAlphaNumChars() {
char[] output = new char[26+26+10];
int index = fillCharRange('a', 'z', output, 0);
index = fillCharRange('A', 'Z', output, index);
index = fillCharRange('0', '9', output, index);
assert index == output.length;
return output;
}
private static final char[] ALPHANUM = makeAlphaNumChars();
// caches SecureRandom objects because they are expensive
private static final ConcurrentLinkedQueue<SecureRandom> RNG_QUEUE =
new ConcurrentLinkedQueue<SecureRandom>();
/** Returns a secure random password with numChars alpha numeric characters. */
public static String makeRandomAlphanumericString(int numChars) {
SecureRandom rng = RNG_QUEUE.poll();
if (rng == null) {
// automatically seeded on first use
rng = new SecureRandom();
}
StringBuilder output = new StringBuilder(numChars);
while (output.length() != numChars) {
// nextInt()'s algorithm is unbiased, so this will select an unbiased char from ALPHANUM
int index = rng.nextInt(ALPHANUM.length);
output.append(ALPHANUM[index]);
}
RNG_QUEUE.add(rng);
return output.toString();
}
}