diff --git a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java index ffff4a2acf3272438e9c8aa9deb85e57d02aea72..c0be6492baecd1b7eb493308d05409d85da101ce 100644 --- a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java +++ b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java @@ -7,6 +7,7 @@ import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; import net.i2p.util.I2PThread; import net.i2p.util.Log; +import net.i2p.util.SystemVersion; /** * fortuna instance that tries to avoid blocking if at all possible by using separate @@ -25,7 +26,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl * The router must override this via the prng.buffers property in the router context. */ private static final int DEFAULT_BUFFERS = 2; - private static final int DEFAULT_BUFSIZE = 256*1024; + private static final int DEFAULT_BUFSIZE = SystemVersion.isAndroid() ? 64*1024 : 256*1024; private final int _bufferCount; private final int _bufferSize; /** the lock */ @@ -39,7 +40,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl private AsyncBuffer _currentBuffer; public AsyncFortunaStandalone(I2PAppContext context) { - super(); + super(context.getBooleanProperty("prng.useDevRandom") && !SystemVersion.isWindows() && !SystemVersion.isSlow()); _bufferCount = Math.max(context.getProperty("prng.buffers", DEFAULT_BUFFERS), 2); _bufferSize = Math.max(context.getProperty("prng.bufferSize", DEFAULT_BUFSIZE), 16*1024); _emptyBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount); diff --git a/core/java/src/gnu/crypto/prng/DevRandom.java b/core/java/src/gnu/crypto/prng/DevRandom.java new file mode 100644 index 0000000000000000000000000000000000000000..a8f2cf2ff2776def222c4cb8bad4eb7e20fe8706 --- /dev/null +++ b/core/java/src/gnu/crypto/prng/DevRandom.java @@ -0,0 +1,57 @@ +package gnu.crypto.prng; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.Map; + +import net.i2p.data.DataHelper; + +/** + * Simple /dev/random reader + * + * @since 0.9.58 + */ +class DevRandom implements IRandomStandalone { + + private static final String F = "/dev/random"; + private final File file = new File(F); + + public String name() { return F; } + + public void init(Map<String, byte[]> attributes) { + if (!file.canRead()) + throw new IllegalStateException("Cannot open " + F); + } + + public byte nextByte() { + throw new IllegalStateException("unsupported"); + } + + /** + * @since 0.9.58 added to interface + */ + public void nextBytes(byte[] out) throws IllegalStateException { + nextBytes(out, 0, out.length); + } + + public void nextBytes(byte[] out, int offset, int length) throws IllegalStateException { + InputStream in = null; + try { + in = new FileInputStream(file); + DataHelper.read(in, out, offset, length); + } catch (IOException ioe) { + throw new IllegalStateException("Read failed " + F, ioe); + } finally { + if (in != null) try { in.close(); } catch (IOException ioe2) {} + } + } + + public void addRandomByte(byte b) {} + public void addRandomBytes(byte[] in) {} + public void addRandomBytes(byte[] in, int offset, int length) {} + + @Override + public Object clone() throws CloneNotSupportedException { return super.clone(); } +} diff --git a/core/java/src/gnu/crypto/prng/FortunaStandalone.java b/core/java/src/gnu/crypto/prng/FortunaStandalone.java index f444c11ec941b7b5330a2bc237072c223cd3731d..3856ebbd561610c8bc17167a4d7dc9279ea9add6 100644 --- a/core/java/src/gnu/crypto/prng/FortunaStandalone.java +++ b/core/java/src/gnu/crypto/prng/FortunaStandalone.java @@ -103,33 +103,34 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl private static final int SEED_FILE_SIZE = 64; static final int NUM_POOLS = 32; static final int MIN_POOL_SIZE = 64; - final Generator generator; - final MessageDigest[] pools; - long lastReseed; - int pool; - int pool0Count; - int reseedCount; - //static long refillCount = 0; - //static long lastRefill = System.currentTimeMillis(); + protected final IRandomStandalone generator; + protected final MessageDigest[] pools; + protected long lastReseed; + private int pool; + protected int pool0Count; + protected int reseedCount; public static final String SEED = "gnu.crypto.prng.fortuna.seed"; - public FortunaStandalone() - { + public FortunaStandalone() { + this(false); + } + + /** + * @since 0.9.58 + */ + public FortunaStandalone(boolean useDevRandom) { super("Fortuna i2p"); - generator = new Generator(); + generator = useDevRandom ? new DevRandom() : new Generator(); pools = new MessageDigest[NUM_POOLS]; for (int i = 0; i < NUM_POOLS; i++) pools[i] = SHA256Generator.getDigestInstance(); - lastReseed = 0; - pool = 0; - pool0Count = 0; allocBuffer(); } /** Unused, see AsyncFortunaStandalone */ protected void allocBuffer() { - buffer = new byte[4*1024*1024]; //256]; // larger buffer to reduce churn + buffer = new byte[64*1024]; } /** Unused, see AsyncFortunaStandalone */ @@ -213,7 +214,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl * right; Fortuna itself is basically a wrapper around this generator * that manages reseeding in a secure way. */ - public static class Generator extends BasePRNGStandalone implements Cloneable + private static class Generator extends BasePRNGStandalone implements Cloneable { private static final int LIMIT = 1 << 20; diff --git a/core/java/src/gnu/crypto/prng/IRandomStandalone.java b/core/java/src/gnu/crypto/prng/IRandomStandalone.java index 580ab4de0e1afc380c0eca1a6f6b86c850762574..dc3a6c63d159a713a26cc02d2bf34e31e4d67ba9 100644 --- a/core/java/src/gnu/crypto/prng/IRandomStandalone.java +++ b/core/java/src/gnu/crypto/prng/IRandomStandalone.java @@ -118,6 +118,11 @@ public interface IRandomStandalone extends Cloneable { */ byte nextByte() throws IllegalStateException; + /** + * @since 0.9.58 added to interface + */ + public void nextBytes(byte[] out) throws IllegalStateException; + /** * <p>Fills the designated byte array, starting from byte at index * <code>offset</code>, for a maximum of <code>length</code> bytes with the