Author: nextgens
Date: 2007-10-21 15:27:24 +0000 (Sun, 21 Oct 2007)
New Revision: 15469
Modified:
trunk/freenet/src/freenet/node/FNPPacketMangler.java
trunk/freenet/src/freenet/node/PeerNode.java
Log:
JFK:
* Keep 10 signed exponents in a FIFO queue
* Serve a new one whenever possible
* Refill the queue every 30 sec if needed
That's probably better this way. What about the NewArbitraryValue I've
introduced? well you tell me :p
Is 1 *new* DH exponent every 30sec a reasonable rate ?
I wonder when we should clear the DH exponent on the responder's side...
Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-10-21
14:19:15 UTC (rev 15468)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-10-21
15:27:24 UTC (rev 15469)
@@ -8,6 +8,8 @@
import java.security.MessageDigest;
import java.util.Arrays;
+import java.util.LinkedList;
+
import net.i2p.util.NativeBigInteger;
import freenet.crypt.BlockCipher;
import freenet.crypt.DSA;
@@ -81,8 +83,8 @@
JFK_PREFIX_RESPONDER = R;
}
- /** We renew it every 30sec (the spec. says "once a while") - access is
synchronized! */
- private DiffieHellmanLightContext currentDHContext = null;
+ public final static int DH_CONTEXT_BUFFER_SIZE = 10;
+ private final LinkedList dhContextBuffer = new LinkedList();
private long currentDHContextLifetime = 0;
protected static final int NONCE_SIZE = 8;
@@ -506,9 +508,10 @@
*/
private void sendJFKMessage1(PeerNode pn, Peer replyTo) {
if(logMINOR) Logger.minor(this, "Sending a JFK(1) message to
"+pn);
- DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
+ if(pn.jfkContext == null) // get a new DH exponents only if
needed
+ pn.jfkContext = getLightDiffieHellmanContext();
int offset = 0;
- byte[] myExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] myExponential =
stripBigIntegerToNetworkFormat(pn.jfkContext.myExponential);
byte[] nonce = new byte[NONCE_SIZE];
node.random.nextBytes(nonce);
@@ -535,14 +538,14 @@
*/
private void sendJFKMessage2(byte[] nonceInitator, byte[]
hisExponential, PeerNode pn, Peer replyTo) {
if(logMINOR) Logger.minor(this, "Sending a JFK(2) message to
"+pn);
- DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
+ pn.jfkContext = getLightDiffieHellmanContext();
// g^r
- byte[] myExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] myExponential =
stripBigIntegerToNetworkFormat(pn.jfkContext.myExponential);
// Nr
byte[] myNonce = new byte[NONCE_SIZE];
node.random.nextBytes(myNonce);
- byte[] r =
dhContext.signature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
- byte[] s =
dhContext.signature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
+ byte[] r =
pn.jfkContext.signature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
+ byte[] s =
pn.jfkContext.signature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
HMAC hash = new HMAC(SHA256.getInstance());
byte[] authenticator =
hash.mac(getTransientKey(),assembleJFKAuthenticator(myExponential,
hisExponential, myNonce, nonceInitator, replyTo.getAddress().getAddress()),
HASH_LENGTH);
if(logMINOR) Logger.minor(this, "We are using the following
HMAC : " + HexUtil.bytesToHex(authenticator));
@@ -775,8 +778,7 @@
System.arraycopy(payload, inputOffset, hmac, 0, HASH_LENGTH);
inputOffset += HASH_LENGTH;
- DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
- BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DHgroupA);
+ BigInteger computedExponential =
pn.jfkContext.getHMACKey(_hisExponential, Global.DHgroupA);
byte[] Ks = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "0");
byte[] Ke = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
byte[] Ka = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
@@ -979,6 +981,9 @@
pn.jfkKa = null;
pn.jfkKe = null;
pn.jfkKs = null;
+ // We want to clear it here so that new handshake requests
+ // will be sent with a different DH pair
+ pn.jfkContext = null;
synchronized (pn) {
// FIXME TRUE MULTI-HOMING: winner-takes-all, kill all
other connection attempts since we can't deal with multiple active connections
// Also avoids leaking
@@ -1004,8 +1009,7 @@
if(logMINOR) Logger.minor(this, "Sending a JFK(3) message to
"+pn);
BlockCipher c = null;
try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
- DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
- byte[] ourExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] ourExponential =
stripBigIntegerToNetworkFormat(pn.jfkContext.myExponential);
pn.jfkMyRef = crypto.myCompressedSetupRef();
byte[] data = new byte[8 + pn.jfkMyRef.length];
System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0,
8);
@@ -1047,7 +1051,7 @@
byte[] r =
localSignature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s =
localSignature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
- BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DHgroupA);
+ BigInteger computedExponential =
pn.jfkContext.getHMACKey(_hisExponential, Global.DHgroupA);
pn.jfkKs = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "0");
pn.jfkKe = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
pn.jfkKa = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
@@ -1174,6 +1178,7 @@
else
authenticatorCache.put(authenticator, message4);
}
+
sendAuthPacket(1, 2, 3, message4, pn, replyTo);
}
@@ -2470,33 +2475,46 @@
final long now = System.currentTimeMillis();
boolean changeDHExponents = false;
+ boolean generateOnThread = false;
+ int dhContextBufferSize = 0;
- synchronized (this) {
- if((currentDHContext == null) ||
(currentDHContextLifetime + 30000 /*30sec*/) < now) {
+ synchronized (dhContextBuffer) {
+ dhContextBufferSize = dhContextBuffer.size();
+
+ if(dhContextBufferSize < 1) {
+ // We need one exponent, generate it at all
cost! (startup)
changeDHExponents = true;
+ generateOnThread = true;
+ } else if((dhContextBufferSize <
DH_CONTEXT_BUFFER_SIZE) && (currentDHContextLifetime + 30000 /*30sec*/) < now) {
+ changeDHExponents = true;
currentDHContextLifetime = now;
}
}
if(changeDHExponents) {
- if(currentDHContext == null) {
+ if(generateOnThread) {
Logger.minor(this, "No DH exponent have been
created; generate the context on-thread!");
// No need to synchronize here as we are
on-thread
- currentDHContext =
_genLightDiffieHellmanContext();
+
dhContextBuffer.add(_genLightDiffieHellmanContext());
} else {
// Use the ticket to do it off-thread
node.getTicker().queueTimedJob(new Runnable() {
public void run() {
- synchronized (this) {
- currentDHContext =
_genLightDiffieHellmanContext();
+ synchronized (dhContextBuffer) {
+
dhContextBuffer.addLast(_genLightDiffieHellmanContext());
}
}
}, 0);
Logger.minor(this, "The DH exponents will been
renewed soonish");
}
}
-
- return currentDHContext;
+
+ DiffieHellmanLightContext result;
+ synchronized (dhContextBuffer) {
+ // Don't remove the exponent from the list if it's the
only remaining one.
+ result = (DiffieHellmanLightContext)
(dhContextBufferSize < 2 ? dhContextBuffer.getFirst() :
dhContextBuffer.removeFirst());
+ }
+ return result;
}
/*
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2007-10-21 14:19:15 UTC
(rev 15468)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2007-10-21 15:27:24 UTC
(rev 15469)
@@ -28,6 +28,7 @@
import freenet.crypt.DSAGroup;
import freenet.crypt.DSAPublicKey;
import freenet.crypt.DSASignature;
+import freenet.crypt.DiffieHellmanLightContext;
import freenet.crypt.KeyAgreementSchemeContext;
import freenet.crypt.SHA256;
import freenet.crypt.UnsupportedCipherException;
@@ -96,6 +97,7 @@
protected byte[] jfkKe;
protected byte[] jfkKs;
protected byte[] jfkMyRef;
+ protected DiffieHellmanLightContext jfkContext = null;
/** My low-level address for SocketManager purposes */
private Peer detectedPeer;