Java tutorial
/** * Copyright (C) 2016 Stichting PALGA * This file is distributed under the GNU Affero General Public License * (see accompanying file <a href="{@docRoot}/LICENSE">LICENSE</a>). */ package business.security; import java.math.BigInteger; import java.security.SecureRandom; import java.util.UUID; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import business.validation.PasswordValidator; public class SecureTokenGenerator { private static SecureRandom rng = new SecureRandom(); public static String generateToken() { return new BigInteger(130, rng).toString(32); } private final static String[] letters = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; private final static String[] specials = { "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "-", "+", "\\", "|", "{", "}", "[", "]", "/", "?", "<", ">", ",", ".", "`" }; private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); /** * Generates a password that is valid for the {@link PasswordValidator}. * * Rationale behind this function: * - Generate a long enough secure pseudo random string that contains at * least a number, a letter and a 'special character'. * - The number, letter and special character are explicitely chosen * (one letter, one special character and a random number between 0 and 1024). * - A long enough secure random string is generated by using the * {@link SecureRandom} generator and {@link BigInteger} to generate a * very large random number (in base 32 encoding). Because theoretically * this could be not long enough (in number of characters), the * {@link BCryptPasswordEncoder} is applied to that number as well. * - All these values are concatenated. * * Note: for the alphanumerical part, probably {@link UUID.randomUUID()} * would suffice as well. * * @return the password. */ public static String generatePassword() { String special = specials[rng.nextInt(specials.length)]; String letter = letters[rng.nextInt(letters.length)]; String number = new BigInteger(10, rng).toString(10); String alphanumerical = passwordEncoder.encode(generateToken()); return alphanumerical + special + letter + number; } }