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

Skip to content
Snippets Groups Projects
Commit 80120b7b authored by jrandom's avatar jrandom Committed by zzz
Browse files

added entropy feeding interface, and hooked it up to the end of the DH...

added entropy feeding interface, and hooked it up to the end of the DH exchange (source=DH) as well as the end of the ElGamal/AES decrypt (source=ElG/AES).  the default RandomSource ignores this data
parent af8a6188
No related branches found
No related tags found
No related merge requests found
...@@ -48,6 +48,7 @@ import net.i2p.util.RandomSource; ...@@ -48,6 +48,7 @@ import net.i2p.util.RandomSource;
* @author jrandom * @author jrandom
*/ */
public class DHSessionKeyBuilder { public class DHSessionKeyBuilder {
private static I2PAppContext _context = I2PAppContext.getGlobalContext();
private final static Log _log = new Log(DHSessionKeyBuilder.class); private final static Log _log = new Log(DHSessionKeyBuilder.class);
private static int MIN_NUM_BUILDERS = -1; private static int MIN_NUM_BUILDERS = -1;
private static int MAX_NUM_BUILDERS = -1; private static int MAX_NUM_BUILDERS = -1;
...@@ -68,7 +69,7 @@ public class DHSessionKeyBuilder { ...@@ -68,7 +69,7 @@ public class DHSessionKeyBuilder {
public final static String DEFAULT_DH_PRECALC_DELAY = "1000"; public final static String DEFAULT_DH_PRECALC_DELAY = "1000";
static { static {
I2PAppContext ctx = I2PAppContext.getGlobalContext(); I2PAppContext ctx = _context;
try { try {
int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN)); int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN));
MIN_NUM_BUILDERS = val; MIN_NUM_BUILDERS = val;
...@@ -305,6 +306,8 @@ public class DHSessionKeyBuilder { ...@@ -305,6 +306,8 @@ public class DHSessionKeyBuilder {
_log.debug("Storing " + remaining.length + " bytes from the DH exchange by SHA256 the session key"); _log.debug("Storing " + remaining.length + " bytes from the DH exchange by SHA256 the session key");
} else { // (buf.length >= val.length) } else { // (buf.length >= val.length)
System.arraycopy(buf, 0, val, 0, val.length); System.arraycopy(buf, 0, val, 0, val.length);
// feed the extra bytes into the PRNG
_context.random().harvester().feedEntropy("DH", buf, val.length, buf.length-val.length);
byte remaining[] = new byte[buf.length - val.length]; byte remaining[] = new byte[buf.length - val.length];
System.arraycopy(buf, val.length, remaining, 0, remaining.length); System.arraycopy(buf, val.length, remaining, 0, remaining.length);
_extraExchangedBytes.setData(remaining); _extraExchangedBytes.setData(remaining);
......
...@@ -154,11 +154,14 @@ public class ElGamalAESEngine { ...@@ -154,11 +154,14 @@ public class ElGamalAESEngine {
byte preIV[] = null; byte preIV[] = null;
int offset = 0;
byte key[] = new byte[SessionKey.KEYSIZE_BYTES]; byte key[] = new byte[SessionKey.KEYSIZE_BYTES];
System.arraycopy(elgDecr, 0, key, 0, SessionKey.KEYSIZE_BYTES); System.arraycopy(elgDecr, offset, key, 0, SessionKey.KEYSIZE_BYTES);
offset += SessionKey.KEYSIZE_BYTES;
usedKey.setData(key); usedKey.setData(key);
preIV = new byte[32]; preIV = new byte[32];
System.arraycopy(elgDecr, SessionKey.KEYSIZE_BYTES, preIV, 0, 32); System.arraycopy(elgDecr, offset, preIV, 0, 32);
offset += 32;
//_log.debug("Pre IV for decryptNewSession: " + DataHelper.toString(preIV, 32)); //_log.debug("Pre IV for decryptNewSession: " + DataHelper.toString(preIV, 32));
//_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32)); //_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32));
...@@ -168,6 +171,9 @@ public class ElGamalAESEngine { ...@@ -168,6 +171,9 @@ public class ElGamalAESEngine {
System.arraycopy(ivHash.getData(), 0, iv, 0, 16); System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
_context.sha().cache().release(cache); _context.sha().cache().release(cache);
// feed the extra bytes into the PRNG
_context.random().harvester().feedEntropy("ElG/AES", elgDecr, offset, elgDecr.length - offset);
byte aesDecr[] = decryptAESBlock(data, 514, data.length-514, usedKey, iv, null, foundTags, foundKey); byte aesDecr[] = decryptAESBlock(data, 514, data.length-514, usedKey, iv, null, foundTags, foundKey);
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
...@@ -403,6 +409,8 @@ public class ElGamalAESEngine { ...@@ -403,6 +409,8 @@ public class ElGamalAESEngine {
elgEncr = elg; elgEncr = elg;
} }
//_log.debug("ElGamal encrypted length: " + elgEncr.length + " elGamal source length: " + elgSrc.toByteArray().length); //_log.debug("ElGamal encrypted length: " + elgEncr.length + " elGamal source length: " + elgSrc.toByteArray().length);
// should we also feed the encrypted elG block into the harvester?
SHA256EntryCache.CacheEntry cache = _context.sha().cache().acquire(preIV.length); SHA256EntryCache.CacheEntry cache = _context.sha().cache().acquire(preIV.length);
Hash ivHash = _context.sha().calculateHash(preIV, cache); Hash ivHash = _context.sha().calculateHash(preIV, cache);
......
package net.i2p.crypto;
/**
* Allow various components with some entropy to feed that entropy back
* into some PRNG. The quality of the entropy provided varies, so anything
* harvesting should discriminate based on the offered "source" of the
* entropy, silently discarding insufficient entropy sources.
*
*/
public interface EntropyHarvester {
/**
* Feed the entropy pools with data[offset:offset+len]
*
* @param source origin of the entropy, allowing the harvester to
* determine how much to value the data
* @param offset index into the data array to start
* @param len how many bytes to use
*/
void feedEntropy(String source, byte data[], int offset, int len);
/**
* Feed the entropy pools with the bits in the data
*
* @param source origin of the entropy, allowing the harvester to
* determine how much to value the data
* @param bitoffset bit index into the data array to start
* (using java standard big-endian)
* @param bits how many bits to use
*/
void feedEntropy(String source, long data, int bitoffset, int bits);
}
...@@ -12,6 +12,7 @@ package net.i2p.util; ...@@ -12,6 +12,7 @@ package net.i2p.util;
import java.security.SecureRandom; import java.security.SecureRandom;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.crypto.EntropyHarvester;
/** /**
* Singleton for whatever PRNG i2p uses. * Singleton for whatever PRNG i2p uses.
...@@ -20,10 +21,14 @@ import net.i2p.I2PAppContext; ...@@ -20,10 +21,14 @@ import net.i2p.I2PAppContext;
*/ */
public class RandomSource extends SecureRandom { public class RandomSource extends SecureRandom {
private Log _log; private Log _log;
private EntropyHarvester _entropyHarvester;
public RandomSource(I2PAppContext context) { public RandomSource(I2PAppContext context) {
super(); super();
_log = context.logManager().getLog(RandomSource.class); _log = context.logManager().getLog(RandomSource.class);
// when we replace to have hooks for fortuna (etc), replace with
// a factory (or just a factory method)
_entropyHarvester = new DummyEntropyHarvester();
} }
public static RandomSource getInstance() { public static RandomSource getInstance() {
return I2PAppContext.getGlobalContext().random(); return I2PAppContext.getGlobalContext().random();
...@@ -62,4 +67,12 @@ public class RandomSource extends SecureRandom { ...@@ -62,4 +67,12 @@ public class RandomSource extends SecureRandom {
super.nextBytes(bytes); super.nextBytes(bytes);
} }
} }
public EntropyHarvester harvester() { return _entropyHarvester; }
// noop
private static class DummyEntropyHarvester implements EntropyHarvester {
public void feedEntropy(String source, long data, int bitoffset, int bits) {}
public void feedEntropy(String source, byte[] data, int offset, int len) {}
}
} }
\ No newline at end of file
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