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