From db42d9ec373e432ff975688aa179950f6bb6f592 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 11 Sep 2012 19:40:20 +0000 Subject: [PATCH] * FortunaRandomSource: - Fix bug that wasted entropy in nextInt() - Improved synchronization --- .../crypto/prng/AsyncFortunaStandalone.java | 2 +- .../gnu/crypto/prng/BasePRNGStandalone.java | 5 +- .../src/net/i2p/util/FortunaRandomSource.java | 108 ++++++++++++------ 3 files changed, 73 insertions(+), 42 deletions(-) diff --git a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java index 71c9ed60c5..46e994695d 100644 --- a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java +++ b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java @@ -14,7 +14,7 @@ import net.i2p.util.Log; * * Note that this class is not fully Thread safe! * The following methods must be synchronized externally, they are not - * sycned here or in super(): + * synced here or in super(): * addRandomByte(), addRandomBytes(), nextByte(), nextBytes(), seed() * */ diff --git a/core/java/src/gnu/crypto/prng/BasePRNGStandalone.java b/core/java/src/gnu/crypto/prng/BasePRNGStandalone.java index 6b71330d86..4b88e0f0b5 100644 --- a/core/java/src/gnu/crypto/prng/BasePRNGStandalone.java +++ b/core/java/src/gnu/crypto/prng/BasePRNGStandalone.java @@ -55,7 +55,7 @@ public abstract class BasePRNGStandalone implements IRandomStandalone { // ------------------------------------------------------------------------- /** The canonical name prefix of the PRNG algorithm. */ - protected String name; + protected final String name; /** Indicate if this instance has already been initialised or not. */ protected boolean initialised; @@ -75,10 +75,7 @@ public abstract class BasePRNGStandalone implements IRandomStandalone { * @param name the canonical name of this instance. */ protected BasePRNGStandalone(String name) { - super(); - this.name = name; - initialised = false; buffer = new byte[0]; } diff --git a/core/java/src/net/i2p/util/FortunaRandomSource.java b/core/java/src/net/i2p/util/FortunaRandomSource.java index 6d57f1c6cc..2209785cf6 100644 --- a/core/java/src/net/i2p/util/FortunaRandomSource.java +++ b/core/java/src/net/i2p/util/FortunaRandomSource.java @@ -49,12 +49,16 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste * @since 0.8.8 */ public void shutdown() { - _fortuna.shutdown(); + synchronized(_fortuna) { + _fortuna.shutdown(); + } } @Override - public synchronized void setSeed(byte buf[]) { - _fortuna.addRandomBytes(buf); + public void setSeed(byte buf[]) { + synchronized(_fortuna) { + _fortuna.addRandomBytes(buf); + } } /** @@ -93,16 +97,21 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste // return (int)((n * (long)nextBits(31)) >> 31); //} - int numBits = 0; - int remaining = n; - int rv = 0; - while (remaining > 0) { - remaining >>= 1; - rv += nextBits(8) << numBits*8; - numBits++; + // get at least 4 extra bits if possible for better + // distribution after the % + int numBits; + if (n > 0xfffff) + numBits = 31; + else if (n > 0xfff) + numBits = 24; + else if (n > 0xf) + numBits = 16; + else + numBits = 8; + int rv; + synchronized(_fortuna) { + rv = nextBits(numBits); } - if (rv < 0) - rv += n; return rv % n; //int bits, val; @@ -121,7 +130,7 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste @Override public long nextLong(long n) { if (n == 0) return 0; - long rv = signedNextLong(n); + long rv = signedNextLong(); if (rv < 0) rv = 0 - rv; rv %= n; @@ -129,25 +138,31 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste } @Override - public long nextLong() { return signedNextLong(Long.MAX_VALUE); } + public long nextLong() { return signedNextLong(); } /** * Implementation from Sun's java.util.Random javadocs */ - private long signedNextLong(long n) { - return ((long)nextBits(32) << 32) + nextBits(32); + private long signedNextLong() { + synchronized(_fortuna) { + return ((long)nextBits(32) << 32) + nextBits(32); + } } @Override - public synchronized boolean nextBoolean() { - // wasteful, might be worth caching the boolean byte later - byte val = _fortuna.nextByte(); - return ((val & 0x01) == 1); + public boolean nextBoolean() { + byte val; + synchronized(_fortuna) { + val = _fortuna.nextByte(); + } + return ((val & 0x01) != 0); } @Override - public synchronized void nextBytes(byte buf[]) { - _fortuna.nextBytes(buf); + public void nextBytes(byte buf[]) { + synchronized(_fortuna) { + _fortuna.nextBytes(buf); + } } /** @@ -156,8 +171,10 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste * @since 0.8.12 */ @Override - public synchronized void nextBytes(byte buf[], int offset, int length) { - _fortuna.nextBytes(buf, offset, length); + public void nextBytes(byte buf[], int offset, int length) { + synchronized(_fortuna) { + _fortuna.nextBytes(buf, offset, length); + } } /** @@ -165,24 +182,35 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste */ @Override public double nextDouble() { - return (((long)nextBits(26) << 27) + nextBits(27)) / (double)(1L << 53); + long d; + synchronized(_fortuna) { + d = ((long)nextBits(26) << 27) + nextBits(27); + } + return d / (double)(1L << 53); } + /** * Implementation from sun's java.util.Random javadocs */ @Override public float nextFloat() { - return nextBits(24) / ((float)(1 << 24)); + int d; + synchronized(_fortuna) { + d = nextBits(24); + } + return d / ((float)(1 << 24)); } + /** * Implementation from sun's java.util.Random javadocs */ @Override - public synchronized double nextGaussian() { - if (_haveNextGaussian) { - _haveNextGaussian = false; - return _nextGaussian; - } else { + public double nextGaussian() { + synchronized (this) { + if (_haveNextGaussian) { + _haveNextGaussian = false; + return _nextGaussian; + } double v1, v2, s; do { v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0 @@ -197,10 +225,12 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste } /** - * Pull the next numBits of random data off the fortuna instance (returning -2^numBits-1 + * Pull the next numBits of random data off the fortuna instance (returning 0 * through 2^numBits-1 + * + * Caller must synchronize! */ - protected synchronized int nextBits(int numBits) { + protected int nextBits(int numBits) { long rv = 0; int bytes = (numBits + 7) / 8; for (int i = 0; i < bytes; i++) @@ -218,14 +248,18 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste /** reseed the fortuna */ @Override - public synchronized void feedEntropy(String source, long data, int bitoffset, int bits) { - _fortuna.addRandomByte((byte)(data & 0xFF)); + public void feedEntropy(String source, long data, int bitoffset, int bits) { + synchronized(_fortuna) { + _fortuna.addRandomByte((byte)(data & 0xFF)); + } } /** reseed the fortuna */ @Override - public synchronized void feedEntropy(String source, byte[] data, int offset, int len) { - _fortuna.addRandomBytes(data, offset, len); + public void feedEntropy(String source, byte[] data, int offset, int len) { + synchronized(_fortuna) { + _fortuna.addRandomBytes(data, offset, len); + } } /***** -- GitLab