Author: nextgens
Date: 2007-09-10 12:05:40 +0000 (Mon, 10 Sep 2007)
New Revision: 15115
Modified:
branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
Send AuthMessage1, fix numerous bugs... add logging strings
They are still problems with the parsing of DSAgroups/signatures
Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-10
10:02:23 UTC (rev 15114)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-10
12:05:40 UTC (rev 15115)
@@ -36,6 +36,7 @@
import freenet.io.comm.PacketSocketHandler;
import freenet.io.comm.Peer;
import freenet.io.comm.PeerContext;
+import freenet.support.BitArray;
import freenet.support.HexUtil;
import freenet.support.Logger;
import freenet.support.StringArray;
@@ -45,6 +46,7 @@
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
import java.util.Map;
import java.util.HashMap;
@@ -401,7 +403,7 @@
* session key will be different,can be used to
differentiate between
* parallel sessions
*/
- ProcessMessage1(payload,pn,replyTo,0);
+ ProcessMessage1(payload,pn,replyTo);
}
else if(packetType==1){
@@ -410,7 +412,7 @@
* nonce and an authenticator calculated from a
transient hash key private
* to the responder.
*/
- ProcessMessage2(payload,pn,replyTo,1);
+ ProcessMessage2(payload,pn,replyTo);
}
else if(packetType==2){
/*
@@ -418,7 +420,7 @@
* cached by the Responder.Receiving a
duplicate message simply causes
* the responder to Re-transmit the
corresponding message4
*/
- ProcessMessage3(payload, pn, replyTo, 2);
+ ProcessMessage3(payload, pn, replyTo);
}
else if(packetType==3){
/*
@@ -426,7 +428,7 @@
* using the same keys as in the previous
message.
* The signature is non-message recovering
*/
- ProcessMessage4(payload,pn,replyTo,3);
+ ProcessMessage4(payload,pn,replyTo);
}
}
else {
@@ -434,35 +436,8 @@
return;
}
}
- /*
- * Initiator DH Exponential
- */
- private synchronized byte[] Gi(PeerNode pn){
- DiffieHellmanContext
dh=(DiffieHellmanContext)pn.getKeyAgreementSchemeContext();
- if(dh==null)
- {
- if(shouldLogErrorInHandshake())
- Logger.error(this,"Failed getting
exponentials");
- }
- return dh.getOurExponential().toByteArray();
- }
-
/*
- * Responder DH Exponential
- */
- private synchronized byte[] Gr(PeerNode pn){
- DiffieHellmanContext
dh=(DiffieHellmanContext)pn.getKeyAgreementSchemeContext();
- if(dh==null)
- {
- if(shouldLogErrorInHandshake())
- Logger.error(this,"Failed getting
exponentials");
-
- }
- return dh.getHisExponential().toByteArray();
- }
-
- /*
* Shared Secret key
* Alice generates random number x and computes exponential g^x
* Bob generates random number y and computes exponential g^y
@@ -478,21 +453,8 @@
}
return dh.getKey();
}
+
/*
- * The Initiator and Responder nonce are random bytes used to provide
key independence
- */
- private synchronized byte[] iNonce(){
-
- byte[] n=new byte[16];
- node.random.nextBytes(n);
- return n;
- }
- private synchronized byte[] rNonce(){
- byte[] n=new byte[16];
- node.random.nextBytes(n);
- return n;
- }
- /*
* Initiator Method:Message1
* Process Message1
* Send the Initiator nonce and DiffieHellman Exponential
@@ -505,27 +467,29 @@
* g^i
* IDr'
*/
- private void ProcessMessage1(byte[] payload,PeerNode pn,Peer
replyTo,int phase)
+ private void ProcessMessage1(byte[] payload,PeerNode pn,Peer replyTo)
{
long t1=System.currentTimeMillis();
if(logMINOR) Logger.minor(this, "Got a JFK(1) message,
processing it");
// FIXME: follow the spec and send IDr' ?
- 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()));
+ if(payload.length < NONCE_SIZE +
DiffieHellman.modulusLengthInBytes() + 3) {
+ Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(1), should be "+(NONCE_SIZE +
DiffieHellman.modulusLengthInBytes()));
return;
}
+ int offset=3;
// get Ni
byte[] nonceInitiator = new byte[NONCE_SIZE];
- System.arraycopy(payload, 0, nonceInitiator, 0, NONCE_SIZE);
+ System.arraycopy(payload, offset, nonceInitiator, 0,
NONCE_SIZE);
+ offset += NONCE_SIZE;
// get g^i
byte[] hisExponential = new
byte[DiffieHellman.modulusLengthInBytes()];
- System.arraycopy(payload, NONCE_SIZE, hisExponential, 0,
DiffieHellman.modulusLengthInBytes());
-
- NativeBigInteger _hisExponential = new NativeBigInteger(1,
hisExponential);
- if(_hisExponential.compareTo(NativeBigInteger.ONE) > 0)
- sendMessage2(nonceInitiator, hisExponential, pn,
replyTo);
- else
+ System.arraycopy(payload, offset, hisExponential, 0,
DiffieHellman.modulusLengthInBytes());
+ NativeBigInteger _hisExponential = new
NativeBigInteger(hisExponential);
+ if(logMINOR) Logger.minor(this, "his exponential from message1
length="+DiffieHellman.modulusLengthInBytes() +" value=" +
_hisExponential.toHexString());
+ if(_hisExponential.compareTo(NativeBigInteger.ONE) > 0) {
+ sendMessage2(nonceInitiator, pn, replyTo);
+ }else
Logger.error(this, "We can't accept the exponential
"+pn+" sent us; it's smaller than 1!!");
long t2=System.currentTimeMillis();
@@ -534,19 +498,46 @@
}
/*
- * format:
- * Ni,Nr,g^r,GrpInfo(r),IDr
- * Signature[g^r,grpInfo(r)]
- * Hashed JFKAuthenticator
- * FIXME: IDr' not sent during JFK(1) ?
- */
- private void sendMessage2(byte[] nonceInitator, byte[] hisExponential,
PeerNode pn, Peer replyTo) {
+ * format:
+ * Ni,g^i,IDr'
+ * FIXME: IDr' not sent?
+ */
+ private void sendMessage1(PeerNode pn, Peer replyTo) {
+ if(logMINOR) Logger.minor(this, "Sending a JFK(1) message to
"+pn);
+ DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
+ int offset = 0;
+ byte[] idR = new byte[0];
+ byte[] myExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] myNonce = new byte[NONCE_SIZE];
+ node.random.nextBytes(myNonce);
+
+ byte[] message1 = new
byte[NONCE_SIZE+DiffieHellman.modulusLengthInBytes()+idR.length];
+
+ System.arraycopy(myNonce, 0, message1, offset, NONCE_SIZE);
+ 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();
+ System.arraycopy(idR, 0, message1, offset, idR.length);
+ offset += idR.length;
+
+ sendAuthPacket(1,2,0,message1,pn,replyTo);
+ }
+
+ /*
+ * format:
+ * Ni,Nr,g^r,GrpInfo(r),IDr
+ * Signature[g^r,grpInfo(r)]
+ * Hashed JFKAuthenticator
+ * FIXME: IDr' not sent during JFK(1) ?
+ */
+ private void sendMessage2(byte[] nonceInitator, PeerNode pn, Peer
replyTo) {
if(logMINOR) Logger.minor(this, "Sending a JFK(2) message to
"+pn);
DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext();
byte[] idR = new byte[0];
byte[] myDHGroup = dhContext.group.asBytes();
byte[] myNonce = new byte[NONCE_SIZE];
- byte[] myExponential = dhContext.myExponential.toByteArray();
+ byte[] myExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
node.random.nextBytes(myNonce);
byte[] signature;
try {
@@ -566,8 +557,8 @@
offset += NONCE_SIZE;
System.arraycopy(myNonce, 0, message2, offset, NONCE_SIZE);
offset += NONCE_SIZE;
- System.arraycopy(myExponential, 0, message2, offset,
myExponential.length);
- offset += myExponential.length;
+ System.arraycopy(myExponential, 0, message2, offset,
DiffieHellman.modulusLengthInBytes());
+ offset += DiffieHellman.modulusLengthInBytes();
// TODO: are groups modulo something ?
message2[offset++] =
Integer.valueOf(myDHGroup.length).byteValue();
System.arraycopy(myDHGroup, 0, message2, offset,
myDHGroup.length);
@@ -580,7 +571,7 @@
System.arraycopy(authenticator, 0, message2, offset,
HASH_LENGTH);
- sendAuthPacket(1,2,2,message2,pn,replyTo);
+ sendAuthPacket(1,2,1,message2,pn,replyTo);
}
/*
@@ -614,7 +605,9 @@
* Hash the authenticator using SHA256
*/
private byte[] computeHashedJFKAuthenticator(byte[] gR, byte[] nR,
byte[] nI, byte[] address) {
- return SHA256.digest(computeJFKAuthenticator(gR, nR, nI,
address));
+ byte[] result = SHA256.digest(computeJFKAuthenticator(gR, nR,
nI, address));
+ assert(result.length == HASH_LENGTH);
+ return result;
}
/*
@@ -634,18 +627,17 @@
* @param The peerNode we are talking to
*/
- private void ProcessMessage2(byte[] payload,PeerNode pn,Peer
replyTo,int phase)
+ private void ProcessMessage2(byte[] payload,PeerNode pn,Peer replyTo)
{
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()));
+ if(payload.length < NONCE_SIZE +
DiffieHellman.modulusLengthInBytes() + 3) {
+ Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(2), should be "+(NONCE_SIZE +
DiffieHellman.modulusLengthInBytes()));
return;
}
- int inputOffset=0;
+ int inputOffset=3;
byte[] nonceInitiator = new byte[NONCE_SIZE];
System.arraycopy(payload, inputOffset, nonceInitiator, 0,
NONCE_SIZE);
inputOffset += NONCE_SIZE;
@@ -656,7 +648,7 @@
byte[] hisExponential = new
byte[DiffieHellman.modulusLengthInBytes()];
System.arraycopy(payload, inputOffset, hisExponential, 0,
DiffieHellman.modulusLengthInBytes());
inputOffset += DiffieHellman.modulusLengthInBytes();
- NativeBigInteger _hisExponential = new NativeBigInteger(1,
hisExponential);
+ NativeBigInteger _hisExponential = new
NativeBigInteger(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;
@@ -682,8 +674,13 @@
byte[] locallyExpectedExponentials = new
byte[hisExponential.length+hisGroupLength];
System.arraycopy(hisExponential, 0,
locallyExpectedExponentials, 0, hisExponential.length);
System.arraycopy(hisGroup, 0, locallyExpectedExponentials,
hisExponential.length, hisGroupLength);
- DSASignature signatureToCheck = new DSASignature(new
String(remoteSignedExponentials));
- if(!DSA.verify(pn.peerPubKey, signatureToCheck, new
NativeBigInteger(1,locallyExpectedExponentials), false)) {
+ String sigToCheckAsString = null;
+ try {
+ sigToCheckAsString = new
String(remoteSignedExponentials, "UTF-8");
+ } catch (UnsupportedEncodingException e) {}
+ if(logMINOR) Logger.minor(this, "His signedExponentials :"+
HexUtil.bytesToHex(hisExponential));
+ DSASignature signatureToCheck = new
DSASignature(sigToCheckAsString);
+ if(!DSA.verify(pn.peerPubKey, signatureToCheck, new
NativeBigInteger(locallyExpectedExponentials), false)) {
Logger.error(this, "The signature verification has
failed!!");
return;
}
@@ -712,7 +709,7 @@
* @param The peerNode we are talking to
* @return byte Message3
*/
- private void ProcessMessage3(byte[] payload, PeerNode pn,Peer
replyTo,int phase)
+ private void ProcessMessage3(byte[] payload, PeerNode pn,Peer replyTo)
{
long t1 = System.currentTimeMillis();
if(logMINOR) Logger.minor(this, "Got a JFK(3) message,
processing it");
@@ -780,7 +777,7 @@
* @param The peerNode we are talking to
*/
- private void ProcessMessage4(byte[] payload,PeerNode pn,Peer
replyTo,int phase)
+ private void ProcessMessage4(byte[] payload,PeerNode pn,Peer replyTo)
{
if(logMINOR) Logger.minor(this, "Got a JFK(4) message,
processing it");
long t1=System.currentTimeMillis();
@@ -934,7 +931,7 @@
// We don't want to keep the lock while sending
try
{
-
sendAuthPacket(1,2,3,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
+
sendAuthPacket(1,2,2,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
}
catch(IOException e){
Logger.error(this,"Error getting
bytes");
@@ -1062,20 +1059,7 @@
private void sendFirstHalfDHPacket(int phase, int negType,
NativeBigInteger integer, PeerNode pn, Peer replyTo) {
long time1 = System.currentTimeMillis();
if(logMINOR) Logger.minor(this, "Sending ("+phase+")
"+integer.toHexString()+" to "+pn.getPeer());
- byte[] data = integer.toByteArray();
- int targetLength = DiffieHellman.modulusLengthInBytes();
- if(data.length != targetLength) {
- byte[] newData = new byte[targetLength];
- if((data.length == targetLength+1) && (data[0] == 0)) {
- // Sign bit
- System.arraycopy(data, 1, newData, 0,
targetLength);
- } else if(data.length < targetLength) {
- System.arraycopy(data, 0, newData,
targetLength-data.length, data.length);
- } else {
- throw new IllegalStateException("Too long!");
- }
- data = newData;
- }
+ byte[] data = stripBigIntegerToNetworkFormat(integer);
if(logMINOR) Logger.minor(this, "Processed:
"+HexUtil.bytesToHex(data));
long time2 = System.currentTimeMillis();
if((time2 - time1) > 200) {
@@ -2151,7 +2135,7 @@
return;
}
if(logMINOR) Logger.minor(this, "Possibly sending handshake to
"+pn+" negotiation type "+negType);
- DiffieHellmanContext ctx;
+ DiffieHellmanContext ctx = null;
Peer[] handshakeIPs;
if(!pn.shouldSendHandshake()) {
if(logMINOR) Logger.minor(this, "Not sending handshake
to "+pn.getPeer()+" because pn.shouldSendHandshake() returned false");
@@ -2168,7 +2152,7 @@
if((thirdTime - secondTime) > 1000)
Logger.error(this, "couldNotSendHandshake()
(after getHandshakeIPs()) took more than a second to execute ("+(thirdTime -
secondTime)+") working on "+pn.userToString());
return;
- } else {
+ } else if(negType < 2){
long DHTime1 = System.currentTimeMillis();
ctx = DiffieHellman.generateContext();
long DHTime2 = System.currentTimeMillis();
@@ -2196,7 +2180,10 @@
if(logMINOR) Logger.minor(this, "Not sending
handshake to "+handshakeIPs[i]+" for "+pn.getPeer()+" because it's not a real
Internet address and metadata.allowLocalAddresses is not true");
continue;
}
- sendFirstHalfDHPacket(0, negType,
ctx.getOurExponential(), pn, peer);
+ if(negType == 1)
+ sendFirstHalfDHPacket(0, negType,
ctx.getOurExponential(), pn, peer);
+ else
+ sendMessage1(pn, peer);
pn.sentHandshake();
sentCount += 1;
}
@@ -2274,4 +2261,23 @@
authenticatorCache.clear();
}
}
+
+ private byte[] stripBigIntegerToNetworkFormat(BigInteger exponential) {
+ byte[] data = exponential.toByteArray();
+ int targetLength = DiffieHellman.modulusLengthInBytes();
+
+ if(data.length != targetLength) {
+ byte[] newData = new byte[targetLength];
+ if((data.length == targetLength+1) && (data[0] == 0)) {
+ // Sign bit
+ System.arraycopy(data, 1, newData, 0,
targetLength);
+ } else if(data.length < targetLength) {
+ System.arraycopy(data, 0, newData,
targetLength-data.length, data.length);
+ } else {
+ throw new IllegalStateException("Too long!");
+ }
+ data = newData;
+ }
+ return data;
+ }
}
\ No newline at end of file