Author: fmeschbe
Date: Mon Sep 6 11:59:13 2010
New Revision: 993004
URL: http://svn.apache.org/viewvc?rev=993004&view=rev
Log:
SLING-1729 Provide a simple and faster alternative to the default SecureRandom
seeding. This might be of interest mostly for the Linux and Solaris platforms
which seed SecureRandom from the blocking /dev/random by default.
Modified:
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/TokenStore.java
sling/trunk/bundles/auth/form/src/main/resources/OSGI-INF/metatype/metatype.properties
Modified:
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java?rev=993004&r1=993003&r2=993004&view=diff
==============================================================================
---
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
(original)
+++
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
Mon Sep 6 11:59:13 2010
@@ -153,6 +153,19 @@ public class FormAuthenticationHandler e
@Property(value = DEFAULT_TOKEN_FILE)
private static final String PAR_TOKEN_FILE = "form.token.file";
+ private static final boolean DEFAULT_TOKEN_FAST_SEED = false;
+
+ /**
+ * Whether to use a less secure but faster seeding mechanism to seed the
+ * random number generator in the {...@link TokenStore}. By default the
faster
+ * mechanism is disabled and the platform provided seeding is used. This
may
+ * however block the startup considerably, particularly on Linux and
Solaris
+ * platforms which use the (blocking but secure) <code>/dev/random</code>
+ * device for seeding.
+ */
+ @Property(boolValue = DEFAULT_TOKEN_FAST_SEED)
+ private static final String PAR_TOKEN_FAST_SEED = "form.token.fastseed";
+
/**
* The default include value.
*
@@ -758,8 +771,10 @@ public class FormAuthenticationHandler e
properties.get(PAR_TOKEN_FILE), DEFAULT_TOKEN_FILE);
final File tokenFile = getTokenFile(tokenFileName,
componentContext.getBundleContext());
+ final boolean fastSeed = OsgiUtil.toBoolean(
+ properties.get(PAR_TOKEN_FAST_SEED), DEFAULT_TOKEN_FAST_SEED);
log.info("Storing tokens in {}", tokenFile.getAbsolutePath());
- this.tokenStore = new TokenStore(tokenFile, sessionTimeout);
+ this.tokenStore = new TokenStore(tokenFile, sessionTimeout, fastSeed);
this.loginModule = null;
try {
Modified:
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/TokenStore.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/TokenStore.java?rev=993004&r1=993003&r2=993004&view=diff
==============================================================================
---
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/TokenStore.java
(original)
+++
sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/TokenStore.java
Mon Sep 6 11:59:13 2010
@@ -25,9 +25,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
+import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
-
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@@ -109,9 +109,10 @@ class TokenStore {
* @throws NullPointerException if <code>tokenFile</code> is
* <code>null</code>.
*/
- TokenStore(final File tokenFile, final long sessionTimeout)
- throws NoSuchAlgorithmException, InvalidKeyException,
- IllegalStateException, UnsupportedEncodingException {
+ TokenStore(final File tokenFile, final long sessionTimeout,
+ final boolean fastSeed) throws NoSuchAlgorithmException,
+ InvalidKeyException, IllegalStateException,
+ UnsupportedEncodingException {
if (tokenFile == null) {
throw new NullPointerException("tokenfile");
@@ -126,6 +127,9 @@ class TokenStore {
loadTokens();
// warm up the crypto API
+ if (fastSeed) {
+ random.setSeed(getFastEntropy());
+ }
byte[] b = new byte[20];
random.nextBytes(b);
final SecretKey secretKey = new SecretKeySpec(b, HMAC_SHA1);
@@ -377,4 +381,63 @@ class TokenStore {
}
return new String(c);
}
+
+ /**
+ * Creates a byte array of entry from the current state of the system:
+ * <ul>
+ * <li>The current system time in milliseconds since the epoch</li>
+ * <li>The number of nanoseconds since system startup</li>
+ * <li>The name, size and last modification time of the files in the
+ * <code>java.io.tmpdir</code> folder.</li>
+ * </ul>
+ * <p>
+ * <b>NOTE</b> This method generates entropy fast but not necessairily
+ * secure enough for seeding the random number generator.
+ *
+ * @return bytes of entropy
+ */
+ private static byte[] getFastEntropy() {
+ final MessageDigest md;
+
+ try {
+ md = MessageDigest.getInstance("SHA");
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new InternalError("internal error: SHA-1 not available.");
+ }
+
+ // update with XorShifted time values
+ update(md, System.currentTimeMillis());
+ update(md, System.nanoTime());
+
+ // scan the temp file system
+ File file = new File(System.getProperty("java.io.tmpdir"));
+ File[] entries = file.listFiles();
+ if (entries != null) {
+ for (File entry : entries) {
+ md.update(entry.getName().getBytes());
+ update(md, entry.lastModified());
+ update(md, entry.length());
+ }
+ }
+
+ return md.digest();
+ }
+
+ /**
+ * Updates the message digest with an XOR-Shifted value.
+ *
+ * @param md The MessageDigest to update
+ * @param value The original value to be XOR-Shifted first before taking
the
+ * bytes ot update the message digest
+ */
+ private static void update(final MessageDigest md, long value) {
+ value ^= (value << 21);
+ value ^= (value >>> 35);
+ value ^= (value << 4);
+
+ for (int i = 0; i < 8; i++) {
+ md.update((byte) value);
+ value >>= 8;
+ }
+ }
}
\ No newline at end of file
Modified:
sling/trunk/bundles/auth/form/src/main/resources/OSGI-INF/metatype/metatype.properties
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/auth/form/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=993004&r1=993003&r2=993004&view=diff
==============================================================================
---
sling/trunk/bundles/auth/form/src/main/resources/OSGI-INF/metatype/metatype.properties
(original)
+++
sling/trunk/bundles/auth/form/src/main/resources/OSGI-INF/metatype/metatype.properties
Mon Sep 6 11:59:13 2010
@@ -67,6 +67,13 @@ form.token.file.description = The name o
working directory. In the future this file may be store in the JCR Repository
\
to support clustering scenarios.
+form.token.fastseed.name = Fast Seed Generator
+form.token.fastseed.description = Defines whether the random number generator \
+ should be seeded with a fast but less secure method. If this property is not \
+ set or is set to "false" the seed generator of the Java platform will be \
+ used. By default the secure seed generator is used, which may block startup \
+ on Linux and Solaris systems due to accessing /dev/random.
+
service.ranking.name = Ranking
service.ranking.description = The relative ranking of this service.