001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
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    
028    import java.security.Key;
029    import java.security.Provider;
030    import java.security.SecureRandom;
031    import java.security.Security;
032    
033    import java.util.Map;
034    import java.util.concurrent.ConcurrentHashMap;
035    
036    import javax.crypto.Cipher;
037    import javax.crypto.KeyGenerator;
038    
039    /**
040     * @author Brian Wing Shun Chan
041     * @author Shuyang Zhou
042     */
043    public class Encryptor {
044    
045            public static final String ENCODING = Digester.ENCODING;
046    
047            public static final String KEY_ALGORITHM = GetterUtil.getString(
048                    PropsUtil.get(PropsKeys.COMPANY_ENCRYPTION_ALGORITHM)).toUpperCase();
049    
050            public static final int KEY_SIZE = GetterUtil.getInteger(
051                    PropsUtil.get(PropsKeys.COMPANY_ENCRYPTION_KEY_SIZE));
052    
053            public static final String SUN_PROVIDER_CLASS =
054                    "com.sun.crypto.provider.SunJCE";
055    
056            public static final String IBM_PROVIDER_CLASS =
057                    "com.ibm.crypto.provider.IBMJCE";
058    
059            public static final String PROVIDER_CLASS = GetterUtil.getString(
060                    SystemProperties.get(Encryptor.class.getName() + ".provider.class"),
061                    SUN_PROVIDER_CLASS);
062    
063            public static Key generateKey() throws EncryptorException {
064                    return generateKey(KEY_ALGORITHM);
065            }
066    
067            public static Key generateKey(String algorithm) throws EncryptorException {
068                    try {
069                            Security.addProvider(getProvider());
070    
071                            KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
072    
073                            keyGenerator.init(KEY_SIZE, new SecureRandom());
074    
075                            Key key = keyGenerator.generateKey();
076    
077                            return key;
078                    }
079                    catch (Exception e) {
080                            throw new EncryptorException(e);
081                    }
082            }
083    
084            public static Provider getProvider()
085                    throws ClassNotFoundException, IllegalAccessException,
086                               InstantiationException {
087    
088                    Class<?> providerClass = null;
089    
090                    try {
091                            providerClass = Class.forName(PROVIDER_CLASS);
092                    }
093                    catch (ClassNotFoundException cnfe) {
094                            if ((ServerDetector.isWebSphere()) &&
095                                    (PROVIDER_CLASS.equals(SUN_PROVIDER_CLASS))) {
096    
097                                    if (_log.isWarnEnabled()) {
098                                            _log.warn(
099                                                    "WebSphere does not have " + SUN_PROVIDER_CLASS +
100                                                            ", using " + IBM_PROVIDER_CLASS + " instead");
101                                    }
102    
103                                    providerClass = Class.forName(IBM_PROVIDER_CLASS);
104                            }
105                            else if (System.getProperty("java.vm.vendor").equals(
106                                                    "IBM Corporation")) {
107    
108                                    if (_log.isWarnEnabled()) {
109                                            _log.warn(
110                                                    "IBM JVM does not have " + SUN_PROVIDER_CLASS +
111                                                            ", using " + IBM_PROVIDER_CLASS + " instead");
112                                    }
113    
114                                    providerClass = Class.forName(IBM_PROVIDER_CLASS);
115                            }
116                            else {
117                                    throw cnfe;
118                            }
119                    }
120    
121                    return (Provider)providerClass.newInstance();
122            }
123    
124            public static String decrypt(Key key, String encryptedString)
125                    throws EncryptorException {
126    
127                    byte[] encryptedBytes = Base64.decode(encryptedString);
128    
129                    return decryptUnencodedAsString(key, encryptedBytes);
130            }
131    
132            public static byte[] decryptUnencodedAsBytes(Key key, byte[] encryptedBytes)
133                    throws EncryptorException {
134    
135                    String algorithm = key.getAlgorithm();
136    
137                    String cacheKey = algorithm.concat(StringPool.POUND).concat(
138                            key.toString());
139    
140                    Cipher cipher = _decryptCipherMap.get(cacheKey);
141    
142                    try {
143                            if (cipher == null) {
144                                    Security.addProvider(getProvider());
145    
146                                    cipher = Cipher.getInstance(algorithm);
147    
148                                    cipher.init(Cipher.DECRYPT_MODE, key);
149    
150                                    _decryptCipherMap.put(cacheKey, cipher);
151                            }
152    
153                            synchronized (cipher) {
154                                    return cipher.doFinal(encryptedBytes);
155                            }
156                    }
157                    catch (Exception e) {
158                            throw new EncryptorException(e);
159                    }
160            }
161    
162            public static String decryptUnencodedAsString(
163                            Key key, byte[] encryptedBytes)
164                    throws EncryptorException {
165    
166                    try {
167                            byte[] decryptedBytes = decryptUnencodedAsBytes(
168                                    key, encryptedBytes);
169    
170                            return new String(decryptedBytes, ENCODING);
171                    }
172                    catch (Exception e) {
173                            throw new EncryptorException(e);
174                    }
175            }
176    
177            public static String digest(String text) {
178                    return DigesterUtil.digest(text);
179            }
180    
181            public static String digest(String algorithm, String text) {
182                    return DigesterUtil.digest(algorithm, text);
183            }
184    
185            public static String encrypt(Key key, String plainText)
186                    throws EncryptorException {
187    
188                    byte[] encryptedBytes = encryptUnencoded(key, plainText);
189    
190                    return Base64.encode(encryptedBytes);
191            }
192    
193            public static byte[] encryptUnencoded(Key key, byte[] plainBytes)
194                    throws EncryptorException {
195    
196                    String algorithm = key.getAlgorithm();
197    
198                    String cacheKey = algorithm.concat(StringPool.POUND).concat(
199                            key.toString());
200    
201                    Cipher cipher = _encryptCipherMap.get(cacheKey);
202    
203                    try {
204                            if (cipher == null) {
205                                    Security.addProvider(getProvider());
206    
207                                    cipher = Cipher.getInstance(algorithm);
208    
209                                    cipher.init(Cipher.ENCRYPT_MODE, key);
210    
211                                    _encryptCipherMap.put(cacheKey, cipher);
212                            }
213    
214                            synchronized (cipher) {
215                                    return cipher.doFinal(plainBytes);
216                            }
217                    }
218                    catch (Exception e) {
219                            throw new EncryptorException(e);
220                    }
221            }
222    
223            public static byte[] encryptUnencoded(Key key, String plainText)
224                    throws EncryptorException {
225    
226                    try {
227                            byte[] decryptedBytes = plainText.getBytes(ENCODING);
228    
229                            return encryptUnencoded(key, decryptedBytes);
230                    }
231                    catch (Exception e) {
232                            throw new EncryptorException(e);
233                    }
234            }
235    
236            private static Log _log = LogFactoryUtil.getLog(Encryptor.class);
237    
238            private static Map<String, Cipher> _decryptCipherMap =
239                    new ConcurrentHashMap<String, Cipher>(1, 1f, 1);
240            private static Map<String, Cipher> _encryptCipherMap =
241                    new ConcurrentHashMap<String, Cipher>(1, 1f, 1);
242    
243    }