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