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

This commit is contained in:
jrandom
2005-02-06 08:38:07 +00:00
committed by zzz
parent af8a618826
commit 80120b7b7d
4 changed files with 57 additions and 3 deletions

View File

@ -48,6 +48,7 @@ import net.i2p.util.RandomSource;
* @author jrandom
*/
public class DHSessionKeyBuilder {
private static I2PAppContext _context = I2PAppContext.getGlobalContext();
private final static Log _log = new Log(DHSessionKeyBuilder.class);
private static int MIN_NUM_BUILDERS = -1;
private static int MAX_NUM_BUILDERS = -1;
@ -68,7 +69,7 @@ public class DHSessionKeyBuilder {
public final static String DEFAULT_DH_PRECALC_DELAY = "1000";
static {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
I2PAppContext ctx = _context;
try {
int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN));
MIN_NUM_BUILDERS = val;
@ -305,6 +306,8 @@ public class DHSessionKeyBuilder {
_log.debug("Storing " + remaining.length + " bytes from the DH exchange by SHA256 the session key");
} else { // (buf.length >= 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];
System.arraycopy(buf, val.length, remaining, 0, remaining.length);
_extraExchangedBytes.setData(remaining);

View File

@ -154,11 +154,14 @@ public class ElGamalAESEngine {
byte preIV[] = null;
int offset = 0;
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);
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("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32));
@ -168,6 +171,9 @@ public class ElGamalAESEngine {
System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
_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);
if (_log.shouldLog(Log.DEBUG))
@ -403,6 +409,8 @@ public class ElGamalAESEngine {
elgEncr = elg;
}
//_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);
Hash ivHash = _context.sha().calculateHash(preIV, cache);

View File

@ -0,0 +1,30 @@
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);
}

View File

@ -12,6 +12,7 @@ package net.i2p.util;
import java.security.SecureRandom;
import net.i2p.I2PAppContext;
import net.i2p.crypto.EntropyHarvester;
/**
* Singleton for whatever PRNG i2p uses.
@ -20,10 +21,14 @@ import net.i2p.I2PAppContext;
*/
public class RandomSource extends SecureRandom {
private Log _log;
private EntropyHarvester _entropyHarvester;
public RandomSource(I2PAppContext context) {
super();
_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() {
return I2PAppContext.getGlobalContext().random();
@ -62,4 +67,12 @@ public class RandomSource extends SecureRandom {
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) {}
}
}