Author: nextgens
Date: 2007-09-27 18:05:57 +0000 (Thu, 27 Sep 2007)
New Revision: 15363
Modified:
branches/freenet-jfk/src/freenet/crypt/DiffieHellmanLightContext.java
branches/freenet-jfk/src/freenet/crypt/crypto_Random/eKey.java
branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
More work on jfk ... message3 is still not working; for some reason the
exponentials generated don't match.
Modified: branches/freenet-jfk/src/freenet/crypt/DiffieHellmanLightContext.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/DiffieHellmanLightContext.java
2007-09-27 10:53:01 UTC (rev 15362)
+++ branches/freenet-jfk/src/freenet/crypt/DiffieHellmanLightContext.java
2007-09-27 18:05:57 UTC (rev 15363)
@@ -43,7 +43,7 @@
if(logMINOR)
Logger.minor(this, "My exponent:
"+myExponent.toHexString()+", my exponential: "+myExponential.toHexString()+",
peer's exponential: "+peerExponential.toHexString());
NativeBigInteger sharedSecret =
- (NativeBigInteger) peerExponential.modPow(myExponent,
group.getP());
+ (NativeBigInteger) peerExponential.modPow(myExponent,
group.getQ());
if(logMINOR)
Logger.minor(this, "g^ir mod p = " +
sharedSecret.toString());
Modified: branches/freenet-jfk/src/freenet/crypt/crypto_Random/eKey.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/crypto_Random/eKey.java
2007-09-27 10:53:01 UTC (rev 15362)
+++ branches/freenet-jfk/src/freenet/crypt/crypto_Random/eKey.java
2007-09-27 18:05:57 UTC (rev 15363)
@@ -1,6 +1,7 @@
package freenet.crypt.crypto_Random;
import freenet.crypt.HMAC;
import freenet.crypt.SHA1;
+import freenet.crypt.SHA256;
public class eKey
{
@@ -19,8 +20,9 @@
System.arraycopy(Ni,0,byteArray,0,Ni.length);
System.arraycopy(Nr,0,byteArray,Ni.length,Nr.length);
byteArray[Ni.length + Nr.length] = (byte)1;
- HMAC s = new HMAC(SHA1.getInstance());
+ HMAC s = new HMAC(SHA256.getInstance());
return s.mac(DFExp,byteArray,DFExp.length);
+
}catch(Exception e){
System.err.println("Exception:" + e);
System.exit(1);
Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-27
10:53:01 UTC (rev 15362)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-27
18:05:57 UTC (rev 15363)
@@ -17,9 +17,9 @@
import freenet.crypt.DiffieHellmanContext;
import freenet.crypt.DiffieHellmanLightContext;
import freenet.crypt.EntropySource;
+import freenet.crypt.Global;
import freenet.crypt.HMAC;
import freenet.crypt.PCFBMode;
-import freenet.crypt.RijndaelPCFBMode;
import freenet.crypt.SHA256;
import freenet.crypt.UnsupportedCipherException;
import freenet.crypt.ciphers.Rijndael;
@@ -43,6 +43,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.HashMap;
@@ -505,7 +506,6 @@
offset += NONCE_SIZE;
if(logMINOR) Logger.minor(this, "My Exponential (message1),
length ="+DiffieHellman.modulusLengthInBytes()+" value ="+
dhContext.myExponential.toHexString());
System.arraycopy(myExponential, 0, message1, offset,
DiffieHellman.modulusLengthInBytes());
- offset += DiffieHellman.modulusLengthInBytes();
sendAuthPacket(1,2,0,message1,pn,replyTo);
}
@@ -525,13 +525,12 @@
// Nr
byte[] myNonce = new byte[NONCE_SIZE];
node.random.nextBytes(myNonce);
- // FIXME: can we do that ? is it (mod p) as well ?
byte[] r =
dhContext.signature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s =
dhContext.signature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
HMAC hash = new HMAC(SHA256.getInstance());
byte[] authenticator =
hash.mac(getTransientKey(),assembleJFKAuthenticator(myExponential, myNonce,
nonceInitator, replyTo.getAddress().getAddress()), HASH_LENGTH);
+ if(logMINOR) Logger.minor(this, "We are using the following
HMAC : " + HexUtil.bytesToHex(authenticator));
-
byte[] message2 = new
byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()+
Node.SIGNATURE_PARAMETER_LENGTH*2+
HASH_LENGTH];
@@ -636,11 +635,11 @@
return;
}
- byte[] remoteHashedAuthenticator = new byte[HASH_LENGTH];
- System.arraycopy(payload, inputOffset,
remoteHashedAuthenticator, 0, HASH_LENGTH);
+ byte[] authenticator = new byte[HASH_LENGTH];
+ System.arraycopy(payload, inputOffset, authenticator, 0,
HASH_LENGTH);
inputOffset += HASH_LENGTH;
// FIXME: maybe the cache should be checked before verifying
the signature
- sendMessage3Packet(1, 2, 3, nonceInitiator, nonceResponder,
hisExponential, remoteHashedAuthenticator, pn, replyTo);
+ sendMessage3Packet(1, 2, 3, nonceInitiator, nonceResponder,
hisExponential, authenticator, pn, replyTo);
long t2=System.currentTimeMillis();
if((t2-t1)>500)
@@ -672,7 +671,7 @@
final int expectedLength = NONCE_SIZE*2 +
DiffieHellman.modulusLengthInBytes()*2 +
HASH_LENGTH + // authenticator
HASH_LENGTH + // HMAC of the cyphertext
-
(c.getBlockSize() >> 3) + // ugly way of getting the size of the IV
+
c.getBlockSize() + // IV
HASH_LENGTH; // it's at least a signature
if(payload.length < expectedLength + 3) {
Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(3), should be "+(expectedLength +
3));
@@ -699,10 +698,11 @@
byte[] authenticator = new byte[HASH_LENGTH];
System.arraycopy(payload, inputOffset, authenticator, 0,
HASH_LENGTH);
inputOffset += HASH_LENGTH;
+ if(logMINOR) Logger.minor(this, "We got the following HMAC : "
+ HexUtil.bytesToHex(authenticator));
// FIXME: check the cache before or after the hmac verification
?
// is it cheaper to wait for the lock on authenticatorCache or
to verify the hmac ?
HMAC mac = new HMAC(SHA256.getInstance());
- if(!mac.verify(getTransientKey(),
assembleJFKAuthenticator(responderExponential, nonceResponder,
initiatorExponential, replyTo.getAddress().getAddress()) , authenticator)) {
+ if(!mac.verify(getTransientKey(),
assembleJFKAuthenticator(responderExponential, nonceResponder, nonceInitiator,
replyTo.getAddress().getAddress()) , authenticator)) {
Logger.error(this, "The HMAC doesn't match; let's
discard the packet (either we rekeyed or we are victim of forgery)");
return;
}
@@ -738,17 +738,26 @@
byte[] hmac = new byte[HASH_LENGTH];
System.arraycopy(payload, inputOffset, hmac, 0, HASH_LENGTH);
inputOffset += HASH_LENGTH;
- c.initialize();
+
+ DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext(pn);
+ BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DSAgroupBigA);
+ if(logMINOR) Logger.minor(this, "We have computed the following
exponential : " + HexUtil.biToHex(computedExponential));
+ byte[] Ke = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
+ if(logMINOR) Logger.minor(this, "We are using Ke=" +
HexUtil.bytesToHex(Ke));
+ byte[] Ka = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
+ if(logMINOR) Logger.minor(this, "We are using Ka=" +
HexUtil.bytesToHex(Ka));
+ c.initialize(Ke);
final PCFBMode pk = PCFBMode.create(c);
int ivLength = pk.lengthIV();
int decypheredPayloadOffset = 0;
// We compute the HMAC of ("I"+cyphertext) : the cyphertext
includes the IV!
- byte[] prefix = "I".getBytes("UTF-8");
+ byte[] prefix = null;
+ try { prefix = "I".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
byte[] decypheredPayload = new byte[prefix.length +
payload.length - inputOffset];
System.arraycopy(prefix, 0, decypheredPayload,
decypheredPayloadOffset, prefix.length);
decypheredPayloadOffset += prefix.length;
System.arraycopy(payload, inputOffset, decypheredPayload,
decypheredPayloadOffset, payload.length - inputOffset);
- if(!mac.verify(null /*FIXME*/, decypheredPayload, hmac)) {
+ if(!mac.verify(Ka, decypheredPayload, hmac)) {
Logger.error(this, "The digest-HMAC doesn't match;
let's discard the packet");
return;
}
@@ -812,89 +821,92 @@
* g^i
* g^r
* Authenticator
- * E[idI,S[Ni,Nr,g^i,g^r]] over the key Ka
+ * HMAC(cyphertext)
+ * IV + E[S[Ni,Nr,g^i,g^r]]
*/
- private void sendMessage3Packet(int version,int negType,int
phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] hisExponential, byte[]
hashedAuthenticator, PeerNode pn, Peer replyTo)
+ private void sendMessage3Packet(int version,int negType,int
phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] hisExponential, byte[]
authenticator, PeerNode pn, Peer replyTo)
{
if(logMINOR) Logger.minor(this, "Sending a JFK(3) message to
"+pn);
- long now = System.currentTimeMillis();
- long delta = now - pn.lastSentPacketTime();
-
+ BlockCipher c = null;
+ try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext(pn);
- byte[] ourExponential = dhContext.myExponential.toByteArray();
- byte[] unVerifiedData=new
byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()*2];
+ byte[] ourExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] message3 = new byte[NONCE_SIZE*2 + // nI, nR
+
DiffieHellman.modulusLengthInBytes()*2 + // g^i, g^r
+ HASH_LENGTH + // authenticator
+ HASH_LENGTH + // HMAC(cyphertext)
+ c.getBlockSize() + // IV
+ Node.SIGNATURE_PARAMETER_LENGTH * 2
// Signature (R,S)
+ ];
int offset = 0;
// Ni
- System.arraycopy(nonceInitiator, 0, unVerifiedData, offset,
NONCE_SIZE);
+ System.arraycopy(nonceInitiator, 0, message3, offset,
NONCE_SIZE);
offset += NONCE_SIZE;
// Nr
- System.arraycopy(nonceResponder, 0, unVerifiedData, offset,
NONCE_SIZE);
+ System.arraycopy(nonceResponder, 0, message3, offset,
NONCE_SIZE);
offset += NONCE_SIZE;
// g^i
- System.arraycopy(ourExponential, 0,unVerifiedData, offset,
ourExponential.length);
+ System.arraycopy(ourExponential, 0,message3, offset,
ourExponential.length);
offset += ourExponential.length;
// g^r
- System.arraycopy(hisExponential, 0,unVerifiedData, offset,
hisExponential.length);
+ System.arraycopy(hisExponential, 0,message3, offset,
hisExponential.length);
offset += hisExponential.length;
+ // Authenticator
+ System.arraycopy(authenticator, 0, message3, offset,
HASH_LENGTH);
+ offset += HASH_LENGTH;
/*
* Digital Signature of the message with the private key
belonging to the initiator/responder
* It is assumed to be non-message recovering
*/
- //FIXME: IDr not signed?
NativeBigInteger _ourExponential = new
NativeBigInteger(1,ourExponential);
NativeBigInteger _hisExponential = new
NativeBigInteger(1,hisExponential);
DSASignature localSignature =
signDHParams(nonceInitiator,nonceResponder,_ourExponential,_hisExponential);
byte[] r =
localSignature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s =
localSignature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
- // Encrypt idI,r,s
- // Encryption is performed using HMAC[Ni,Nr,1] over the key g^ir
- BlockCipher c=pn.incomingSetupCipher;
- /*
- * 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
- */
-
- NativeBigInteger tempKey =
dhContext.getHMACKey(_hisExponential, pn.peerCryptoGroup);
- byte[] eKey = tempKey.toByteArray();
-
c.initialize(encryptionKey.getEncKey(eKey,nonceInitiator,nonceResponder));
- PCFBMode pk=PCFBMode.create(c);
- byte[] iv=new byte[pk.lengthIV()];
+ BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DSAgroupBigA);
+ if(logMINOR) Logger.minor(this, "We have computed the following
exponential : " + HexUtil.biToHex(computedExponential));
+ byte[] Ke = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
+ if(logMINOR) Logger.minor(this, "We are using Ke=" +
HexUtil.bytesToHex(Ke));
+ byte[] Ka = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
+ if(logMINOR) Logger.minor(this, "We are using Ka=" +
HexUtil.bytesToHex(Ka));
+ if(logMINOR) Logger.minor(this, "we are re-sending
authenticator = " + HexUtil.bytesToHex(authenticator));
+ c.initialize(Ke);
+ PCFBMode pcfb = PCFBMode.create(c);
+ int ivLength = pcfb.lengthIV();
+ byte[] iv = new byte[ivLength];
node.random.nextBytes(iv);
- byte[] idI = new byte[0];
- /*
- * Save state at this point for signature verification in JFK(4)
- * Ni,Nr,g^i,g^r,Idi
- */
-
System.arraycopy(unVerifiedData,0,pn.bufferJFK,0,unVerifiedData.length);
-
System.arraycopy(idI,0,pn.bufferJFK,unVerifiedData.length,idI.length);
- int encryptedDataLength = iv.length + idI.length + r.length +
s.length + 2;
- byte[] encryptedData = new byte[encryptedDataLength];
- System.arraycopy(iv, 0, encryptedData, 0, iv.length);
- int count = iv.length;
-
- System.arraycopy(idI,0, encryptedData,count,idI.length);
- count += idI.length;
- System.arraycopy(r, 0, encryptedData, count, r.length);
- count += r.length;
-
- System.arraycopy(s, 0, encryptedData, count, s.length);
- count += s.length;
- pk.blockEncipher(encryptedData, 0, encryptedData.length);
- /*
- * Message Format:
- * [Ni,Nr,g^i,g^r]
- * Authenticator
- * Encrypted data
- */
- 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);
-
- sendAuthPacket(1,2,2,message3,pn,replyTo);
+ pcfb.reset(iv);
+ int cleartextOffset = 0;
+ byte[] prefix = null;
+ try { prefix = "I".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
+
+ byte[] cleartext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2];
+ System.arraycopy(prefix, 0, cleartext, cleartextOffset,
prefix.length);
+ cleartextOffset += prefix.length;
+ System.arraycopy(iv, 0, cleartext, cleartextOffset, ivLength);
+ cleartextOffset += ivLength;
+ System.arraycopy(r, 0, cleartext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
+ cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+ System.arraycopy(s, 0, cleartext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
+ cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+
+ // We compute the HMAC of ("I"+cyphertext) : the cyphertext
includes the IV!
+ HMAC mac = new HMAC(SHA256.getInstance());
+ byte[] hmac = mac.mac(Ka, cleartext, HASH_LENGTH);
+
+ int cleartextToEncypherOffset = prefix.length + ivLength;
+ pcfb.blockEncipher(cleartext, cleartextToEncypherOffset,
Node.SIGNATURE_PARAMETER_LENGTH * 2);
+
+ // copy stuffs back to the message
+ System.arraycopy(hmac, 0, message3, offset, HASH_LENGTH);
+ offset += HASH_LENGTH;
+ System.arraycopy(iv, 0, message3, offset, ivLength);
+ offset += ivLength;
+ System.arraycopy(cleartext, cleartextToEncypherOffset,
message3, offset, Node.SIGNATURE_PARAMETER_LENGTH * 2);
+
+ sendAuthPacket(1, 2, 2, message3, pn, replyTo);
}
/*
@@ -2315,6 +2327,23 @@
return transientKey;
}
}
+
+ private byte[] computeJFKSharedKey(BigInteger exponential, byte[] nI,
byte[] nR, String what) {
+ assert("0".equals(what) || "1".equals(what) ||
"2".equals(what));
+ HMAC mac = new HMAC(SHA256.getInstance());
+ byte[] number = null;
+ try { number = what.getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
+
+ byte[] toHash = new byte[NONCE_SIZE * 2 + number.length];
+ int offset = 0;
+ System.arraycopy(nI, 0, toHash, offset, NONCE_SIZE);
+ offset += NONCE_SIZE;
+ System.arraycopy(nR, 0, toHash, offset, NONCE_SIZE);
+ offset += NONCE_SIZE;
+ System.arraycopy(number, 0, toHash, offset, number.length);
+
+ return mac.mac(exponential.toByteArray(), toHash, HASH_LENGTH);
+ }
//TODO: when shall that be called ? what about DH exponentials ?
private void resetTransientKey() {