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