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