On Sunday 21 October 2007 16:27, you wrote:
> 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

Increasing it uses more memory, and an attacker could exhaust a larger queue 
almost as quickly. However it would allow slightly more forward secrecy under 
heavy load. But the difference is marginal: our *real* forward secrecy 
depends on how long the connections retain the negotiated keys, not on their 
being completely unrelated to one another.

In fact you could argue that it's unnecesary complexity to have a queue at 
all, but since the JFK paper suggests it, it's probably a good idea.

Is 1 *new* DH exponent every 30sec a reasonable rate ?

Yes. It's a trivial amount of CPU and memory, unlike the cost of creating a 
new DH exponent per packet, which is what we'd be doing with STS (one of the 
reasons for using JFK).

Oh and you should synchronize on pn when accessing pn.jfkContext. The below 
suggests NPEs.
> 
> 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;
> 
> _______________________________________________
> cvs mailing list
> cvs at freenetproject.org
> http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<https://emu.freenetproject.org/pipermail/devl/attachments/20071023/fb61bf30/attachment.pgp>

Reply via email to