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