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