I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit fe575a38 authored by zzz's avatar zzz
Browse files

fix up DH like YK

parent 4c9558c5
No related branches found
No related tags found
No related merge requests found
...@@ -13,8 +13,7 @@ import java.io.IOException; ...@@ -13,8 +13,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.concurrent.LinkedBlockingQueue;
import java.util.List;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.I2PException; import net.i2p.I2PException;
...@@ -48,14 +47,15 @@ import net.i2p.util.RandomSource; ...@@ -48,14 +47,15 @@ import net.i2p.util.RandomSource;
* @author jrandom * @author jrandom
*/ */
public class DHSessionKeyBuilder { public class DHSessionKeyBuilder {
private static I2PAppContext _context = I2PAppContext.getGlobalContext(); private static final I2PAppContext _context = I2PAppContext.getGlobalContext();
private final static Log _log = new Log(DHSessionKeyBuilder.class); private static final Log _log;
private static int MIN_NUM_BUILDERS = -1; private static final int MIN_NUM_BUILDERS;
private static int MAX_NUM_BUILDERS = -1; private static final int MAX_NUM_BUILDERS;
private static int CALC_DELAY = -1; private static final int CALC_DELAY;
/* FIXME this should be final if you syncronize FIXME */ private static final LinkedBlockingQueue<DHSessionKeyBuilder> _builders;
private static volatile List _builders = new ArrayList(50); private static final Thread _precalcThread;
private static Thread _precalcThread = null;
// the data of importance
private BigInteger _myPrivateValue; private BigInteger _myPrivateValue;
private BigInteger _myPublicValue; private BigInteger _myPublicValue;
private BigInteger _peerValue; private BigInteger _peerValue;
...@@ -65,17 +65,31 @@ public class DHSessionKeyBuilder { ...@@ -65,17 +65,31 @@ public class DHSessionKeyBuilder {
public final static String PROP_DH_PRECALC_MIN = "crypto.dh.precalc.min"; public final static String PROP_DH_PRECALC_MIN = "crypto.dh.precalc.min";
public final static String PROP_DH_PRECALC_MAX = "crypto.dh.precalc.max"; public final static String PROP_DH_PRECALC_MAX = "crypto.dh.precalc.max";
public final static String PROP_DH_PRECALC_DELAY = "crypto.dh.precalc.delay"; public final static String PROP_DH_PRECALC_DELAY = "crypto.dh.precalc.delay";
public final static int DEFAULT_DH_PRECALC_MIN = 5; public final static int DEFAULT_DH_PRECALC_MIN = 15;
public final static int DEFAULT_DH_PRECALC_MAX = 50; public final static int DEFAULT_DH_PRECALC_MAX = 40;
public final static int DEFAULT_DH_PRECALC_DELAY = 10000; public final static int DEFAULT_DH_PRECALC_DELAY = 200;
/** check every 30 seconds whether we have less than the minimum */
private static long _checkDelay = 30 * 1000;
static { static {
I2PAppContext ctx = _context; I2PAppContext ctx = _context;
ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); _log = ctx.logManager().getLog(DHSessionKeyBuilder.class);
ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*60*1000 });
MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN); ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*60*1000 });
MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, DEFAULT_DH_PRECALC_MAX); ctx.statManager().createRateStat("crypto.DHUsed", "Need a DH from the queue", "Encryption", new long[] { 60*60*1000 });
ctx.statManager().createRateStat("crypto.DHEmpty", "DH queue empty", "Encryption", new long[] { 60*60*1000 });
// add to the defaults for every 128MB of RAM, up to 512MB
long maxMemory = Runtime.getRuntime().maxMemory();
int factor = Math.min(4, (int) (1 + (maxMemory / (128*1024*1024l))));
int defaultMin = DEFAULT_DH_PRECALC_MIN * factor;
int defaultMax = DEFAULT_DH_PRECALC_MAX * factor;
MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, defaultMin);
MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, defaultMax);
CALC_DELAY = ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY); CALC_DELAY = ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY);
_builders = new LinkedBlockingQueue(MAX_NUM_BUILDERS);
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("DH Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: " _log.debug("DH Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: "
...@@ -90,40 +104,33 @@ public class DHSessionKeyBuilder { ...@@ -90,40 +104,33 @@ public class DHSessionKeyBuilder {
/** /**
* Construct a new DH key builder * Construct a new DH key builder
* * or pulls a prebuilt one from the queue.
*/ */
public DHSessionKeyBuilder() { public DHSessionKeyBuilder() {
this(false); _context.statManager().addRateData("crypto.DHUsed", 1, 0);
DHSessionKeyBuilder builder = null; DHSessionKeyBuilder builder = _builders.poll();
synchronized (_builders) {
if (!_builders.isEmpty()) {
builder = (DHSessionKeyBuilder) _builders.remove(0);
if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder. # left = " + _builders.size());
} else {
if (_log.shouldLog(Log.WARN)) _log.warn("NO MORE BUILDERS! creating one now");
}
}
if (builder != null) { if (builder != null) {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder. # left = " + _builders.size());
_myPrivateValue = builder._myPrivateValue; _myPrivateValue = builder._myPrivateValue;
_myPublicValue = builder._myPublicValue; _myPublicValue = builder._myPublicValue;
_peerValue = builder._peerValue; // these two are still null after precalc
_sessionKey = builder._sessionKey; //_peerValue = builder._peerValue;
//_sessionKey = builder._sessionKey;
_extraExchangedBytes = builder._extraExchangedBytes; _extraExchangedBytes = builder._extraExchangedBytes;
} else { } else {
_myPrivateValue = null; if (_log.shouldLog(Log.INFO)) _log.info("No more builders, creating one now");
_myPublicValue = null; _context.statManager().addRateData("crypto.DHEmpty", 1, 0);
_peerValue = null; // sets _myPrivateValue as a side effect
_sessionKey = null;
_myPublicValue = generateMyValue(); _myPublicValue = generateMyValue();
_extraExchangedBytes = new ByteArray(); _extraExchangedBytes = new ByteArray();
} }
} }
public DHSessionKeyBuilder(boolean usePool) { /**
_myPrivateValue = null; * Only for internal use
_myPublicValue = null; * @parameter usePool unused, just to make it different from other constructor
_peerValue = null; */
_sessionKey = null; private DHSessionKeyBuilder(boolean usePool) {
_extraExchangedBytes = new ByteArray(); _extraExchangedBytes = new ByteArray();
} }
...@@ -189,18 +196,12 @@ public class DHSessionKeyBuilder { ...@@ -189,18 +196,12 @@ public class DHSessionKeyBuilder {
} }
private static final int getSize() { private static final int getSize() {
synchronized (_builders) {
return _builders.size(); return _builders.size();
}
} }
private static final int addBuilder(DHSessionKeyBuilder builder) { /** @return true if successful, false if full */
int sz = 0; private static final boolean addBuilder(DHSessionKeyBuilder builder) {
synchronized (_builders) { return _builders.offer(builder);
_builders.add(builder);
sz = _builders.size();
}
return sz;
} }
/** /**
...@@ -210,7 +211,7 @@ public class DHSessionKeyBuilder { ...@@ -210,7 +211,7 @@ public class DHSessionKeyBuilder {
*/ */
public BigInteger generateMyValue() { public BigInteger generateMyValue() {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
_myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, RandomSource.getInstance()); _myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, _context.random());
BigInteger myValue = CryptoConstants.elgg.modPow(_myPrivateValue, CryptoConstants.elgp); BigInteger myValue = CryptoConstants.elgg.modPow(_myPrivateValue, CryptoConstants.elgp);
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
long diff = end - start; long diff = end - start;
...@@ -314,6 +315,7 @@ public class DHSessionKeyBuilder { ...@@ -314,6 +315,7 @@ public class DHSessionKeyBuilder {
* If there aren't enough bytes (with all of them being consumed by the 32 byte key), * If there aren't enough bytes (with all of them being consumed by the 32 byte key),
* the SHA256 of the key itself is used. * the SHA256 of the key itself is used.
* *
* @return non-null (but rv.getData() may be null)
*/ */
public ByteArray getExtraBytes() { public ByteArray getExtraBytes() {
return _extraExchangedBytes; return _extraExchangedBytes;
...@@ -406,6 +408,7 @@ public class DHSessionKeyBuilder { ...@@ -406,6 +408,7 @@ public class DHSessionKeyBuilder {
} }
*/ */
/******
public static void main(String args[]) { public static void main(String args[]) {
//if (true) { testValidation(); return; } //if (true) { testValidation(); return; }
...@@ -419,7 +422,7 @@ public class DHSessionKeyBuilder { ...@@ -419,7 +422,7 @@ public class DHSessionKeyBuilder {
long negTime = 0; long negTime = 0;
try { try {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
long startNeg = Clock.getInstance().now(); long startNeg = System.currentTimeMillis();
DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder(); DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder();
DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder(); DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder();
BigInteger pub1 = builder1.getMyPublicValue(); BigInteger pub1 = builder1.getMyPublicValue();
...@@ -428,7 +431,7 @@ public class DHSessionKeyBuilder { ...@@ -428,7 +431,7 @@ public class DHSessionKeyBuilder {
builder1.setPeerPublicValue(pub2); builder1.setPeerPublicValue(pub2);
SessionKey key1 = builder1.getSessionKey(); SessionKey key1 = builder1.getSessionKey();
SessionKey key2 = builder2.getSessionKey(); SessionKey key2 = builder2.getSessionKey();
long endNeg = Clock.getInstance().now(); long endNeg = System.currentTimeMillis();
negTime += endNeg - startNeg; negTime += endNeg - startNeg;
if (!key1.equals(key2)) if (!key1.equals(key2))
...@@ -458,10 +461,11 @@ public class DHSessionKeyBuilder { ...@@ -458,10 +461,11 @@ public class DHSessionKeyBuilder {
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
} }
******/
private static class DHSessionKeyBuilderPrecalcRunner implements Runnable { private static class DHSessionKeyBuilderPrecalcRunner implements Runnable {
private int _minSize; private final int _minSize;
private int _maxSize; private final int _maxSize;
private DHSessionKeyBuilderPrecalcRunner(int minSize, int maxSize) { private DHSessionKeyBuilderPrecalcRunner(int minSize, int maxSize) {
_minSize = minSize; _minSize = minSize;
...@@ -472,22 +476,28 @@ public class DHSessionKeyBuilder { ...@@ -472,22 +476,28 @@ public class DHSessionKeyBuilder {
while (true) { while (true) {
int curSize = 0; int curSize = 0;
long start = Clock.getInstance().now(); long start = System.currentTimeMillis();
int startSize = getSize(); int startSize = getSize();
// Adjust delay
if (startSize <= (_minSize * 2 / 3) && _checkDelay > 1000)
_checkDelay -= 1000;
else if (startSize > (_minSize * 3 / 2) && _checkDelay < 60*1000)
_checkDelay += 1000;
curSize = startSize; curSize = startSize;
while (curSize < _minSize) { if (curSize < _minSize) {
while (curSize < _maxSize) { for (int i = curSize; i < _maxSize; i++) {
long curStart = System.currentTimeMillis(); long curStart = System.currentTimeMillis();
curSize = addBuilder(precalc(curSize)); if (!addBuilder(precalc()))
break;
long curCalc = System.currentTimeMillis() - curStart; long curCalc = System.currentTimeMillis() - curStart;
// for some relief... // for some relief...
try { try {
Thread.sleep(CALC_DELAY + curCalc * 10); Thread.sleep(CALC_DELAY + (curCalc * 3));
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
} }
} }
long end = Clock.getInstance().now(); long end = System.currentTimeMillis();
int numCalc = curSize - startSize; int numCalc = curSize - startSize;
if (numCalc > 0) { if (numCalc > 0) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
...@@ -496,16 +506,15 @@ public class DHSessionKeyBuilder { ...@@ -496,16 +506,15 @@ public class DHSessionKeyBuilder {
+ (CALC_DELAY * numCalc) + "ms relief). now sleeping"); + (CALC_DELAY * numCalc) + "ms relief). now sleeping");
} }
try { try {
Thread.sleep(30 * 1000); Thread.sleep(_checkDelay);
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
} }
} }
private DHSessionKeyBuilder precalc(int i) { private static DHSessionKeyBuilder precalc() {
DHSessionKeyBuilder builder = new DHSessionKeyBuilder(false); DHSessionKeyBuilder builder = new DHSessionKeyBuilder(false);
builder.getMyPublicValue(); builder.getMyPublicValue();
//_log.debug("Precalc " + i + " complete");
return builder; return builder;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment