2 * Copyright (C) 2016 Roland Haeder
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.jusercore.model.user;
19 import java.io.Serializable;
20 import java.security.SecureRandom;
21 import java.text.MessageFormat;
22 import java.util.Random;
23 import org.apache.commons.codec.digest.Crypt;
24 import org.mxchange.jusercore.container.login.LoginContainer;
25 import org.mxchange.jusercore.container.login.UserLoginContainer;
28 * An utilities class for users
30 * @author Roland Haeder<roland@mxchange.org>
32 public class UserUtils implements Serializable {
37 private static final String PASSWORD_ALPHABET = "abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY0123456789-/?!_+#@"; //NOI18N
40 * Minimum password length
42 private static final Integer PASSWORD_MINIMUM_LENGTH = 5;
45 * Random number generator
47 private static final Random RANDOM_NUMBER_GENERATOR;
52 private static final long serialVersionUID = 18_356_847_120_972L;
59 RANDOM_NUMBER_GENERATOR = new SecureRandom();
63 * Creates a pseudo-random password with given length
65 * @param length Length of the password
67 * @return Pseudo-random password
69 public static String createRandomPassword (final Integer length) {
70 // Parameter should be valid
73 throw new NullPointerException("length is null"); //NOI18N
74 } else if (length < PASSWORD_MINIMUM_LENGTH) {
76 throw new IllegalArgumentException(MessageFormat.format("Password length {0} is to short, minimum: {1}", length, PASSWORD_MINIMUM_LENGTH)); //NOI18N
80 StringBuilder password = new StringBuilder(length);
83 for (int i = 0; i < length; i++) {
84 // Generate random number
85 int pos = RANDOM_NUMBER_GENERATOR.nextInt(PASSWORD_ALPHABET.length());
87 // Get char at this position and add it to the final password
88 password.append(String.valueOf(PASSWORD_ALPHABET.charAt(pos)));
91 // Should have the wanted length
92 assert (password.length() == length) : MessageFormat.format("Password length {0} doesn't match requested: {1}", password.length(), length); //NOI18N
95 return password.toString();
99 * Hashes given user password and adds a salt to it
101 * @param userPassword User password to be hashed
103 * @return Hashed user password
105 public static String encryptPassword (final String userPassword) {
106 // Is it null or empty?
107 if (null == userPassword) {
109 throw new NullPointerException("userPassword is null"); //NOI18N
110 } else if (userPassword.isEmpty()) {
111 // Empty passwords are hardcoded not allowed due to security risks
112 throw new IllegalArgumentException("userPassword is empty"); //NOI18N
115 // Generate large number
116 String number = Long.toString(RANDOM_NUMBER_GENERATOR.nextLong() * 10_000_000_000L);
119 String salt = Crypt.crypt(number);
121 // First encrypt password
122 String encryptedPassword = Crypt.crypt(userPassword, salt);
125 return encryptedPassword;
129 * Checks if password from container matches the updatedUser's password
131 * @param container Container holding user instance and unencrypted password
132 * @param updatedUser Updated user instance from database
134 * @return Whether the password matches
136 public static boolean ifPasswordMatches (final LoginContainer container, final User updatedUser) {
137 // Validate parameters
138 if (null == container) {
140 throw new NullPointerException("container is null"); //NOI18N
141 } else if (null == updatedUser) {
143 throw new NullPointerException("updatedUser is null"); //NOI18N
144 } else if (container.getUser() == null) {
145 // NPE for user in container
146 throw new NullPointerException("container.user is null"); //NOI18N
147 } else if (container.getUserPassword() == null) {
148 // NPE for user password in container
149 throw new NullPointerException("container.userPassword is null"); //NOI18N
150 } else if (container.getUserPassword().isEmpty()) {
151 // Empty password in container
152 throw new IllegalArgumentException("container.userPassword is empty"); //NOI18N
155 // First encrypt password
156 String encryptedPassword = Crypt.crypt(container.getUserPassword(), updatedUser.getUserEncryptedPassword());
159 return encryptedPassword.equals(updatedUser.getUserEncryptedPassword());
163 * Checks if password from container matches with from user instance.
165 * @param container Container holding user instance and unencrypted password
167 * @return Whether it maches
169 public static boolean ifPasswordMatches (final UserLoginContainer container) {
170 // Validate parameters
171 if (null == container) {
173 throw new NullPointerException("container is null"); //NOI18N
174 } else if (container.getUser() == null) {
175 // NPE for user in container
176 throw new NullPointerException("container.user is null"); //NOI18N
177 } else if (container.getUserPassword() == null) {
178 // NPE for user password in container
179 throw new NullPointerException("container.userPassword is null"); //NOI18N
180 } else if (container.getUserPassword().isEmpty()) {
181 // Empty password in container
182 throw new IllegalArgumentException("container.userPassword is empty"); //NOI18N
185 // First encrypt password
186 String encryptedPassword = Crypt.crypt(container.getUserPassword(), container.getUser().getUserEncryptedPassword());
189 return encryptedPassword.equals(container.getUser().getUserEncryptedPassword());
193 * No instance from this class
195 private UserUtils () {