1
14
15 package com.liferay.portal.security.pwd;
16
17 import com.liferay.portal.PwdEncryptorException;
18 import com.liferay.portal.kernel.util.Base64;
19 import com.liferay.portal.kernel.util.Digester;
20 import com.liferay.portal.kernel.util.DigesterUtil;
21 import com.liferay.portal.kernel.util.GetterUtil;
22 import com.liferay.portal.kernel.util.PropsKeys;
23 import com.liferay.portal.kernel.util.Validator;
24 import com.liferay.portal.util.PropsUtil;
25
26 import java.io.UnsupportedEncodingException;
27
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.security.SecureRandom;
31
32 import java.util.Random;
33
34 import org.vps.crypt.Crypt;
35
36
42 public class PwdEncryptor {
43
44 public static final String PASSWORDS_ENCRYPTION_ALGORITHM =
45 GetterUtil.getString(PropsUtil.get(
46 PropsKeys.PASSWORDS_ENCRYPTION_ALGORITHM)).toUpperCase();
47
48 public static final String TYPE_CRYPT = "CRYPT";
49
50 public static final String TYPE_MD2 = "MD2";
51
52 public static final String TYPE_MD5 = "MD5";
53
54 public static final String TYPE_NONE = "NONE";
55
56 public static final String TYPE_SHA = "SHA";
57
58 public static final String TYPE_SHA_256 = "SHA-256";
59
60 public static final String TYPE_SHA_384 = "SHA-384";
61
62 public static final String TYPE_SSHA = "SSHA";
63
64 public static final char[] saltChars =
65 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
66 .toCharArray();
67
68 public static String encrypt(String clearTextPassword)
69 throws PwdEncryptorException {
70
71 return encrypt(PASSWORDS_ENCRYPTION_ALGORITHM, clearTextPassword, null);
72 }
73
74 public static String encrypt(
75 String clearTextPassword, String currentEncryptedPassword)
76 throws PwdEncryptorException {
77
78 return encrypt(
79 PASSWORDS_ENCRYPTION_ALGORITHM, clearTextPassword,
80 currentEncryptedPassword);
81 }
82
83 public static String encrypt(
84 String algorithm, String clearTextPassword,
85 String currentEncryptedPassword)
86 throws PwdEncryptorException {
87
88 if (algorithm.equals(TYPE_CRYPT)) {
89 byte[] saltBytes = _getSaltFromCrypt(currentEncryptedPassword);
90
91 return encodePassword(algorithm, clearTextPassword, saltBytes);
92 }
93 else if (algorithm.equals(TYPE_NONE)) {
94 return clearTextPassword;
95 }
96 else if (algorithm.equals(TYPE_SSHA)) {
97 byte[] saltBytes = _getSaltFromSSHA(currentEncryptedPassword);
98
99 return encodePassword(algorithm, clearTextPassword, saltBytes);
100 }
101 else {
102 return encodePassword(algorithm, clearTextPassword, null);
103 }
104 }
105
106 protected static String encodePassword(
107 String algorithm, String clearTextPassword, byte[] saltBytes)
108 throws PwdEncryptorException {
109
110 try {
111 if (algorithm.equals(TYPE_CRYPT)) {
112 return Crypt.crypt(
113 saltBytes, clearTextPassword.getBytes(Digester.ENCODING));
114 }
115 else if (algorithm.equals(TYPE_SSHA)) {
116 byte[] clearTextPasswordBytes =
117 clearTextPassword.getBytes(Digester.ENCODING);
118
119
121 byte[] pwdPlusSalt =
122 new byte[clearTextPasswordBytes.length + saltBytes.length];
123
124 System.arraycopy(
125 clearTextPasswordBytes, 0, pwdPlusSalt, 0,
126 clearTextPasswordBytes.length);
127
128 System.arraycopy(
129 saltBytes, 0, pwdPlusSalt, clearTextPasswordBytes.length,
130 saltBytes.length);
131
132
134 MessageDigest sha1Digest = MessageDigest.getInstance("SHA-1");
135
136 byte[] pwdPlusSaltHash = sha1Digest.digest(pwdPlusSalt);
137
138
140 byte[] digestPlusSalt =
141 new byte[pwdPlusSaltHash.length + saltBytes.length];
142
143 System.arraycopy(
144 pwdPlusSaltHash, 0, digestPlusSalt, 0,
145 pwdPlusSaltHash.length);
146
147 System.arraycopy(
148 saltBytes, 0, digestPlusSalt, pwdPlusSaltHash.length,
149 saltBytes.length);
150
151
153 return Base64.encode(digestPlusSalt);
154 }
155 else {
156 return DigesterUtil.digest(algorithm, clearTextPassword);
157 }
158 }
159 catch (NoSuchAlgorithmException nsae) {
160 throw new PwdEncryptorException(nsae.getMessage());
161 }
162 catch (UnsupportedEncodingException uee) {
163 throw new PwdEncryptorException(uee.getMessage());
164 }
165 }
166
167 private static byte[] _getSaltFromCrypt(String cryptString)
168 throws PwdEncryptorException {
169
170 byte[] saltBytes = null;
171
172 try {
173 if (Validator.isNull(cryptString)) {
174
175
177 Random random = new Random();
178
179 int numSaltChars = saltChars.length;
180
181 StringBuilder sb = new StringBuilder();
182
183 int x = random.nextInt(Integer.MAX_VALUE) % numSaltChars;
184 int y = random.nextInt(Integer.MAX_VALUE) % numSaltChars;
185
186 sb.append(saltChars[x]);
187 sb.append(saltChars[y]);
188
189 String salt = sb.toString();
190
191 saltBytes = salt.getBytes(Digester.ENCODING);
192 }
193 else {
194
195
197 String salt = cryptString.substring(0, 2);
198
199 saltBytes = salt.getBytes(Digester.ENCODING);
200 }
201 }
202 catch (UnsupportedEncodingException uee) {
203 throw new PwdEncryptorException(
204 "Unable to extract salt from encrypted password: " +
205 uee.getMessage());
206 }
207
208 return saltBytes;
209 }
210
211 private static byte[] _getSaltFromSSHA(String sshaString)
212 throws PwdEncryptorException {
213
214 byte[] saltBytes = new byte[8];
215
216 if (Validator.isNull(sshaString)) {
217
218
220 Random random = new SecureRandom();
221
222 random.nextBytes(saltBytes);
223 }
224 else {
225
226
228 try {
229 byte[] digestPlusSalt = Base64.decode(sshaString);
230 byte[] digestBytes = new byte[digestPlusSalt.length - 8];
231
232 System.arraycopy(
233 digestPlusSalt, 0, digestBytes, 0, digestBytes.length);
234
235 System.arraycopy(
236 digestPlusSalt, digestBytes.length, saltBytes, 0,
237 saltBytes.length);
238 }
239 catch (Exception e) {
240 throw new PwdEncryptorException(
241 "Unable to extract salt from encrypted password: " +
242 e.getMessage());
243 }
244 }
245
246 return saltBytes;
247 }
248
249 }