forked from I2P_Developers/i2p.i2p
PRNG: Switch to /dev/random by default
This commit is contained in:
@ -40,14 +40,13 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
|||||||
private AsyncBuffer _currentBuffer;
|
private AsyncBuffer _currentBuffer;
|
||||||
|
|
||||||
public AsyncFortunaStandalone(I2PAppContext context) {
|
public AsyncFortunaStandalone(I2PAppContext context) {
|
||||||
super(context.getBooleanProperty("prng.useDevRandom") && !SystemVersion.isWindows() && !SystemVersion.isSlow());
|
super(context.getBooleanPropertyDefaultTrue("prng.useDevRandom") && !SystemVersion.isWindows() && !SystemVersion.isSlow());
|
||||||
_bufferCount = Math.max(context.getProperty("prng.buffers", DEFAULT_BUFFERS), 2);
|
_bufferCount = Math.max(context.getProperty("prng.buffers", DEFAULT_BUFFERS), 2);
|
||||||
_bufferSize = Math.max(context.getProperty("prng.bufferSize", DEFAULT_BUFSIZE), 16*1024);
|
_bufferSize = Math.max(context.getProperty("prng.bufferSize", DEFAULT_BUFSIZE), 16*1024);
|
||||||
_emptyBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
|
_emptyBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
|
||||||
_fullBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
|
_fullBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
|
||||||
_context = context;
|
_context = context;
|
||||||
context.statManager().createRateStat("prng.bufferWaitTime", "Delay for random number buffer (ms)", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
|
context.statManager().createRateStat("prng.bufferFillTime", "Time to fill random number buffer (ms)", "Encryption", new long[] { 60*60*1000 } );
|
||||||
context.statManager().createRateStat("prng.bufferFillTime", "Time to fill random number buffer (ms)", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
|
|
||||||
_log = context.logManager().getLog(AsyncFortunaStandalone.class);
|
_log = context.logManager().getLog(AsyncFortunaStandalone.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +79,8 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
|||||||
public void seed(byte val[]) {
|
public void seed(byte val[]) {
|
||||||
Map<String, byte[]> props = Collections.singletonMap(SEED, val);
|
Map<String, byte[]> props = Collections.singletonMap(SEED, val);
|
||||||
init(props);
|
init(props);
|
||||||
//fillBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void allocBuffer() {}
|
|
||||||
|
|
||||||
private static class AsyncBuffer {
|
private static class AsyncBuffer {
|
||||||
public final byte[] buffer;
|
public final byte[] buffer;
|
||||||
|
|
||||||
@ -103,7 +98,6 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
|||||||
AsyncBuffer old = _currentBuffer;
|
AsyncBuffer old = _currentBuffer;
|
||||||
if (old != null)
|
if (old != null)
|
||||||
_emptyBuffers.offer(old);
|
_emptyBuffers.offer(old);
|
||||||
long before = System.currentTimeMillis();
|
|
||||||
AsyncBuffer nextBuffer = null;
|
AsyncBuffer nextBuffer = null;
|
||||||
|
|
||||||
while (nextBuffer == null) {
|
while (nextBuffer == null) {
|
||||||
@ -115,11 +109,6 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long waited = System.currentTimeMillis()-before;
|
|
||||||
_context.statManager().addRateData("prng.bufferWaitTime", waited, 0);
|
|
||||||
if (waited > 10*1000 && _log.shouldLog(Log.WARN))
|
|
||||||
_log.warn(Thread.currentThread().getName() + ": Took " + waited
|
|
||||||
+ "ms for a full PRNG buffer to be found");
|
|
||||||
_currentBuffer = nextBuffer;
|
_currentBuffer = nextBuffer;
|
||||||
buffer = nextBuffer.buffer;
|
buffer = nextBuffer.buffer;
|
||||||
}
|
}
|
||||||
@ -162,26 +151,22 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doFill(byte buf[]) {
|
private void doFill(byte buf[]) {
|
||||||
//long start = System.currentTimeMillis();
|
if (pools != null) {
|
||||||
if (pool0Count >= MIN_POOL_SIZE
|
if (pool0Count >= MIN_POOL_SIZE
|
||||||
&& System.currentTimeMillis() - lastReseed > 100)
|
&& System.currentTimeMillis() - lastReseed > 100)
|
||||||
{
|
|
||||||
reseedCount++;
|
|
||||||
//byte[] seed = new byte[0];
|
|
||||||
for (int i = 0; i < NUM_POOLS; i++)
|
|
||||||
{
|
{
|
||||||
if (reseedCount % (1 << i) == 0) {
|
reseedCount++;
|
||||||
generator.addRandomBytes(pools[i].digest());
|
//byte[] seed = new byte[0];
|
||||||
}
|
for (int i = 0; i < NUM_POOLS; i++)
|
||||||
|
{
|
||||||
|
if (reseedCount % (1 << i) == 0) {
|
||||||
|
generator.addRandomBytes(pools[i].digest());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastReseed = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
lastReseed = System.currentTimeMillis();
|
} // else we're using DevRandom
|
||||||
}
|
|
||||||
generator.nextBytes(buf);
|
generator.nextBytes(buf);
|
||||||
//long now = System.currentTimeMillis();
|
|
||||||
//long diff = now-lastRefill;
|
|
||||||
//lastRefill = now;
|
|
||||||
//long refillTime = now-start;
|
|
||||||
//System.out.println("Refilling " + (++refillCount) + " after " + diff + " for the PRNG took " + refillTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
|
@ -18,10 +18,17 @@ class DevRandom implements IRandomStandalone {
|
|||||||
private static final String F = "/dev/random";
|
private static final String F = "/dev/random";
|
||||||
private final File file = new File(F);
|
private final File file = new File(F);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.66
|
||||||
|
*/
|
||||||
|
public static boolean isSupported() {
|
||||||
|
return (new File(F)).canRead();
|
||||||
|
}
|
||||||
|
|
||||||
public String name() { return F; }
|
public String name() { return F; }
|
||||||
|
|
||||||
public void init(Map<String, byte[]> attributes) {
|
public void init(Map<String, byte[]> attributes) {
|
||||||
if (!file.canRead())
|
if (!isSupported())
|
||||||
throw new IllegalStateException("Cannot open " + F);
|
throw new IllegalStateException("Cannot open " + F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +36,6 @@ class DevRandom implements IRandomStandalone {
|
|||||||
throw new IllegalStateException("unsupported");
|
throw new IllegalStateException("unsupported");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 0.9.58 added to interface
|
|
||||||
*/
|
|
||||||
public void nextBytes(byte[] out) throws IllegalStateException {
|
public void nextBytes(byte[] out) throws IllegalStateException {
|
||||||
nextBytes(out, 0, out.length);
|
nextBytes(out, 0, out.length);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@ import java.io.Serializable;
|
|||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.i2p.crypto.CryptixAESKeyCache;
|
import net.i2p.crypto.CryptixAESKeyCache;
|
||||||
@ -104,6 +103,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
|||||||
static final int NUM_POOLS = 32;
|
static final int NUM_POOLS = 32;
|
||||||
static final int MIN_POOL_SIZE = 64;
|
static final int MIN_POOL_SIZE = 64;
|
||||||
protected final IRandomStandalone generator;
|
protected final IRandomStandalone generator;
|
||||||
|
/** null if using DevRandom */
|
||||||
protected final MessageDigest[] pools;
|
protected final MessageDigest[] pools;
|
||||||
protected long lastReseed;
|
protected long lastReseed;
|
||||||
private int pool;
|
private int pool;
|
||||||
@ -121,23 +121,22 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
|||||||
*/
|
*/
|
||||||
public FortunaStandalone(boolean useDevRandom) {
|
public FortunaStandalone(boolean useDevRandom) {
|
||||||
super("Fortuna i2p");
|
super("Fortuna i2p");
|
||||||
|
if (useDevRandom && !DevRandom.isSupported())
|
||||||
|
useDevRandom = false;
|
||||||
generator = useDevRandom ? new DevRandom() : new Generator();
|
generator = useDevRandom ? new DevRandom() : new Generator();
|
||||||
pools = new MessageDigest[NUM_POOLS];
|
if (useDevRandom) {
|
||||||
for (int i = 0; i < NUM_POOLS; i++)
|
pools = null;
|
||||||
pools[i] = SHA256Generator.getDigestInstance();
|
} else {
|
||||||
allocBuffer();
|
pools = new MessageDigest[NUM_POOLS];
|
||||||
}
|
for (int i = 0; i < NUM_POOLS; i++) {
|
||||||
|
pools[i] = SHA256Generator.getDigestInstance();
|
||||||
/** Unused, see AsyncFortunaStandalone */
|
}
|
||||||
protected void allocBuffer() {
|
}
|
||||||
buffer = new byte[64*1024];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unused, see AsyncFortunaStandalone */
|
/** Unused, see AsyncFortunaStandalone */
|
||||||
public void seed(byte val[]) {
|
public void seed(byte val[]) {
|
||||||
Map<String, byte[]> props = Collections.singletonMap(SEED, val);
|
throw new UnsupportedOperationException("use override");
|
||||||
init(props);
|
|
||||||
fillBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup(Map<String, byte[]> attributes)
|
public void setup(Map<String, byte[]> attributes)
|
||||||
@ -152,31 +151,14 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
|||||||
/** Unused, see AsyncFortunaStandalone */
|
/** Unused, see AsyncFortunaStandalone */
|
||||||
public void fillBlock()
|
public void fillBlock()
|
||||||
{
|
{
|
||||||
//long start = System.currentTimeMillis();
|
throw new UnsupportedOperationException("use override");
|
||||||
if (pool0Count >= MIN_POOL_SIZE
|
|
||||||
&& System.currentTimeMillis() - lastReseed > 100)
|
|
||||||
{
|
|
||||||
reseedCount++;
|
|
||||||
//byte[] seed = new byte[0];
|
|
||||||
for (int i = 0; i < NUM_POOLS; i++)
|
|
||||||
{
|
|
||||||
if (reseedCount % (1 << i) == 0) {
|
|
||||||
generator.addRandomBytes(pools[i].digest());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastReseed = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
generator.nextBytes(buffer);
|
|
||||||
//long now = System.currentTimeMillis();
|
|
||||||
//long diff = now-lastRefill;
|
|
||||||
//lastRefill = now;
|
|
||||||
//long refillTime = now-start;
|
|
||||||
//System.out.println("Refilling " + (++refillCount) + " after " + diff + " for the PRNG took " + refillTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addRandomByte(byte b)
|
public void addRandomByte(byte b)
|
||||||
{
|
{
|
||||||
|
if (pools == null)
|
||||||
|
return;
|
||||||
pools[pool].update(b);
|
pools[pool].update(b);
|
||||||
if (pool == 0)
|
if (pool == 0)
|
||||||
pool0Count++;
|
pool0Count++;
|
||||||
@ -186,6 +168,8 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
|||||||
@Override
|
@Override
|
||||||
public void addRandomBytes(byte[] buf, int offset, int length)
|
public void addRandomBytes(byte[] buf, int offset, int length)
|
||||||
{
|
{
|
||||||
|
if (pools == null)
|
||||||
|
return;
|
||||||
pools[pool].update(buf, offset, length);
|
pools[pool].update(buf, offset, length);
|
||||||
if (pool == 0)
|
if (pool == 0)
|
||||||
pool0Count += length;
|
pool0Count += length;
|
||||||
|
@ -170,7 +170,7 @@ public class RouterContext extends I2PAppContext {
|
|||||||
// or about 2 seconds per buffer - so about 200x faster
|
// or about 2 seconds per buffer - so about 200x faster
|
||||||
// to fill than to drain - so we don't need too many
|
// to fill than to drain - so we don't need too many
|
||||||
long maxMemory = SystemVersion.getMaxMemory();
|
long maxMemory = SystemVersion.getMaxMemory();
|
||||||
long maxBuffs = (SystemVersion.isAndroid() || SystemVersion.isARM()) ? 3 : 5;
|
long maxBuffs = 3;
|
||||||
long buffs = Math.min(maxBuffs, Math.max(2, maxMemory / (21 * 1024 * 1024)));
|
long buffs = Math.min(maxBuffs, Math.max(2, maxMemory / (21 * 1024 * 1024)));
|
||||||
envProps.setProperty("prng.buffers", Long.toString(buffs));
|
envProps.setProperty("prng.buffers", Long.toString(buffs));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user