001
014
015 package com.liferay.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.util.Base64;
020 import com.liferay.portal.kernel.util.Digester;
021 import com.liferay.portal.kernel.util.DigesterUtil;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.PropsKeys;
024 import com.liferay.portal.kernel.util.PropsUtil;
025 import com.liferay.portal.kernel.util.ServerDetector;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.StringUtil;
028 import com.liferay.portal.kernel.util.SystemProperties;
029
030 import java.security.Key;
031 import java.security.Provider;
032 import java.security.SecureRandom;
033 import java.security.Security;
034
035 import java.util.Map;
036 import java.util.concurrent.ConcurrentHashMap;
037
038 import javax.crypto.Cipher;
039 import javax.crypto.KeyGenerator;
040 import javax.crypto.spec.SecretKeySpec;
041
042
047 public class Encryptor {
048
049 public static final String ENCODING = Digester.ENCODING;
050
051 public static final String IBM_PROVIDER_CLASS =
052 "com.ibm.crypto.provider.IBMJCE";
053
054 public static final String KEY_ALGORITHM = StringUtil.toUpperCase(
055 GetterUtil.getString(
056 PropsUtil.get(PropsKeys.COMPANY_ENCRYPTION_ALGORITHM)));
057
058 public static final int KEY_SIZE = GetterUtil.getInteger(
059 PropsUtil.get(PropsKeys.COMPANY_ENCRYPTION_KEY_SIZE));
060
061 public static final String PROVIDER_CLASS = GetterUtil.getString(
062 SystemProperties.get(Encryptor.class.getName() + ".provider.class"),
063 Encryptor.SUN_PROVIDER_CLASS);
064
065 public static final String SUN_PROVIDER_CLASS =
066 "com.sun.crypto.provider.SunJCE";
067
068 public static String decrypt(Key key, String encryptedString)
069 throws EncryptorException {
070
071 byte[] encryptedBytes = Base64.decode(encryptedString);
072
073 return decryptUnencodedAsString(key, encryptedBytes);
074 }
075
076 public static byte[] decryptUnencodedAsBytes(Key key, byte[] encryptedBytes)
077 throws EncryptorException {
078
079 String algorithm = key.getAlgorithm();
080
081 String cacheKey = algorithm.concat(StringPool.POUND).concat(
082 key.toString());
083
084 Cipher cipher = _decryptCipherMap.get(cacheKey);
085
086 try {
087 if (cipher == null) {
088 Security.addProvider(getProvider());
089
090 cipher = Cipher.getInstance(algorithm);
091
092 cipher.init(Cipher.DECRYPT_MODE, key);
093
094 _decryptCipherMap.put(cacheKey, cipher);
095 }
096
097 synchronized (cipher) {
098 return cipher.doFinal(encryptedBytes);
099 }
100 }
101 catch (Exception e) {
102 throw new EncryptorException(e);
103 }
104 }
105
106 public static String decryptUnencodedAsString(
107 Key key, byte[] encryptedBytes)
108 throws EncryptorException {
109
110 try {
111 byte[] decryptedBytes = decryptUnencodedAsBytes(
112 key, encryptedBytes);
113
114 return new String(decryptedBytes, ENCODING);
115 }
116 catch (Exception e) {
117 throw new EncryptorException(e);
118 }
119 }
120
121 public static Key deserializeKey(String base64String) {
122 byte[] bytes = Base64.decode(base64String);
123
124 return new SecretKeySpec(bytes, Encryptor.KEY_ALGORITHM);
125 }
126
127 public static String digest(String text) {
128 return DigesterUtil.digest(text);
129 }
130
131 public static String digest(String algorithm, String text) {
132 return DigesterUtil.digest(algorithm, text);
133 }
134
135 public static String encrypt(Key key, String plainText)
136 throws EncryptorException {
137
138 if (key == null) {
139 if (_log.isWarnEnabled()) {
140 _log.warn("Skip encrypting based on a null key");
141 }
142
143 return plainText;
144 }
145
146 byte[] encryptedBytes = encryptUnencoded(key, plainText);
147
148 return Base64.encode(encryptedBytes);
149 }
150
151 public static byte[] encryptUnencoded(Key key, byte[] plainBytes)
152 throws EncryptorException {
153
154 String algorithm = key.getAlgorithm();
155
156 String cacheKey = algorithm.concat(StringPool.POUND).concat(
157 key.toString());
158
159 Cipher cipher = _encryptCipherMap.get(cacheKey);
160
161 try {
162 if (cipher == null) {
163 Security.addProvider(getProvider());
164
165 cipher = Cipher.getInstance(algorithm);
166
167 cipher.init(Cipher.ENCRYPT_MODE, key);
168
169 _encryptCipherMap.put(cacheKey, cipher);
170 }
171
172 synchronized (cipher) {
173 return cipher.doFinal(plainBytes);
174 }
175 }
176 catch (Exception e) {
177 throw new EncryptorException(e);
178 }
179 }
180
181 public static byte[] encryptUnencoded(Key key, String plainText)
182 throws EncryptorException {
183
184 try {
185 byte[] decryptedBytes = plainText.getBytes(ENCODING);
186
187 return encryptUnencoded(key, decryptedBytes);
188 }
189 catch (Exception e) {
190 throw new EncryptorException(e);
191 }
192 }
193
194 public static Key generateKey() throws EncryptorException {
195 return generateKey(KEY_ALGORITHM);
196 }
197
198 public static Key generateKey(String algorithm) throws EncryptorException {
199 try {
200 Security.addProvider(getProvider());
201
202 KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
203
204 keyGenerator.init(KEY_SIZE, new SecureRandom());
205
206 Key key = keyGenerator.generateKey();
207
208 return key;
209 }
210 catch (Exception e) {
211 throw new EncryptorException(e);
212 }
213 }
214
215 public static Provider getProvider()
216 throws ClassNotFoundException, IllegalAccessException,
217 InstantiationException {
218
219 Class<?> providerClass = null;
220
221 try {
222 providerClass = Class.forName(PROVIDER_CLASS);
223 }
224 catch (ClassNotFoundException cnfe) {
225 if (ServerDetector.isWebSphere() &&
226 PROVIDER_CLASS.equals(SUN_PROVIDER_CLASS)) {
227
228 if (_log.isWarnEnabled()) {
229 _log.warn(
230 "WebSphere does not have " + SUN_PROVIDER_CLASS +
231 ", using " + IBM_PROVIDER_CLASS + " instead");
232 }
233
234 providerClass = Class.forName(IBM_PROVIDER_CLASS);
235 }
236 else if (System.getProperty("java.vm.vendor").equals(
237 "IBM Corporation")) {
238
239 if (_log.isWarnEnabled()) {
240 _log.warn(
241 "IBM JVM does not have " + SUN_PROVIDER_CLASS +
242 ", using " + IBM_PROVIDER_CLASS + " instead");
243 }
244
245 providerClass = Class.forName(IBM_PROVIDER_CLASS);
246 }
247 else {
248 throw cnfe;
249 }
250 }
251
252 return (Provider)providerClass.newInstance();
253 }
254
255 public static String serializeKey(Key key) {
256 return Base64.encode(key.getEncoded());
257 }
258
259 private static final Log _log = LogFactoryUtil.getLog(Encryptor.class);
260
261 private static final Map<String, Cipher> _decryptCipherMap =
262 new ConcurrentHashMap<>(1, 1f, 1);
263 private static final Map<String, Cipher> _encryptCipherMap =
264 new ConcurrentHashMap<>(1, 1f, 1);
265
266 }