Improves #5053 by giving option of secure or pseudo random

Allow random to be passed in and can default to a weak pseudo random.
This commit is contained in:
gregw 2020-07-17 12:19:22 +02:00
parent 8e7bfa0ee5
commit f6d39849e8
4 changed files with 51 additions and 23 deletions

View File

@ -26,6 +26,7 @@ import java.security.SecureRandom;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.client.HttpClient;
@ -46,19 +47,32 @@ import org.eclipse.jetty.util.TypeUtil;
*/
public class DigestAuthentication extends AbstractAuthentication
{
private static final SecureRandom random = new SecureRandom();
private final Random random;
private final String user;
private final String password;
/**
/** Construct a DigestAuthentication with a {@link SecureRandom} nonce.
* @param uri the URI to match for the authentication
* @param realm the realm to match for the authentication
* @param user the user that wants to authenticate
* @param password the password of the user
*/
public DigestAuthentication(URI uri, String realm, String user, String password)
{
this(uri, realm, user, password, new SecureRandom());
}
/**
* @param uri the URI to match for the authentication
* @param realm the realm to match for the authentication
* @param user the user that wants to authenticate
* @param password the password of the user
* @param random the Random generator to use for nonces, or null for a weak algorithm.
*/
public DigestAuthentication(URI uri, String realm, String user, String password, Random random)
{
super(uri, realm);
this.random = random;
this.user = user;
this.password = password;
}
@ -217,9 +231,15 @@ public class DigestAuthentication extends AbstractAuthentication
private String newClientNonce()
{
byte[] bytes = new byte[8];
random.nextBytes(bytes);
return toHexString(bytes);
if (random != null)
{
byte[] bytes = new byte[8];
random.nextBytes(bytes);
return toHexString(bytes);
}
long pseudoRandom = System.nanoTime() ^ System.identityHashCode(new Object());
return Long.toHexString(pseudoRandom);
}
private String toHexString(byte[] bytes)

View File

@ -23,12 +23,10 @@ import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.client.AsyncContentProvider;
@ -70,7 +68,6 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
private static final Logger LOG = Log.getLogger(MultiPartContentProvider.class);
private static final byte[] COLON_SPACE_BYTES = new byte[]{':', ' '};
private static final byte[] CR_LF_BYTES = new byte[]{'\r', '\n'};
private static final Random random = new SecureRandom();
private final List<Part> parts = new ArrayList<>();
private final ByteBuffer firstBoundary;
@ -102,13 +99,9 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
private static String makeBoundary()
{
StringBuilder builder = new StringBuilder("JettyHttpClientBoundary");
int length = builder.length();
while (builder.length() < length + 16)
{
long rnd = random.nextLong();
builder.append(Long.toString(rnd < 0 ? -rnd : rnd, 36));
}
builder.setLength(length + 16);
builder.append(Long.toString(System.identityHashCode(builder), 36));
builder.append(Long.toString(System.identityHashCode(Thread.currentThread()), 36));
builder.append(Long.toString(System.nanoTime(), 36));
return builder.toString();
}

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.plus.webapp;
import java.security.SecureRandom;
import java.util.Random;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
@ -40,7 +38,6 @@ import org.eclipse.jetty.webapp.WebAppContext;
public class PlusConfiguration extends AbstractConfiguration
{
private static final Logger LOG = Log.getLogger(PlusConfiguration.class);
private static final Random __random = new SecureRandom();
private Integer _key;
@ -101,7 +98,7 @@ public class PlusConfiguration extends AbstractConfiguration
{
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(wac.getClassLoader()))
{
_key = __random.nextInt();
_key = (int)(this.hashCode() ^ System.nanoTime());
Context context = new InitialContext();
Context compCtx = (Context)context.lookup("java:comp");
compCtx.addToEnvironment(NamingContext.LOCK_PROPERTY, _key);

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.websocket.client.masks;
import java.security.SecureRandom;
import java.util.Random;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
@ -29,7 +28,7 @@ public class RandomMasker implements Masker
public RandomMasker()
{
this(new SecureRandom());
this(null);
}
public RandomMasker(Random random)
@ -40,8 +39,27 @@ public class RandomMasker implements Masker
@Override
public void setMask(WebSocketFrame frame)
{
byte[] mask = new byte[4];
random.nextBytes(mask);
byte[] mask;
if (random != null)
{
mask = new byte[4];
random.nextBytes(mask);
}
else
{
// This is a weak random, but sufficient for a mask.
// Using a SecureRandom would result in lock contention
// Using a Random is as more predictable than this algorithm
// Using a onetime random is essentially a system time.
int pseudoRandom = (int)(System.identityHashCode(frame.hashCode()) ^ System.nanoTime());
mask = new byte[]
{
(byte)pseudoRandom,
(byte)(pseudoRandom >> 8),
(byte)(pseudoRandom >> 16),
(byte)(pseudoRandom >> 24),
};
}
frame.setMask(mask);
}
}