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  
18  package ch.elca.el4j.util.encryption;
19  
20  import java.security.SecureRandom;
21  
22  import javax.crypto.Cipher;
23  import javax.crypto.SecretKey;
24  import javax.crypto.SecretKeyFactory;
25  import javax.crypto.spec.PBEKeySpec;
26  import javax.crypto.spec.PBEParameterSpec;
27  
28  import org.apache.commons.codec.binary.Base64;
29  import org.apache.commons.lang.ArrayUtils;
30  
31  /**
32   *  En- / decrypts strings with a key derived from a user-supplied password
33   *  with java's PBEStringEncryption (DES, MD5 password hash).
34   *
35   * @svnLink $Revision: 3882 $;$Date: 2009-08-04 15:24:14 +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/PBEncryptor.java $
36   *
37   * @author David Bernhard (DBD)
38   */
39  public class PBEncryptor {
40  
41  	private Cipher m_cipher;
42  	private SecretKey m_key;
43  
44  	private String ENCODING = "UTF-8";
45  	private String ALGORITHM = "PBEWithMD5AndDES";
46  
47  	private int SALTSIZE = 8;
48  	private int ENCITERATIONS = 10;
49  
50  	/**
51  	 * Constructor. As this lives in external we don't initialize with the
52  	 * internal password here.
53  	 * @throws EncryptionException
54  	 */
55  	public PBEncryptor() throws EncryptionException {
56  		try {
57  			deriveKey("This is a fairly long phrase used to encrypt.");
58  			m_cipher = Cipher.getInstance(ALGORITHM);
59  		} catch (Exception e) {
60  			throw new EncryptionException(e);
61  		}
62  
63  	}
64  
65  	/**
66  	 * Hashes the password and converts it to a suitable format for the cipher.
67  	 *
68  	 * @param password
69  	 *            The password to generate a key from.
70  	 * Sets a valid key derived from the password.
71  	 * @throws EncryptionException
72  	 */
73  	public void deriveKey(String password) throws EncryptionException {
74  
75  		String salt = "ELCAEL4J";
76  		int itCount = 100;
77  
78  		try {
79  			SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
80  			PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt
81  				.getBytes(), itCount);
82  			m_key = factory.generateSecret(spec);
83  		} catch (Exception e) {
84  			throw new EncryptionException(e);
85  		}
86  	}
87  
88  	private byte[] generateSalt() throws EncryptionException {
89  		SecureRandom random;
90  		try {
91  			random = SecureRandom.getInstance("SHA1PRNG");
92  		} catch (Exception e) {
93  			throw new EncryptionException(e);
94  		}
95  		byte[] salt = new byte[SALTSIZE];
96  		random.nextBytes(salt);
97  		return salt;
98  	}
99  
100 	/**
101 	 * Encrypts a string with the currently set password.
102 	 *
103 	 * @param plain String.
104 	 * @return The encrypted string.
105 	 * @throws EncryptionException
106 	 */
107 	public String encrypt(String plain) throws EncryptionException {
108 		byte[] salt = generateSalt();
109 		PBEParameterSpec spec = new PBEParameterSpec(salt, ENCITERATIONS);
110 
111 		try {
112 			m_cipher.init(Cipher.ENCRYPT_MODE, m_key, spec);
113 			byte[] plainBytes = plain.getBytes(ENCODING);
114 			byte[] encBytes = m_cipher.doFinal(plainBytes);
115 			return new String(Base64.encodeBase64(ArrayUtils.addAll(salt,
116 				encBytes)));
117 		} catch (Exception e) {
118 			throw new EncryptionException(e);
119 		}
120 	}
121 
122 	/**
123 	 * Decrypts a string with the currently set password.
124 	 *
125 	 * @param enc String.
126 	 * @return The decrypted string.
127 	 * @throws EncryptionException
128 	 */
129 	public String decrypt(String enc) throws EncryptionException {
130 		byte[] plainBytes;
131 		byte[] encBytes = Base64.decodeBase64(enc.getBytes());
132 		byte[] salt = ArrayUtils.subarray(encBytes, 0, SALTSIZE);
133 		encBytes = ArrayUtils.subarray(encBytes, SALTSIZE, encBytes.length);
134 
135 		PBEParameterSpec spec = new PBEParameterSpec(salt, ENCITERATIONS);
136 
137 		try {
138 			m_cipher.init(Cipher.DECRYPT_MODE, m_key, spec);
139 			plainBytes = m_cipher.doFinal(encBytes);
140 		} catch (Exception e) {
141 			throw new EncryptionException(e);
142 		}
143 
144 		StringBuffer stringBuffer = new StringBuffer();
145 		for (int i = 0; i < plainBytes.length; i++) {
146 			stringBuffer.append((char) plainBytes[i]);
147 		}
148 		return stringBuffer.toString();
149 	}
150 
151 }