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