This is an automated email from the ASF dual-hosted git repository.
papegaaij pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/master by this push:
new bf9732d WICKET-6730: central SecureRandom setting
bf9732d is described below
commit bf9732d128be79621841b16f120dbee091e1bf98
Author: Emond Papegaaij <[email protected]>
AuthorDate: Thu Jan 16 21:53:28 2020 +0100
WICKET-6730: central SecureRandom setting
---
.../apache/wicket/DefaultPageManagerProvider.java | 2 +-
.../core/random/DefaultSecureRandomSupplier.java | 50 +++++++++++++++++
.../wicket/core/random/ISecureRandomSupplier.java | 62 ++++++++++++++++++++++
.../apache/wicket/pageStore/CryptingPageStore.java | 23 ++++----
.../apache/wicket/settings/SecuritySettings.java | 36 +++++++++++++
.../wicket/pageStore/CryptingPageStoreTest.java | 8 +--
6 files changed, 162 insertions(+), 19 deletions(-)
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 1e8ec6f..e128266 100644
---
a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++
b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -183,7 +183,7 @@ public class DefaultPageManagerProvider implements
IPageManagerProvider
if (storeSettings.isEncrypted())
{
- pageStore = new CryptingPageStore(pageStore);
+ pageStore = new CryptingPageStore(pageStore,
application);
}
return pageStore;
diff --git
a/wicket-core/src/main/java/org/apache/wicket/core/random/DefaultSecureRandomSupplier.java
b/wicket-core/src/main/java/org/apache/wicket/core/random/DefaultSecureRandomSupplier.java
new file mode 100644
index 0000000..cb00235
--- /dev/null
+++
b/wicket-core/src/main/java/org/apache/wicket/core/random/DefaultSecureRandomSupplier.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.random;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import org.apache.wicket.WicketRuntimeException;
+
+/**
+ * A very simple {@link ISecureRandomSupplier} that holds a strong {@code
SecureRandom}.
+ *
+ * @author papegaaij
+ */
+public class DefaultSecureRandomSupplier implements ISecureRandomSupplier
+{
+ private SecureRandom random;
+
+ public DefaultSecureRandomSupplier()
+ {
+ try
+ {
+ random = SecureRandom.getInstanceStrong();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new WicketRuntimeException(e);
+ }
+ }
+
+ @Override
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+}
diff --git
a/wicket-core/src/main/java/org/apache/wicket/core/random/ISecureRandomSupplier.java
b/wicket-core/src/main/java/org/apache/wicket/core/random/ISecureRandomSupplier.java
new file mode 100644
index 0000000..9b9fe14
--- /dev/null
+++
b/wicket-core/src/main/java/org/apache/wicket/core/random/ISecureRandomSupplier.java
@@ -0,0 +1,62 @@
+/*
+ * 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.core.random;
+
+import java.security.SecureRandom;
+import java.util.Base64;
+
+/**
+ * Supplies the Wicket application with random bytes.
+ *
+ * @author papegaaij
+ */
+public interface ISecureRandomSupplier
+{
+ /**
+ * Returns the actual {@code SecureRandom} being used as source.
+ *
+ * @return The {@code SecureRandom}.
+ */
+ public SecureRandom getRandom();
+
+ /**
+ * Returns a byte array with random bytes of the given length.
+ *
+ * @param length
+ * The number of bytes to return.
+ * @return A byte array with random bytes of the given length.
+ */
+ public default byte[] getRandomBytes(int length)
+ {
+ byte[] ret = new byte[length];
+ getRandom().nextBytes(ret);
+ return ret;
+ }
+
+ /**
+ * Returns a base64 encoded string with random content, base on {@code
length} bytes. The length
+ * of the returned string will be {@code length/3*4}.
+ *
+ * @param length
+ * The number of random bytes to use as input.
+ * @return A string with random base64 data.
+ */
+ public default String getRandomBase64(int length)
+ {
+ return
Base64.getUrlEncoder().encodeToString(getRandomBytes(length));
+ }
+}
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 91ac373..dc0d6eb 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,11 +17,11 @@
package org.apache.wicket.pageStore;
import java.io.Serializable;
-import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import javax.crypto.SecretKey;
+import org.apache.wicket.Application;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.page.IManageablePage;
@@ -46,27 +46,20 @@ public class CryptingPageStore extends DelegatingPageStore
private static final long serialVersionUID = 1L;
};
- private final SecureRandom random;
-
private final ICrypter crypter;
+ private final Application application;
+
/**
* @param delegate
* store to delegate to
* @param applicationName
* name of application
*/
- public CryptingPageStore(IPageStore delegate)
+ public CryptingPageStore(IPageStore delegate, Application application)
{
super(delegate);
- try
- {
- random = SecureRandom.getInstance("SHA1PRNG", "SUN");
- }
- catch (GeneralSecurityException ex)
- {
- throw new WicketRuntimeException(ex);
- }
+ this.application = Args.notNull(application, "application");
crypter = newCrypter();
}
@@ -94,7 +87,8 @@ public class CryptingPageStore extends DelegatingPageStore
private SessionData getSessionData(IPageContext context)
{
- return context.getSessionData(KEY, () -> new
SessionData(crypter.generateKey(random)));
+ return context.getSessionData(KEY, () -> new SessionData(crypter
+
.generateKey(application.getSecuritySettings().getRandomSupplier().getRandom())));
}
/**
@@ -138,7 +132,8 @@ public class CryptingPageStore extends DelegatingPageStore
SerializedPage serializedPage = (SerializedPage) page;
byte[] decrypted = serializedPage.getData();
- byte[] encrypted = getSessionData(context).encrypt(decrypted,
crypter, random);
+ byte[] encrypted = getSessionData(context).encrypt(decrypted,
crypter,
+
application.getSecuritySettings().getRandomSupplier().getRandom());
page = new SerializedPage(page.getPageId(),
serializedPage.getPageType(), encrypted);
diff --git
a/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
b/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
index 94eadea..94e2390 100644
--- a/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
+++ b/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
@@ -24,6 +24,8 @@ import org.apache.wicket.authorization.IAuthorizationStrategy;
import
org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener;
import org.apache.wicket.authorization.IUnauthorizedResourceRequestListener;
import org.apache.wicket.authorization.UnauthorizedInstantiationException;
+import org.apache.wicket.core.random.DefaultSecureRandomSupplier;
+import org.apache.wicket.core.random.ISecureRandomSupplier;
import org.apache.wicket.core.util.crypt.KeyInSessionSunJceCryptFactory;
import org.apache.wicket.util.crypt.ICryptFactory;
import org.apache.wicket.util.lang.Args;
@@ -55,6 +57,9 @@ public class SecuritySettings
/** factory for creating crypt objects */
private ICryptFactory cryptFactory;
+
+ /** supplier of random data and SecureRandom */
+ private ISecureRandomSupplier randomSupplier;
/**
* Whether mounts should be enforced. If {@code true}, requests for a
page will be
@@ -115,6 +120,21 @@ public class SecuritySettings
}
/**
+ * Returns the {@link ISecureRandomSupplier} to use for secure random
data. If no supplier is
+ * set, a {@link DefaultSecureRandomSupplier} is instantiated.
+ *
+ * @return The {@link ISecureRandomSupplier} to use for secure random
data.
+ */
+ public ISecureRandomSupplier getRandomSupplier()
+ {
+ if (randomSupplier == null)
+ {
+ randomSupplier = new DefaultSecureRandomSupplier();
+ }
+ return randomSupplier;
+ }
+
+ /**
* Gets whether page mounts should be enforced. If {@code true},
requests for a page will be
* allowed only if the page has been explicitly mounted in {@link
Application#init() MyApplication#init()}.
*
@@ -163,6 +183,22 @@ public class SecuritySettings
this.cryptFactory = cryptFactory;
return this;
}
+
+ /**
+ * Sets the supplier of secure random data for Wicket. The
implementation must use a strong
+ * source of random data and be able to generate a lot of random data
without running out of
+ * entropy.
+ *
+ * @param randomSupplier
+ * The new supplier, must not be null.
+ * @return {@code this} object for chaining
+ */
+ public SecuritySettings setRandomSupplier(ISecureRandomSupplier
randomSupplier)
+ {
+ Args.notNull(randomSupplier, "randomSupplier");
+ this.randomSupplier = randomSupplier;
+ return this;
+ }
/**
* Sets whether mounts should be enforced. If true, requests for
mounted targets have to done
diff --git
a/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
b/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
index 755a000..48e3def 100644
---
a/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
+++
b/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
@@ -23,10 +23,10 @@ import java.io.StreamCorruptedException;
import java.security.GeneralSecurityException;
import org.apache.wicket.MockPage;
-import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.mock.MockPageContext;
import org.apache.wicket.mock.MockPageStore;
import org.apache.wicket.serialize.java.JavaSerializer;
+import org.apache.wicket.util.tester.WicketTester;
import org.junit.jupiter.api.Test;
/**
@@ -34,13 +34,13 @@ import org.junit.jupiter.api.Test;
*
* @author svenmeier
*/
-public class CryptingPageStoreTest
+public class CryptingPageStoreTest extends WicketTester
{
@Test
void test()
{
- CryptingPageStore store = new CryptingPageStore(new
MockPageStore());
+ CryptingPageStore store = new CryptingPageStore(new
MockPageStore(), getApplication());
JavaSerializer serializer = new JavaSerializer("test");
IPageContext context = new MockPageContext();
@@ -60,7 +60,7 @@ public class CryptingPageStoreTest
@Test
void testFail()
{
- CryptingPageStore store = new CryptingPageStore(new
MockPageStore());
+ CryptingPageStore store = new CryptingPageStore(new
MockPageStore(), getApplication());
JavaSerializer serializer = new JavaSerializer("test");
MockPageContext context = new MockPageContext();