/*
 * $Id$ $Revision$
 * $Date$
 *
 * ==============================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package wicket.util.crypt;

import java.io.IOException;
import java.security.GeneralSecurityException;

import javax.crypto.Cipher;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import wicket.WicketRuntimeException;

/**
 * Abstract base class for JCE based ICrypt implementations.
 * 
 * @author Juergen Donnerstag
 */
public abstract class AbstractCrypt implements ICrypt
{
	/** Default encryption key */
	private static final String DEFAULT_ENCRYPTION_KEY = "WiCkEt-CrYpT";
	
	/** Log. */
	private static Log log = LogFactory.getLog(AbstractCrypt.class);
	
	/** Key used to de-/encrypt the data */
	private String encryptionKey = DEFAULT_ENCRYPTION_KEY;

	/**
	 * Constructor
	 */
	public AbstractCrypt()
	{
	}

	/**
	 * Decrypts a string into a string.
	 * 
	 * @param text
	 *            text to decript
	 * @return the decrypted text
	 */
	public final String decrypt(final String text)
	{
		return new String(decryptStringToByteArray(text));
	}

	/**
	 * Encrypt a string into a string
	 * 
	 * @param plainText
	 *            text to encrypt
	 * @return encrypted string
	 */
	public final String encrypt(final String plainText)
	{
		try
		{
			byte[] cipherText = encryptStringToByteArray(plainText);
			return new BASE64Encoder().encode(cipherText);
		}
		catch (GeneralSecurityException e)
		{
			log.error("Unable to encrypt text '" + plainText + "'", e);
			return null;
		}
	}

	/**
	 * Get encryption private key
	 * 
	 * @return encryption private key
	 */
	public String getKey()
	{
	    return this.encryptionKey;
	}

	/**
	 * Set encryption private key
	 * 
	 * @param key
	 *            private key to make de-/encryption unique
	 */
	public void setKey(final String key)
	{
		this.encryptionKey = key;
	}

	/**
	 * Crypts the given byte array
	 * 
	 * @param input
	 *            byte array to be crypted
	 * @param mode
	 *            crypt mode
	 * @return the input crypted. Null in case of an error
	 * @throws GeneralSecurityException
	 */
	protected abstract byte[] crypt(final byte[] input, final int mode) throws GeneralSecurityException;

	/**
	 * Decrypts a String into a byte array.
	 * 
	 * @param encrypted
	 *            text to decrypt
	 * @return the decrypted text
	 */
	private final byte[] decryptStringToByteArray(final String encrypted)
	{
		final byte[] plainBytes;
		try
		{
			plainBytes = new BASE64Decoder().decodeBuffer(encrypted);
			return crypt(plainBytes, Cipher.DECRYPT_MODE);
		}
		catch (IOException e)
		{
			throw new WicketRuntimeException(e.getMessage());
		}
		catch (GeneralSecurityException e)
		{
			log.error("Unable to decrypt text '" + encrypted + "'", e);
			return null;
		}
	}

	/**
	 * Encrypts the given text into a byte array.
	 * 
	 * @param plainText
	 *            text to encrypt
	 * @return the string encrypted
	 * @throws GeneralSecurityException
	 */
	private final byte[] encryptStringToByteArray(final String plainText)
			throws GeneralSecurityException
	{
		return crypt(plainText.getBytes(), Cipher.ENCRYPT_MODE);
	}
}

@@ -722,16 +722,61 @@
 eption;%0A
+import java.io.UnsupportedEncodingException;%0A
 import j
@@ -814,16 +814,16 @@
 eption;%0A
-
 %0Aimport 
@@ -1291,17 +1291,140 @@
 CrYpT%22;%0A
-%09
+%0A%09/** Encoding used to convert java String from and to byte%5B%5D */%0A%09private static final String CHARACTER_ENCODING = %22UTF-8%22;%0A
 %0A%09/** Lo
@@ -1499,10 +1499,9 @@
 s);%0A
-%09
 %0A
+
 %09/**
@@ -1828,24 +1828,35 @@
 ng text)%0A%09%7B%0A
+%09%09try%0A%09%09%7B%0A%09
 %09%09return new
@@ -1893,18 +1893,146 @@
 ay(text)
-);
+, CHARACTER_ENCODING);%0A%09%09%7D%0A%09%09catch (UnsupportedEncodingException ex)%0A%09%09%7B%0A%09%09%09throw new WicketRuntimeException(ex.getMessage());%0A%09%09%7D
 %0A%09%7D%0A%0A%09/*
@@ -2576,20 +2576,17 @@
 y()%0A%09%7B%0A%09
-    
+%09
 return t
@@ -3106,17 +3106,20 @@
 nt mode)
- 
+%0A%09%09%09
 throws G
@@ -4011,24 +4011,35 @@
 xception%0A%09%7B%0A
+%09%09try%0A%09%09%7B%0A%09
 %09%09return cry
@@ -4060,16 +4060,34 @@
 etBytes(
+CHARACTER_ENCODING
 ), Ciphe
@@ -4103,13 +4103,121 @@
 _MODE);%0A
+%09%09%7D%0A%09%09catch (UnsupportedEncodingException ex)%0A%09%09%7B%0A%09%09%09throw new WicketRuntimeException(ex.getMessage());%0A%09%09%7D%0A
 %09%7D%0A%7D%0A

apply fixed encoding (utf-8) for de-/encrypting, instead of OS setting