You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2018/07/09 19:21:37 UTC

wicket git commit: WICKET-6563 enhance encryption

Repository: wicket
Updated Branches:
  refs/heads/WICKET-6563 fd7b26bac -> ee21d9974


WICKET-6563 enhance encryption


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/ee21d997
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/ee21d997
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/ee21d997

Branch: refs/heads/WICKET-6563
Commit: ee21d99744ceeb2dadfd61bc44483eca77c7abf1
Parents: fd7b26b
Author: Sven Meier <sv...@apache.org>
Authored: Mon Jul 9 21:17:00 2018 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Mon Jul 9 21:17:09 2018 +0200

----------------------------------------------------------------------
 .../wicket/DefaultPageManagerProvider.java      |   6 +-
 .../wicket/pageStore/CryptingPageStore.java     | 103 +++---------------
 .../wicket/pageStore/InSessionPageStore.java    |   2 +-
 .../wicket/pageStore/crypt/DefaultCrypter.java  | 108 +++++++++++++++++++
 .../apache/wicket/pageStore/crypt/ICrypter.java |  28 +++++
 .../apache/wicket/settings/StoreSettings.java   |  31 +++---
 6 files changed, 176 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
index c453be9..1f120f1 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -166,6 +166,10 @@ public class DefaultPageManagerProvider implements IPageManagerProvider
 		Bytes maxSizePerSession = storeSettings.getMaxSizePerSession();
 		File fileStoreFolder = storeSettings.getFileStoreFolder();
 
-		return new DiskPageStore(application.getName(), fileStoreFolder, maxSizePerSession, getSerializer());
+		if (storeSettings.isEncrypted()) {
+			return new SerializingPageStore(new CryptingPageStore(new DiskPageStore(application.getName(), fileStoreFolder, maxSizePerSession)), getSerializer());
+		} else {
+			return new DiskPageStore(application.getName(), fileStoreFolder, maxSizePerSession, getSerializer());
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
index e1014d8..c294d5c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
@@ -17,18 +17,12 @@
 package org.apache.wicket.pageStore;
 
 import java.io.Serializable;
-import java.security.GeneralSecurityException;
-import java.util.UUID;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.PBEParameterSpec;
 
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.pageStore.crypt.DefaultCrypter;
+import org.apache.wicket.pageStore.crypt.ICrypter;
 import org.apache.wicket.serialize.ISerializer;
 
 /**
@@ -44,13 +38,6 @@ import org.apache.wicket.serialize.ISerializer;
  */
 public class CryptingPageStore extends DelegatingPageStore
 {
-	public static final String DEFAULT_CRYPT_METHOD = "PBEWithMD5AndDES";
-
-	private final static byte[] DEFAULT_SALT = { (byte)0x15, (byte)0x8c, (byte)0xa3, (byte)0x4a,
-			(byte)0x66, (byte)0x51, (byte)0x2a, (byte)0xbc };
-
-	private final static int DEFAULT_ITERATION_COUNT = 17;
-
 	private static final MetaDataKey<SessionData> KEY = new MetaDataKey<SessionData>()
 	{
 	};
@@ -86,53 +73,16 @@ public class CryptingPageStore extends DelegatingPageStore
 		{
 			context.bind();
 
-			data = context.setSessionData(KEY, new SessionData(createCipherKey(context)));
+			data = context.setSessionData(KEY, new SessionData(newCrypter(context)));
 		}
 		return data;
 	}
 
 	/**
-	 * Create a cipher key for the given context.
-	 * 
-	 * @param context
-	 *            context
-	 * @return random UUID by default
+	 * Create a new {@link ICrypter} for the given context.
 	 */
-	protected String createCipherKey(IPageContext context)
-	{
-		return UUID.randomUUID().toString();
-	}
-
-	/**
-	 * Create a secret key.
-	 * 
-	 * @param cipherKey
-	 *            cipher key
-	 * @return secret key
-	 * @throws GeneralSecurityException
-	 */
-	protected SecretKey createSecretKey(String cipherKey) throws GeneralSecurityException
-	{
-		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DEFAULT_CRYPT_METHOD);
-
-		return keyFactory.generateSecret(new PBEKeySpec(cipherKey.toCharArray()));
-	}
-
-	/**
-	 * Create a cipher
-	 * 
-	 * @param mode
-	 *            mode
-	 * @param secret
-	 *            secret
-	 * @return cipher
-	 * @throws GeneralSecurityException
-	 */
-	protected Cipher createCipher(int mode, SecretKey secret) throws GeneralSecurityException
-	{
-		Cipher cipher = Cipher.getInstance(DEFAULT_CRYPT_METHOD);
-		cipher.init(mode, secret, new PBEParameterSpec(DEFAULT_SALT, DEFAULT_ITERATION_COUNT));
-		return cipher;
+	protected ICrypter newCrypter(IPageContext context) {
+		return new DefaultCrypter();
 	}
 
 	@Override
@@ -149,7 +99,7 @@ public class CryptingPageStore extends DelegatingPageStore
 			SerializedPage serializedPage = (SerializedPage)page;
 
 			byte[] encrypted = serializedPage.getData();
-			byte[] decrypted = getSessionData(context).crypt(this, encrypted, Cipher.DECRYPT_MODE);
+			byte[] decrypted = getSessionData(context).decrypt(encrypted);
 
 			page = new SerializedPage(page.getPageId(), serializedPage.getPageType(), decrypted);
 		}
@@ -168,7 +118,7 @@ public class CryptingPageStore extends DelegatingPageStore
 		SerializedPage serializedPage = (SerializedPage)page;
 
 		byte[] decrypted = serializedPage.getData();
-		byte[] encrypted = getSessionData(context).crypt(this, decrypted, Cipher.ENCRYPT_MODE);
+		byte[] encrypted = getSessionData(context).encrypt(decrypted);
 
 		page = new SerializedPage(page.getPageId(), serializedPage.getPageType(), encrypted);
 
@@ -178,44 +128,21 @@ public class CryptingPageStore extends DelegatingPageStore
 	private static class SessionData implements Serializable
 	{
 
-		private final String cipherKey;
-
-		private transient SecretKey secretKey;
+		private ICrypter cypter;
 
-		public SessionData(String cipherKey)
+		public SessionData(ICrypter crypter)
 		{
-			this.cipherKey = cipherKey;
+			this.cypter= crypter;
 		}
 
-		protected Cipher createCipher(CryptingPageStore store, int mode) throws GeneralSecurityException
+		public byte[] encrypt(byte[] decrypted)
 		{
-			SecretKey secret = getSecretKey(store);
-
-			return store.createCipher(mode, secret);
-		}
-
-		protected synchronized SecretKey getSecretKey(CryptingPageStore store) throws GeneralSecurityException
-		{
-			if (secretKey == null)
-			{
-				secretKey = store.createSecretKey(cipherKey);
-			}
-
-			return secretKey;
+			return cypter.encrypt(decrypted);
 		}
 
-		public byte[] crypt(CryptingPageStore store, byte[] bytes, int mode)
+		public byte[] decrypt(byte[] encrypted)
 		{
-			try
-			{
-				Cipher cipher = createCipher(store, mode);
-
-				return cipher.doFinal(bytes);
-			}
-			catch (GeneralSecurityException ex)
-			{
-				throw new WicketRuntimeException(ex);
-			}
+			return cypter.decrypt(encrypted);
 		}
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
index e526155..032fa4f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
@@ -219,7 +219,7 @@ public class InSessionPageStore extends DelegatingPageStore
 						}
 						candidate = (IManageablePage)serializer.deserialize(((SerializedPage)candidate).getData());
 		
-						pages.set(id, candidate);
+						pages.set(p, candidate);
 					}
 					
 					page = candidate;

http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/DefaultCrypter.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/DefaultCrypter.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/DefaultCrypter.java
new file mode 100644
index 0000000..8d06339
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/DefaultCrypter.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.pageStore.crypt;
+
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+import org.apache.wicket.WicketRuntimeException;
+
+/**
+ * Default encryption and decryption implementation. 
+ */
+public class DefaultCrypter implements ICrypter
+{
+	private final SecureRandom random;
+
+	private final SecretKey key;
+
+	public DefaultCrypter()
+	{
+		try
+		{
+			random = SecureRandom.getInstance("SHA1PRNG", "SUN");
+
+			KeyGenerator generator = KeyGenerator.getInstance("AES");
+			generator.init(256, random);
+			key = generator.generateKey();
+		}
+		catch (GeneralSecurityException ex)
+		{
+			throw new WicketRuntimeException(ex);
+		}
+	}
+
+	protected Cipher getCipher() throws GeneralSecurityException
+	{
+		return Cipher.getInstance("AES/CBC/PKCS5Padding");
+	}
+
+	@Override
+	public byte[] encrypt(byte[] decrypted)
+	{
+		try
+		{
+			Cipher cipher = getCipher();
+			cipher.init(Cipher.ENCRYPT_MODE, key, random);
+
+			AlgorithmParameters params = cipher.getParameters();
+			byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
+
+			byte[] ciphertext = cipher.doFinal(decrypted);
+			
+			byte[] encrypted = Arrays.copyOf(iv, iv.length + ciphertext.length);
+			System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);
+			
+			return encrypted;
+		}
+		catch (GeneralSecurityException ex)
+		{
+			throw new WicketRuntimeException(ex);
+		}
+	}
+
+	@Override
+	public byte[] decrypt(byte[] encrypted)
+	{
+		try
+		{
+			byte[] iv = new byte[16];
+			byte[] ciphertext = new byte[encrypted.length - 16];
+			System.arraycopy(encrypted, 0, iv, 0, iv.length);
+			System.arraycopy(encrypted, 16, ciphertext, 0, ciphertext.length);
+	
+			Cipher cipher = getCipher();
+			cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+			byte[] decrypted = cipher.doFinal(ciphertext);
+			
+			return decrypted;
+		}
+		catch (GeneralSecurityException ex)
+		{
+			throw new WicketRuntimeException(ex);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/ICrypter.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/ICrypter.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/ICrypter.java
new file mode 100644
index 0000000..f5b37d9
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/crypt/ICrypter.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.pageStore.crypt;
+
+import java.io.Serializable;
+
+/**
+ * An encrypter and decrypter of pages.
+ */
+public interface ICrypter extends Serializable {
+	byte[] encrypt(byte[] bytes);
+	
+	byte[] decrypt(byte[] bytes);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/ee21d997/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java b/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
index 63a5499..6e911d3 100644
--- a/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
+++ b/wicket-core/src/main/java/org/apache/wicket/settings/StoreSettings.java
@@ -38,14 +38,6 @@ import org.apache.wicket.util.lang.Bytes;
  */
 public class StoreSettings
 {
-	/**
-	 * By default the second level cache is disabled.
-	 *
-	 * @see <a href="https://issues.apache.org/jira/browse/WICKET-5554">WICKET-5554</a>
-	 * @see <a href="https://cwiki.apache.org/confluence/x/qIaoAQ">Wicket Page storages</a>
-	 */
-	private static final int DEFAULT_CACHE_SIZE = 0;
-
 	private static final Bytes DEFAULT_MAX_SIZE_PER_SESSION = Bytes.megabytes(10);
 
 	private static final int DEFAULT_ASYNCHRONOUS_QUEUE_CAPACITY = 100;
@@ -56,7 +48,9 @@ public class StoreSettings
 
 	private int asynchronousQueueCapacity = DEFAULT_ASYNCHRONOUS_QUEUE_CAPACITY;
 
-	private boolean isAsynchronous = true;
+	private boolean asynchronous = true;
+	
+	private boolean encrypted = false;
 
 	/**
 	 * Construct.
@@ -177,15 +171,28 @@ public class StoreSettings
 	 */
 	public StoreSettings setAsynchronous(boolean async)
 	{
-		isAsynchronous = async;
+		asynchronous = async;
 		return this;
 	}
 
 	/**
-	 * @return {@code true} if the storing of page's bytes is asynchronous
+	 * @return {@code true} if the storing of page is asynchronous
 	 */
 	public boolean isAsynchronous()
 	{
-		return isAsynchronous;
+		return asynchronous;
+	}
+	
+	public void setEncrypted(boolean encrypted)
+	{
+		this.encrypted = encrypted;
+	}
+	
+	/**
+	 * @return {@code true} if the storing of page is encrypted
+	 */
+	public boolean isEncrypted()
+	{
+		return encrypted;
 	}
 }