001package com.thed.util;
002
003import org.apache.commons.codec.binary.Base64;
004import org.apache.commons.lang.StringUtils;
005import org.apache.commons.logging.Log;
006import org.apache.commons.logging.impl.LogFactoryImpl;
007
008import javax.crypto.Cipher;
009import javax.crypto.SecretKeyFactory;
010import javax.crypto.spec.DESKeySpec;
011import javax.crypto.spec.SecretKeySpec;
012import java.security.Key;
013
014public class CodecUtils {
015        private static Log logger = LogFactoryImpl.getLog(CodecUtils.class);
016        private static final int KEY_LENGTH = 8;
017        private static String keyString = "ZBOT";
018        
019        /**
020         * encrypts the data using customerId as default key. Uses axis base64 utility (because its SOAP safe)
021         * @param data
022         * @return
023         */
024        public static String encrypt(String data) {
025                try{
026                        return encrypt(data, generateKey(keyString, null));
027                } catch (Exception e) {
028                        logger.error("Crypto.encrypt() Exception: ", e);
029                        return null;
030                }
031        }
032        
033        private static String encrypt(String plain, Key key) throws Exception{
034                Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
035                cipher.init(Cipher.ENCRYPT_MODE, key);
036
037                byte[] inputBytes = plain.getBytes("UTF8");
038                byte[] outputBytes = cipher.doFinal(inputBytes);
039
040                String base64 = new String(Base64.encodeBase64(outputBytes));
041                
042                return base64;
043        }
044        
045        /**
046         * decrypts the data using customerId as default key
047         * @param plain
048         * @return
049         */
050        public static String decrypt(String plain) {
051                try{
052                        return decrypt(plain, generateKey(keyString, null));
053                } catch (Exception e) {
054                        logger.error("Crypto.encrypt() Exception: ", e);
055                        return null;
056                }
057        }
058
059        private static String decrypt(String raw,  Key key) throws Exception {
060                Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
061                cipher.init(Cipher.DECRYPT_MODE, key);
062
063                byte[] inputBytes = Base64.decodeBase64(raw.getBytes());
064                byte[] outputBytes = cipher.doFinal(inputBytes);
065
066                String result = new String(outputBytes, "UTF8");
067
068                return result;
069        }
070        
071        /**
072         * Uses simple SecretKeySpec (KeyGenerator is not used as it adds randomness to the key and decrypt fails
073         * @param keyString Length should be equal to or less then 16 
074         * @param algorithm Defaults to DES
075         * @return generated Key
076         * @throws Exception
077         * @see {@link SecretKeySpec}
078         */
079        private static Key generateKey(String keyString, String algorithm) throws Exception{
080                if(StringUtils.isBlank(algorithm)){
081                        algorithm = "DES";
082                }
083                keyString = StringUtils.rightPad(keyString, KEY_LENGTH, '-');
084                
085                DESKeySpec spec = new DESKeySpec(keyString.getBytes());
086                SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
087                Key key = factory.generateSecret(spec);
088                
089                return key;
090                
091        }
092}