[freenet-cvs] r15111 - branches/freenet-jfk/src/freenet/node

kryptos at freenetproject.org kryptos at freenetproject.org
Mon Sep 10 07:07:45 UTC 2007


Author: kryptos
Date: 2007-09-10 07:07:45 +0000 (Mon, 10 Sep 2007)
New Revision: 15111

Modified:
   branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
Message3 parsed and verified:Need to look into the Fixme's though

Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java	2007-09-10 05:00:08 UTC (rev 15110)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java	2007-09-10 07:07:45 UTC (rev 15111)
@@ -627,6 +627,7 @@
 	 * Send a signed copy of his own exponential
 	 * Send an authenticator which is a hash of Ni,Nr,g^r calculated over the transient key HKr
          * Format of JFK(2) as specified above
+         * @param Payload
 	 * @param The packet phase number
 	 * @param The peer to which we need to send the packet
 	 * @param The peerNode we are talking to
@@ -637,6 +638,7 @@
 		long t1=System.currentTimeMillis();
 		if(logMINOR) Logger.minor(this, "Got a JFK(2) message, processing it");
 		// FIXME: follow the spec and send IDr' ?
+                // FIXME: Are we checking for the right condition here?
 		if(payload.length < NONCE_SIZE + DiffieHellman.modulusLengthInBytes()) {
 			Logger.error(this, "Packet too short from "+pn+": "+payload.length+" after decryption in JFK("+phase+"), should be "+(NONCE_SIZE + DiffieHellman.modulusLengthInBytes()));
 			return;
@@ -709,64 +711,60 @@
 	 * @param The peerNode we are talking to
 	 * @return byte Message3
 	 */
-	private byte[] ProcessMessage3(byte[] payload, PeerNode pn,Peer replyTo,int phase)			
+	private void ProcessMessage3(byte[] payload, PeerNode pn,Peer replyTo,int phase)			
 	{
-		if(logMINOR) Logger.minor(this, "Got a JFK(3) message, processing it");
-		// Get the authenticator,which is the latest entry into the cache
-		// It is basically a keyed hash(HMAC); size of output is that of the underlying hash function 
-		byte[] authenticator = new byte[16];
-                byte[] Ni = iNonce();
-		byte[] Nr = rNonce();
-		byte[] DHExpi = Gi(pn);
-		byte[] DHExpr = Gr(pn);
-		byte[] unVerifiedData=new byte[Ni.length+Nr.length+DHExpr.length+DHExpi.length+1];
-		System.arraycopy(Ni,0,unVerifiedData,0,Ni.length);
-		System.arraycopy(Nr,0,unVerifiedData,Ni.length+1,Nr.length);
-		System.arraycopy(DHExpi,0,unVerifiedData,Ni.length+Nr.length+1,DHExpi.length);
-		System.arraycopy(DHExpr,0,unVerifiedData,Ni.length+Nr.length+DHExpi.length+1,DHExpr.length);
-		/*
-		 * Digital Signature of the message with the private key belonging to the initiator/responder
-		 * It is assumed to be non-message recovering
-		 */
-		PKI=new DSAPrivateKey(g, r);
-		//Params: Data,DSAGroup,DSAPrivateKey,randomSource
-		DSASignature sig = crypto.sign(unVerifiedData,g,PKI,r);
-		byte[] r = sig.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
-		byte[] s = sig.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
-		Logger.minor(this, " r="+HexUtil.bytesToHex(sig.getR().toByteArray())+" s="+HexUtil.bytesToHex(sig.getS().toByteArray()));
-		BlockCipher c=pn.outgoingSetupCipher;
-		if(logMINOR)
-			Logger.minor(this,"Cipher"+HexUtil.bytesToHex(pn.outgoingSetupKey));
-		/*
-		 * Initializes the cipher context with the given key
-		 * This would avoid the computation of key using the Rijndael key schedule(S boxes,Rcon etc)
-		 * The key used is generated from Hash of Message:(Ni, Nr, 1) over the shared key of DH
-		 */
-		c.initialize(encryptionKey.getEncKey(sharedSecretKey(pn),iNonce(),rNonce()));
-		PCFBMode pk=PCFBMode.create(c);
+		long t1 = System.currentTimeMillis();
+                if(logMINOR) Logger.minor(this, "Got a JFK(3) message, processing it");
+		int inputOffset=0;
+		byte[] nonceInitiator = new byte[NONCE_SIZE];
+		System.arraycopy(payload, inputOffset, nonceInitiator, 0, NONCE_SIZE);
+		inputOffset += NONCE_SIZE;
+		byte[] nonceResponder = new byte[NONCE_SIZE];
+		System.arraycopy(payload, inputOffset, nonceResponder, 0, NONCE_SIZE);
+		inputOffset += NONCE_SIZE;
+		byte[] ourExponential = new byte[DiffieHellman.modulusLengthInBytes()];
+		System.arraycopy(payload, inputOffset, ourExponential, 0, DiffieHellman.modulusLengthInBytes());
+		inputOffset += DiffieHellman.modulusLengthInBytes();
+		byte[] hisExponential = new byte[DiffieHellman.modulusLengthInBytes()];
+		System.arraycopy(payload, inputOffset, hisExponential, 0, DiffieHellman.modulusLengthInBytes());
+		inputOffset += DiffieHellman.modulusLengthInBytes();
+		NativeBigInteger _hisExponential = new NativeBigInteger(1, hisExponential);
+		if(_hisExponential.compareTo(NativeBigInteger.ONE) < 1) {
+			Logger.error(this, "We can't accept the exponential "+pn+" sent us; it's smaller than 1!!");
+			return;
+		}
+		byte[] remoteHashedAuthenticator = new byte[HASH_LENGTH];
+		System.arraycopy(payload, inputOffset, remoteHashedAuthenticator, 0, HASH_LENGTH);
+		inputOffset += HASH_LENGTH;
+                // FIXME: Is this the right way?
+                int cipherLength = payload.length-NONCE_SIZE*2-DiffieHellman.modulusLengthInBytes()*2-HASH_LENGTH;
+                byte[] encryptedData = new byte[cipherLength];
+                System.arraycopy(payload, inputOffset,encryptedData, 0, cipherLength);
+                inputOffset += cipherLength;
+                //Decrypt 
+                BlockCipher c=pn.outgoingSetupCipher;
+                PCFBMode pk=PCFBMode.create(c);
 		byte[] iv=new byte[pk.lengthIV()];
-		int encryptedDataLength = iv.length + r.length + s.length + 2;
-		/*
-		 * Data sent in the clear is signed and encrypted using PCFB and rijndael
-		 */
-		byte[] encryptedData = new byte[encryptedDataLength];
-		System.arraycopy(iv, 0, encryptedData, 0, iv.length);
-		int count = iv.length;
-		if(r.length > 255 || s.length > 255)
-			throw new IllegalStateException("R or S is too long: r.length="+r.length+" s.length="+s.length);
-		encryptedData[count++] = (byte) r.length;
-		System.arraycopy(r, 0, encryptedData, count, r.length);
-		count += r.length;
-		encryptedData[count++] = (byte) s.length;
-		System.arraycopy(s, 0, encryptedData, count, s.length);
-		count += s.length;
-		pk.blockEncipher(encryptedData, 0, encryptedData.length);
-		byte[] message3=new byte[encryptedData.length+authenticator.length+unVerifiedData.length+1];
-		System.arraycopy(encryptedData,0,message3,0,encryptedData.length);
-		System.arraycopy(authenticator,0,message3,encryptedData.length+1,authenticator.length);
-		System.arraycopy(unVerifiedData,0,message3,encryptedData.length+authenticator.length+1,unVerifiedData.length);
-		return message3;
-
+                pk.blockDecipher(encryptedData,0,cipherLength);
+                byte[] signData = new byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()*2];
+		int offset = 0;
+		System.arraycopy(nonceInitiator, 0, signData, offset, NONCE_SIZE);
+		offset += NONCE_SIZE;
+		System.arraycopy(nonceResponder, 0,signData, offset, NONCE_SIZE);
+		offset += NONCE_SIZE;
+		System.arraycopy(ourExponential, 0,signData, offset, ourExponential.length);
+		offset += ourExponential.length;
+                System.arraycopy(hisExponential, 0,signData, offset, hisExponential.length);
+		offset += hisExponential.length;
+		DSASignature signatureToCheck = new DSASignature(new String(encryptedData));
+		if(!DSA.verify(pn.peerPubKey, signatureToCheck, new NativeBigInteger(1,signData), false)) {
+			Logger.error(this, "The signature verification has failed!!");
+			return;
+		}
+                sendMessage4Packet(1, 2, 3, nonceInitiator, nonceResponder,ourExponential, hisExponential, remoteHashedAuthenticator, pn, replyTo);
+		long t2=System.currentTimeMillis();
+		if((t2-t1)>500)
+			Logger.error(this,"Message1 timeout error:Sending packet for"+pn.getPeer());
 	}
 
 	/*
@@ -823,7 +821,7 @@
 		count += s.length;
 		pk.blockEncipher(message4, 0, message4.length);
 		//Send params:Version,negType,phase,data,peernode,peer 
-		sendMessage4Packet(1,2,3,message4,pn,replyTo);
+		
 		long t2=System.currentTimeMillis();
 		if((t2-t1)>500)
 			Logger.error(this,"Message4 timeout error:Sending packet for"+pn.getPeer());
@@ -863,9 +861,57 @@
 		
 		DiffieHellmanLightContext dhContext = getLightDiffieHellmanContext();
 		byte[] ourExponential = dhContext.myExponential.toByteArray();
-		
-		byte[] output = new byte[nonceInitiator.length+3];
-		if((nonceInitiator.length+3) > sock.getMaxPacketSize())
+		byte[] unVerifiedData=new byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()*2];
+		int offset = 0;
+		System.arraycopy(nonceInitiator, 0, unVerifiedData, offset, NONCE_SIZE);
+		offset += NONCE_SIZE;
+		System.arraycopy(nonceResponder, 0, unVerifiedData, offset, NONCE_SIZE);
+		offset += NONCE_SIZE;
+		System.arraycopy(ourExponential, 0,unVerifiedData, offset, ourExponential.length);
+		offset += ourExponential.length;
+                System.arraycopy(hisExponential, 0,unVerifiedData, offset, hisExponential.length);
+		offset += hisExponential.length;
+		/*
+		 * Digital Signature of the message with the private key belonging to the initiator/responder
+		 * It is assumed to be non-message recovering
+		 */
+		//FIXME: is this the correct way of generating Signatures?
+                //FIXME: IDr not signed?
+                byte[] signature;
+		try {
+			signature = dhContext.signature.toString().getBytes("UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			Logger.error(this, "HUH ??, please report it :"+ e.getMessage(),e);
+			return;
+		}
+		BlockCipher c=pn.outgoingSetupCipher;
+		if(logMINOR)
+			Logger.minor(this,"Cipher"+HexUtil.bytesToHex(pn.outgoingSetupKey));
+		/*
+		 * Initializes the cipher context with the given key
+		 * This would avoid the computation of key using the Rijndael key schedule(S boxes,Rcon etc)
+		 * The key used is generated from Hash of Message:(Ni, Nr, 1) over the shared key of DH
+		 */
+		c.initialize(encryptionKey.getEncKey(sharedSecretKey(pn),nonceInitiator,nonceResponder));
+		PCFBMode pk=PCFBMode.create(c);
+		byte[] iv=new byte[pk.lengthIV()];
+		int encryptedDataLength = iv.length + signature.length + 2;
+		/*
+		 * Data sent in the clear is signed and encrypted using PCFB and rijndael
+		 */
+		byte[] encryptedData = new byte[encryptedDataLength];
+		System.arraycopy(iv, 0, encryptedData, 0, iv.length);
+		int count = iv.length;
+		encryptedData[count++] = (byte) signature.length;
+		System.arraycopy(signature, 0, encryptedData, count, signature.length);
+		count += signature.length;
+		pk.blockEncipher(encryptedData, 0, encryptedData.length);
+		byte[] message3=new byte[unVerifiedData.length+hashedAuthenticator.length+encryptedData.length];
+		System.arraycopy(unVerifiedData,0,message3,0,unVerifiedData.length);
+		System.arraycopy(hashedAuthenticator,0,message3,encryptedData.length,hashedAuthenticator.length);
+		System.arraycopy(encryptedData,0,message3,unVerifiedData.length+hashedAuthenticator.length,encryptedData.length);
+		byte[] output = new byte[message3.length+3];
+		if((message3.length+3) > sock.getMaxPacketSize())
 			throw new IllegalStateException("Packet length too long");
 		/*
 		 * The key for looking up messages in the cache is the authenticator
@@ -882,12 +928,12 @@
 			}
 			if(result != null) {
 				synchronized(message3Cache) {
-					message3Cache.put(hashedAuthenticator,nonceInitiator);
+					message3Cache.put(message3,hashedAuthenticator);
 				}
 				// We don't want to keep the lock while sending
 				try
 				{
-					sendMessage4Packet(1,2,3,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
+					sendAuthPacket(1,2,3,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
 				}
 				catch(IOException e){
 					Logger.error(this,"Error getting bytes");
@@ -895,9 +941,7 @@
 			}
 			sendAuthPacket(version, negType, 4, null, pn, replyTo);
 		}
-		else if(phase==3){
-			message4Cache.put(hashedAuthenticator,nonceInitiator.toString());
-		}
+		
 		else{ 
 			Logger.error(this,"Wrong message");
 
@@ -905,7 +949,7 @@
 		output[0] = (byte) version;
 		output[1] = (byte) negType;
 		output[2] = (byte) phase;
-		System.arraycopy(nonceInitiator, 0, output, 3, nonceInitiator.length);
+		System.arraycopy(message3, 0, output, 3, message3.length);
 		if(logMINOR) Logger.minor(this, "Sending auth packet for "+pn.getPeer()+" (phase="+phase+", ver="+version+", nt="+negType+") (last packet sent "+TimeUtil.formatTime(delta, 2, true)+" ago) to "+replyTo+" data.length="+nonceInitiator.length);
 		try
 		{
@@ -926,7 +970,7 @@
 	 * @param The peer to which we need to send the packet
 	 */
 
-	private void sendMessage4Packet(int version,int negType,int phase,byte[] data,PeerNode pn,Peer replyTo)
+	private void sendMessage4Packet(int version,int negType,int phase,byte[] data,byte[] nonceInitiator,byte[] nonceResponder,byte[] ourExponential,byte[] hisExponential,PeerNode pn,Peer replyTo)
 	{
 		if(logMINOR) Logger.minor(this, "Sending a JFK(4) message to "+pn);
 		long now = System.currentTimeMillis();




More information about the cvs mailing list