View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.util.encryption;
18  
19  import java.io.UnsupportedEncodingException;
20  import java.security.InvalidKeyException;
21  import java.security.NoSuchAlgorithmException;
22  import java.security.spec.InvalidKeySpecException;
23  import java.security.spec.KeySpec;
24  
25  import javax.crypto.Cipher;
26  import javax.crypto.NoSuchPaddingException;
27  import javax.crypto.SecretKey;
28  import javax.crypto.SecretKeyFactory;
29  import javax.crypto.spec.DESKeySpec;
30  import javax.crypto.spec.DESedeKeySpec;
31  import javax.crypto.spec.SecretKeySpec;
32  
33  import org.apache.commons.codec.binary.Base64;
34  
35  /**
36   * Class to en- and decrypt data symetrically.
37   *
38   * CAVEAT: the encoding between byte[] and String was recently changed to adapt to
39   *  the new Base64 encore (before it used a private method of sun).
40   *
41   * @svnLink $Revision: 3884 $;$Date: 2009-08-04 15:48:31 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/core/src/main/java/ch/elca/el4j/util/encryption/SymmetricEncryption.java $
42   *
43   * @author Andreas Pfenninger (APR)
44   */
45  public class SymmetricEncryption {
46  
47  	/** DESede encryption scheme. */
48  	private static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
49  
50  	/** DES encryption scheme. */
51  	private static final String DES_ENCRYPTION_SCHEME = "DES";
52  
53  	/** AES encryption scheme. */
54  	private static final String AES_ENCRYPTION_SCHEME = "AES";
55  
56  	/** Default encryption key. */
57  	private static final String DEFAULT_ENCRYPTION_KEY
58  		= "This is a fairly long phrase used to encrypt.";
59  
60  	/** The encoding used for the data to be signed, default: UTF-8. */
61  	private String m_dataEncodingFormat = "UTF-8";
62  
63  	/** The encryptionScheme, default: "AES". */
64  	private String m_encryptionScheme = AES_ENCRYPTION_SCHEME;
65  
66  	/** The encryptionKey. */
67  	private String m_encryptionKey = DEFAULT_ENCRYPTION_KEY;
68  
69  	/** m_keySpec. */
70  	private KeySpec m_keySpec;
71  
72  	/** m_cipher. */
73  	private Cipher m_cipher;
74  
75  	/**
76  	 * @param dataEncodingFormat
77  	 *            The dataEncodingFormat to set.
78  	 */
79  	public void setDataEncodingFormat(String dataEncodingFormat) {
80  		m_dataEncodingFormat = dataEncodingFormat;
81  	}
82  
83  	/**
84  	 * @param encryptionKey
85  	 *            The encryptionKey to set.
86  	 */
87  	public void setEncryptionKey(String encryptionKey) {
88  		m_encryptionKey = encryptionKey;
89  	}
90  
91  	/**
92  	 * @param encryptionScheme
93  	 *            The encryptionScheme to set.
94  	 */
95  	public void setEncryptionScheme(String encryptionScheme) {
96  		m_encryptionScheme = encryptionScheme;
97  	}
98  
99  	/**
100 	 * Initializes the encryptor.
101 	 *
102 	 * @throws EncryptionException if encryption could not be initialized.
103 	 */
104 	public void init() throws EncryptionException {
105 		try {
106 			byte[] keyAsBytes = m_encryptionKey.getBytes(m_dataEncodingFormat);
107 
108 			if (m_encryptionScheme.equals(DESEDE_ENCRYPTION_SCHEME)) {
109 				m_keySpec = new DESedeKeySpec(keyAsBytes);
110 			} else if (m_encryptionScheme.equals(DES_ENCRYPTION_SCHEME)) {
111 				m_keySpec = new DESKeySpec(keyAsBytes);
112 			} else if (m_encryptionScheme.equals(AES_ENCRYPTION_SCHEME)) {
113 				m_keySpec
114 					= new SecretKeySpec(keyAsBytes, AES_ENCRYPTION_SCHEME);
115 			} else {
116 				throw new IllegalArgumentException(
117 					"Encryption scheme not supported: " + m_encryptionScheme);
118 			}
119 
120 			m_cipher = Cipher.getInstance(m_encryptionScheme);
121 
122 		} catch (InvalidKeyException e) {
123 			throw new EncryptionException(e);
124 		} catch (UnsupportedEncodingException e) {
125 			throw new EncryptionException(e);
126 		} catch (NoSuchAlgorithmException e) {
127 			throw new EncryptionException(e);
128 		} catch (NoSuchPaddingException e) {
129 			throw new EncryptionException(e);
130 		}
131 
132 	}
133 
134 	/**
135 	 * Encrypts a String.
136 	 *
137 	 * @param unencryptedString
138 	 *            The String to encrypt.
139 	 * @return The decrypted String.
140 	 * @throws EncryptionException if there was an error.
141 	 */
142 	public String encrypt(String unencryptedString) throws EncryptionException {
143 		try {
144 			byte[] cleartext = unencryptedString.getBytes(m_dataEncodingFormat);
145 			return encryptByteArrayToString(cleartext);
146 		} catch (Exception e) {
147 			throw new EncryptionException(e);
148 		}
149 	}
150 
151 	/**
152 	 * Decrypts a String.
153 	 *
154 	 * @param encryptedString
155 	 *            The String to decrypt.
156 	 * @return The decrypted String.
157 	 * @throws EncryptionException if there was an error.
158 	 */
159 	public String decrypt(String encryptedString) throws EncryptionException {
160 		return bytes2String(decryptStringToByteArray(encryptedString));
161 	}
162 
163 	/**
164 	 * Method to convert a byte array to a string.
165 	 *
166 	 * @param bytes To convert.
167 	 * @return Returns generated string.
168 	 */
169 	private String bytes2String(byte[] bytes) {
170 		StringBuffer stringBuffer = new StringBuffer();
171 		for (int i = 0; i < bytes.length; i++) {
172 			stringBuffer.append((char) bytes[i]);
173 		}
174 		return stringBuffer.toString();
175 	}
176 
177 	/**
178 	 * Encrypts a byte array into a String.
179 	 *
180 	 * @param cleartext
181 	 *            The byte array to encrypt.
182 	 * @return The encrypted String.
183 	 * @throws EncryptionException if there was an error.
184 	 */
185 	public String encryptByteArrayToString(byte[] cleartext)
186 		throws EncryptionException {
187 
188 		if (cleartext == null || cleartext.length == 0) {
189 			throw new EncryptionException("Unencrypted string was null or "
190 				+ "empty");
191 		}
192 
193 		try {
194 			m_cipher.init(Cipher.ENCRYPT_MODE, getKey());
195 			byte[] ciphertext = m_cipher.doFinal(cleartext);
196 
197 			return new String(Base64.encodeBase64(ciphertext));
198 		} catch (Exception e) {
199 			throw new EncryptionException(e);
200 		}
201 	}
202 
203 	/**
204 	 * Decrypts a String into a byte array.
205 	 *
206 	 * @param encryptedString
207 	 *            The String to decrypt.
208 	 * @return The decrypted byte array.
209 	 * @throws EncryptionException if there was an error.
210 	 */
211 	public byte[] decryptStringToByteArray(String encryptedString)
212 		throws EncryptionException {
213 
214 		if (encryptedString == null || encryptedString.trim().length() <= 0) {
215 			throw new EncryptionException("Unencrypted string was null or "
216 				+ "empty");
217 		}
218 
219 		try {
220 			m_cipher.init(Cipher.DECRYPT_MODE, getKey());
221 			byte[] cleartext = Base64.decodeBase64(encryptedString.getBytes());
222 			byte[] ciphertext = m_cipher.doFinal(cleartext);
223 
224 			return ciphertext;
225 		} catch (Exception e) {
226 			throw new EncryptionException(e);
227 		}
228 	}
229 
230 	/**
231 	 * Returns the secret key.
232 	 *
233 	 * @return The secret key
234 	 * @throws EncryptionException if there was an error.
235 	 */
236 	private SecretKey getKey() throws EncryptionException {
237 
238 		SecretKey key;
239 		if (m_encryptionScheme.equals(AES_ENCRYPTION_SCHEME)) {
240 			// Get the secret key from the secret key specification
241 			key = (SecretKeySpec) m_keySpec;
242 		} else {
243 			// Generate the secret key via secret key factory
244 			try {
245 				SecretKeyFactory keyFactory = SecretKeyFactory
246 					.getInstance(m_encryptionScheme);
247 				key = keyFactory.generateSecret(m_keySpec);
248 			} catch (InvalidKeySpecException e) {
249 				throw new EncryptionException(e);
250 			} catch (NoSuchAlgorithmException e) {
251 				throw new EncryptionException(e);
252 			}
253 		}
254 
255 		return key;
256 
257 	}
258 }