Author: nextgens Date: 2009-01-31 15:49:33 +0000 (Sat, 31 Jan 2009) New Revision: 25445
Modified: trunk/freenet/src/freenet/crypt/HMAC.java trunk/freenet/src/freenet/node/FNPPacketMangler.java trunk/freenet/src/freenet/node/FailureTable.java trunk/freenet/src/freenet/node/NodeDispatcher.java trunk/freenet/src/freenet/node/PeerNode.java Log: revert r25406: will do a branch if I decide to start on this Modified: trunk/freenet/src/freenet/crypt/HMAC.java =================================================================== --- trunk/freenet/src/freenet/crypt/HMAC.java 2009-01-31 10:20:50 UTC (rev 25444) +++ trunk/freenet/src/freenet/crypt/HMAC.java 2009-01-31 15:49:33 UTC (rev 25445) @@ -3,42 +3,150 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.crypt; -import freenet.support.Logger; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.NoSuchAlgorithmException; +import java.io.UnsupportedEncodingException; import java.util.Arrays; -import javax.crypto.Mac; -import javax.crypto.SecretKey; +import freenet.support.HexUtil; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + /** * Implements the HMAC Keyed Message Authentication function, as described * in the draft FIPS standard. - * - * Use a KeyGenerator to generate a key! */ public class HMAC { - public enum ALGORITHM { + protected static final int B = 64; + protected static byte[] ipad = new byte[B]; + protected static byte[] opad = new byte[B]; - HmacSHA256, Hmac1, HmacMD5; - } + static { + for(int i = 0; i < B; i++) { + ipad[i] = (byte) 0x36; + opad[i] = (byte) 0x5c; + } + } + protected MessageDigest d; - public static byte[] mac(ALGORITHM algo, SecretKey key, byte[] input) throws InvalidKeyException { - try { - Mac mac = Mac.getInstance(algo.name()); - mac.init(key); + public HMAC(MessageDigest md) { + this.d = md; + } - return mac.doFinal(); - } catch (NoSuchAlgorithmException ex) { - Logger.error(HMAC.class, "Check your JVM settings especially the JCE!" + ex.getMessage(), ex); - System.err.println("Check your JVM settings especially the JCE!" + ex); - ex.printStackTrace(); - throw new Error("Check your JVM settings especially the JCE!", ex); - } - } + public boolean verify(byte[] K, byte[] text, byte[] mac) { + byte[] mac2 = mac(K, text, mac.length); + return Arrays.equals(mac, mac2); + } - public static boolean verify(ALGORITHM algo, SecretKey key, byte[] input, byte[] mac) throws InvalidKeyException { - return Arrays.equals(mac, mac(algo, key, input)); - } -} \ No newline at end of file + public byte[] mac(byte[] K, byte[] text, int macbytes) { + byte[] K0 = null; + + if(K.length == B) // Step 1 + K0 = K; + else { + // Step 2 + if(K.length > B) + K0 = K = Util.hashBytes(d, K); + + if(K.length < B) { // Step 3 + K0 = new byte[B]; + System.arraycopy(K, 0, K0, 0, K.length); + } + } + + // Step 4 + byte[] IS1 = Util.xor(K0, ipad); + + // Step 5/6 + d.update(IS1); + d.update(text); + IS1 = d.digest(); + + // Step 7 + byte[] IS2 = Util.xor(K0, opad); + + // Step 8/9 + d.update(IS2); + d.update(IS1); + IS1 = d.digest(); + + // Step 10 + if(macbytes == IS1.length) + return IS1; + else { + byte[] rv = new byte[macbytes]; + System.arraycopy(IS1, 0, rv, 0, Math.min(rv.length, IS1.length)); + return rv; + } + } + + public static void main(String[] args) throws UnsupportedEncodingException { + HMAC s = null; + try { + s = new HMAC(MessageDigest.getInstance("SHA1")); + } catch(NoSuchAlgorithmException e) { + } + byte[] key = new byte[20]; + System.err.println("20x0b, 'Hi There':"); + byte[] text; + text = "Hi There".getBytes("UTF-8"); + + for(int i = 0; i < key.length; i++) + key[i] = (byte) 0x0b; + + byte[] mv = s.mac(key, text, 20); + System.out.println(HexUtil.bytesToHex(mv, 0, mv.length)); + + System.err.println("20xaa, 50xdd:"); + for(int i = 0; i < key.length; i++) + key[i] = (byte) 0xaa; + text = new byte[50]; + for(int i = 0; i < text.length; i++) + text[i] = (byte) 0xdd; + mv = s.mac(key, text, 20); + System.out.println(HexUtil.bytesToHex(mv, 0, mv.length)); + + key = new byte[25]; + System.err.println("25x[i+1], 50xcd:"); + for(int i = 0; i < key.length; i++) + key[i] = (byte) (i + 1); + for(int i = 0; i < text.length; i++) + text[i] = (byte) 0xcd; + mv = s.mac(key, text, 20); + System.out.println(HexUtil.bytesToHex(mv, 0, mv.length)); + + key = new byte[20]; + System.err.println("20x0c, 'Test With Truncation':"); + for(int i = 0; i < key.length; i++) + key[i] = (byte) 0x0c; + text = "Test With Truncation".getBytes("UTF-8"); + mv = s.mac(key, text, 20); + System.out.println(HexUtil.bytesToHex(mv, 0, mv.length)); + mv = s.mac(key, text, 12); + System.out.println(HexUtil.bytesToHex(mv, 0, mv.length)); + + } + + public static byte[] macWithSHA256(byte[] K, byte[] text, int macbytes) { + MessageDigest sha256 = null; + try { + sha256 = SHA256.getMessageDigest(); + HMAC hash = new HMAC(sha256); + return hash.mac(K, text, macbytes); + } finally { + if(sha256 != null) + SHA256.returnMessageDigest(sha256); + } + } + + public static boolean verifyWithSHA256(byte[] K, byte[] text, byte[] mac) { + MessageDigest sha256 = null; + try { + sha256 = SHA256.getMessageDigest(); + HMAC hash = new HMAC(sha256); + return hash.verify(K, text, mac); + } finally { + if(sha256 != null) + SHA256.returnMessageDigest(sha256); + } + } +} Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java =================================================================== --- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2009-01-31 10:20:50 UTC (rev 25444) +++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2009-01-31 15:49:33 UTC (rev 25445) @@ -52,9 +52,6 @@ import freenet.support.TimeUtil; import freenet.support.WouldBlockException; import freenet.support.io.NativeThread; -import java.security.InvalidKeyException; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; /** * @author amphibian @@ -132,7 +129,7 @@ /** The size of the key used to authenticate the hmac */ private static final int TRANSIENT_KEY_SIZE = HASH_LENGTH; /** The key used to authenticate the hmac */ - private SecretKey transientKey; + private final byte[] transientKey = new byte[TRANSIENT_KEY_SIZE]; public static final int TRANSIENT_KEY_REKEYING_MIN_INTERVAL = 30*60*1000; /** The rekeying interval for the session key (keytrackers) */ public static final int SESSION_KEY_REKEYING_INTERVAL = 60*60*1000; @@ -234,7 +231,7 @@ opn = null; } PeerNode pn; - try { + if(opn != null) { if(logMINOR) Logger.minor(this, "Trying exact match"); if(length > HEADERS_LENGTH_MINIMUM) { @@ -252,7 +249,7 @@ if(tryProcessAuth(buf, offset, length, opn, peer, false, now)) return; // Might be a reply to an anon auth packet if(tryProcessAuthAnonReply(buf, offset, length, opn, peer, now)) return; - } + } } PeerNode[] peers = crypto.getPeerNodes(); // Existing connection, changed IP address? @@ -309,6 +306,7 @@ } } } + OpennetManager opennet = node.getOpennet(); if(opennet != null) { // Try old opennet connections. @@ -324,10 +322,6 @@ if(node.wantAnonAuth()) { if(tryProcessAuthAnon(buf, offset, length, peer)) return; } - } catch (InvalidKeyException e) { - Logger.error(this, "Huh! " + e.getMessage(), e); - return; - } if(LOG_UNMATCHABLE_ERROR) System.err.println("Unmatchable packet from "+peer+" on "+node.getDarknetPortNumber()); Logger.normal(this,"Unmatchable packet from "+peer); @@ -343,7 +337,7 @@ * @param now The time at which the packet was received * @return True if we handled a negotiation packet, false otherwise. */ - private boolean tryProcessAuth(byte[] buf, int offset, int length, PeerNode pn, Peer peer, boolean oldOpennetPeer, long now) throws InvalidKeyException { + private boolean tryProcessAuth(byte[] buf, int offset, int length, PeerNode pn, Peer peer, boolean oldOpennetPeer, long now) { BlockCipher authKey = pn.incomingSetupCipher; if(logMINOR) Logger.minor(this, "Decrypt key: "+HexUtil.bytesToHex(pn.incomingSetupKey)+" for "+peer+" : "+pn+" in tryProcessAuth"); // Does the packet match IV E( H(data) data ) ? @@ -412,7 +406,7 @@ * @param now The time at which the packet was received * @return True if we handled a negotiation packet, false otherwise. */ - private boolean tryProcessAuthAnon(byte[] buf, int offset, int length, Peer peer) throws InvalidKeyException { + private boolean tryProcessAuthAnon(byte[] buf, int offset, int length, Peer peer) { BlockCipher authKey = crypto.getAnonSetupCipher(); // Does the packet match IV E( H(data) data ) ? PCFBMode pcfb = PCFBMode.create(authKey); @@ -477,7 +471,7 @@ * @param now The time at which the packet was received * @return True if we handled a negotiation packet, false otherwise. */ - private boolean tryProcessAuthAnonReply(byte[] buf, int offset, int length, PeerNode pn, Peer peer, long now) throws InvalidKeyException { + private boolean tryProcessAuthAnonReply(byte[] buf, int offset, int length, PeerNode pn, Peer peer, long now) { BlockCipher authKey = pn.anonymousInitiatorSetupCipher; // Does the packet match IV E( H(data) data ) ? PCFBMode pcfb = PCFBMode.create(authKey); @@ -539,7 +533,7 @@ * @param payload The decrypted payload of the packet. * @param replyTo The address the packet came in from. */ - private void processDecryptedAuthAnon(byte[] payload, Peer replyTo) throws InvalidKeyException { + private void processDecryptedAuthAnon(byte[] payload, Peer replyTo) { if(logMINOR) Logger.minor(this, "Processing decrypted auth packet from "+replyTo+" length "+payload.length); /** Protocol version. Should be 1. */ @@ -589,7 +583,7 @@ } } - private void processDecryptedAuthAnonReply(byte[] payload, Peer replyTo, PeerNode pn) throws InvalidKeyException { + private void processDecryptedAuthAnonReply(byte[] payload, Peer replyTo, PeerNode pn) { if(logMINOR) Logger.minor(this, "Processing decrypted auth packet from "+replyTo+" for "+pn+" length "+payload.length); /** Protocol version. Should be 1. */ @@ -640,7 +634,7 @@ * Process a decrypted, authenticated auth packet. * @param payload The packet payload, after it has been decrypted. */ - private void processDecryptedAuth(byte[] payload, PeerNode pn, Peer replyTo, boolean oldOpennetPeer) throws InvalidKeyException { + private void processDecryptedAuth(byte[] payload, PeerNode pn, Peer replyTo, boolean oldOpennetPeer) { if(logMINOR) Logger.minor(this, "Processing decrypted auth packet from "+replyTo+" for "+pn); if(pn.isDisabled()) { if(logMINOR) Logger.minor(this, "Won't connect to a disabled peer ("+pn+ ')'); @@ -765,7 +759,7 @@ * ACM Transactions on Information and System Security, Vol 7 No 2, May 2004, Pages 1-30. * */ - private void processJFKMessage1(byte[] payload,int offset,PeerNode pn,Peer replyTo, boolean unknownInitiator, int setupType, int negType) throws InvalidKeyException + private void processJFKMessage1(byte[] payload,int offset,PeerNode pn,Peer replyTo, boolean unknownInitiator, int setupType, int negType) { long t1=System.currentTimeMillis(); if(logMINOR) Logger.minor(this, "Got a JFK(1) message, processing it - "+pn); @@ -860,7 +854,7 @@ * @param pn The node to encrypt the message for. CAN BE NULL if anonymous-initiator. * @param replyTo The peer to send the packet to. */ - private void sendJFKMessage2(byte[] nonceInitator, byte[] hisExponential, PeerNode pn, Peer replyTo, boolean unknownInitiator, int setupType, int negType) throws InvalidKeyException { + private void sendJFKMessage2(byte[] nonceInitator, byte[] hisExponential, PeerNode pn, Peer replyTo, boolean unknownInitiator, int setupType, int negType) { if(logMINOR) Logger.minor(this, "Sending a JFK(2) message to "+pn); DiffieHellmanLightContext ctx = getLightDiffieHellmanContext(); // g^r @@ -870,7 +864,7 @@ node.random.nextBytes(myNonce); byte[] r = ctx.signature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH); byte[] s = ctx.signature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH); - byte[] authenticator = HMAC.mac(HMAC.ALGORITHM.HmacSHA256, getTransientKey(), assembleJFKAuthenticator(myExponential, hisExponential, myNonce, nonceInitator, replyTo.getAddress().getAddress())); + byte[] authenticator = HMAC.macWithSHA256(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)); byte[] message2 = new byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()+ @@ -932,7 +926,7 @@ * @param pn The peerNode we are talking to. Cannot be null as we are the initiator. */ - private void processJFKMessage2(byte[] payload,int inputOffset,PeerNode pn,Peer replyTo, boolean unknownInitiator, int setupType, int negType) throws InvalidKeyException + private void processJFKMessage2(byte[] payload,int inputOffset,PeerNode pn,Peer replyTo, boolean unknownInitiator, int setupType, int negType) { long t1=System.currentTimeMillis(); if(logMINOR) Logger.minor(this, "Got a JFK(2) message, processing it - "+pn.getPeer()); @@ -1044,7 +1038,7 @@ * responder. * @return byte Message3 */ - private void processJFKMessage3(byte[] payload, int inputOffset, PeerNode pn,Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator, int setupType, int negType) throws InvalidKeyException + private void processJFKMessage3(byte[] payload, int inputOffset, PeerNode pn,Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator, int setupType, int negType) { final long t1 = System.currentTimeMillis(); if(logMINOR) Logger.minor(this, "Got a JFK(3) message, processing it - "+pn); @@ -1091,7 +1085,7 @@ // We *WANT* to check the hmac before we do the lookup on the hashmap // @see https://bugs.freenetproject.org/view.php?id=1604 - if(!HMAC.verify(HMAC.ALGORITHM.HmacSHA256, getTransientKey(), assembleJFKAuthenticator(responderExponential, initiatorExponential, nonceResponder, nonceInitiator, replyTo.getAddress().getAddress()) , authenticator)) { + if(!HMAC.verifyWithSHA256(getTransientKey(), assembleJFKAuthenticator(responderExponential, initiatorExponential, nonceResponder, nonceInitiator, replyTo.getAddress().getAddress()) , authenticator)) { if(shouldLogErrorInHandshake(t1)) Logger.normal(this, "The HMAC doesn't match; let's discard the packet (either we rekeyed or we are victim of forgery) - JFK3 - "+pn); return; @@ -1129,10 +1123,10 @@ return; } BigInteger computedExponential = ctx.getHMACKey(_hisExponential, Global.DHgroupA); - SecretKey Ks = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "0"); - SecretKey Ke = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "1"); - SecretKey Ka = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "2"); - c.initialize(Ke.getEncoded()); + byte[] Ks = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "0"); + byte[] Ke = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "1"); + byte[] Ka = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "2"); + c.initialize(Ke); final PCFBMode pk = PCFBMode.create(c); int ivLength = pk.lengthIV(); int decypheredPayloadOffset = 0; @@ -1141,7 +1135,7 @@ System.arraycopy(JFK_PREFIX_INITIATOR, 0, decypheredPayload, decypheredPayloadOffset, JFK_PREFIX_INITIATOR.length); decypheredPayloadOffset += JFK_PREFIX_INITIATOR.length; System.arraycopy(payload, inputOffset, decypheredPayload, decypheredPayloadOffset, decypheredPayload.length-decypheredPayloadOffset); - if(!HMAC.verify(HMAC.ALGORITHM.HmacSHA256 ,Ka, decypheredPayload, hmac)) { + if(!HMAC.verifyWithSHA256(Ka, decypheredPayload, hmac)) { Logger.error(this, "The inner-HMAC doesn't match; let's discard the packet JFK(3) - "+pn); return; } @@ -1203,7 +1197,7 @@ BlockCipher cs = null; try { cs = new Rijndael(256, 256); } catch (UnsupportedCipherException e) {} - cs.initialize(Ks.getEncoded()); + cs.initialize(Ks); // Promote if necessary boolean dontWant = false; @@ -1298,7 +1292,7 @@ * @param pn The PeerNode we are talking to. Cannot be null as we are the initiator. * @param replyTo The Peer we are replying to. */ - private boolean processJFKMessage4(byte[] payload, int inputOffset, PeerNode pn, Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator, int setupType, int negType) throws InvalidKeyException + private boolean processJFKMessage4(byte[] payload, int inputOffset, PeerNode pn, Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator, int setupType, int negType) { final long t1 = System.currentTimeMillis(); if(logMINOR) Logger.minor(this, "Got a JFK(4) message, processing it - "+pn.getPeer()); @@ -1334,7 +1328,7 @@ System.arraycopy(payload, inputOffset, hmac, 0, HASH_LENGTH); inputOffset += HASH_LENGTH; - c.initialize(pn.jfkKe.getEncoded()); + c.initialize(pn.jfkKe); final PCFBMode pk = PCFBMode.create(c); int ivLength = pk.lengthIV(); int decypheredPayloadOffset = 0; @@ -1343,7 +1337,7 @@ System.arraycopy(JFK_PREFIX_RESPONDER, 0, decypheredPayload, decypheredPayloadOffset, JFK_PREFIX_RESPONDER.length); decypheredPayloadOffset += JFK_PREFIX_RESPONDER.length; System.arraycopy(payload, inputOffset, decypheredPayload, decypheredPayloadOffset, payload.length-inputOffset); - if(!HMAC.verify(HMAC.ALGORITHM.HmacSHA256, pn.jfkKa, decypheredPayload, hmac)) { + if(!HMAC.verifyWithSHA256(pn.jfkKa, decypheredPayload, hmac)) { Logger.normal(this, "The digest-HMAC doesn't match; let's discard the packet - "+pn.getPeer()); return false; } @@ -1442,7 +1436,7 @@ } // We change the key - c.initialize(pn.jfkKs.getEncoded()); + c.initialize(pn.jfkKs); if(pn.completedHandshake(bootID, hisRef, 0, hisRef.length, c, pn.jfkKs, replyTo, false, negType, trackerID, true, reusedTracker) >= 0) { if(dontWant) node.peers.disconnect(pn, true, true, true); @@ -1484,7 +1478,7 @@ * @param replyTo The Peer to send the packet to. */ - private void sendJFKMessage3(int version,final int negType,int phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] hisExponential, byte[] authenticator, final PeerNode pn, final Peer replyTo, final boolean unknownInitiator, final int setupType) throws InvalidKeyException + private void sendJFKMessage3(int version,final int negType,int phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] hisExponential, byte[] authenticator, final PeerNode pn, final Peer replyTo, final boolean unknownInitiator, final int setupType) { if(logMINOR) Logger.minor(this, "Sending a JFK(3) message to "+pn.getPeer()); long t1=System.currentTimeMillis(); @@ -1549,7 +1543,7 @@ pn.jfkKs = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "0"); pn.jfkKe = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "1"); pn.jfkKa = computeJFKSharedKey(computedExponential, nonceInitiator, nonceResponder, "2"); - c.initialize(pn.jfkKe.getEncoded()); + c.initialize(pn.jfkKe); PCFBMode pcfb = PCFBMode.create(c); int ivLength = pcfb.lengthIV(); byte[] iv = new byte[ivLength]; @@ -1572,7 +1566,7 @@ pcfb.blockEncipher(cleartext, cleartextToEncypherOffset, cleartext.length-cleartextToEncypherOffset); // We compute the HMAC of (prefix + cyphertext) Includes the IV! - byte[] hmac = HMAC.mac(HMAC.ALGORITHM.HmacSHA256, pn.jfkKa, cleartext); + byte[] hmac = HMAC.macWithSHA256(pn.jfkKa, cleartext, HASH_LENGTH); // copy stuffs back to the message System.arraycopy(hmac, 0, message3, offset, HASH_LENGTH); @@ -1617,7 +1611,7 @@ * @param pn The PeerNode to encrypt the auth packet to. Cannot be null, because even in anonymous initiator, * we will have created one before calling this method. */ - private void sendJFKMessage4(int version,int negType,int phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] initiatorExponential,byte[] responderExponential, BlockCipher c, SecretKey Ke, SecretKey Ka, byte[] authenticator, byte[] hisRef, PeerNode pn, Peer replyTo, boolean unknownInitiator, int setupType, long newTrackerID, boolean sameAsOldTrackerID) throws InvalidKeyException + private void sendJFKMessage4(int version,int negType,int phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] initiatorExponential,byte[] responderExponential, BlockCipher c, byte[] Ke, byte[] Ka, byte[] authenticator, byte[] hisRef, PeerNode pn, Peer replyTo, boolean unknownInitiator, int setupType, long newTrackerID, boolean sameAsOldTrackerID) { if(logMINOR) Logger.minor(this, "Sending a JFK(4) message to "+pn.getPeer()); @@ -1673,7 +1667,7 @@ pk.blockEncipher(cyphertext, cleartextToEncypherOffset, cyphertext.length - cleartextToEncypherOffset); // We compute the HMAC of (prefix + iv + signature) - byte[] hmac = HMAC.mac(HMAC.ALGORITHM.HmacSHA256, Ka, cyphertext); + byte[] hmac = HMAC.macWithSHA256(Ka, cyphertext, HASH_LENGTH); // Message4 = hmac + IV + encryptedSignature byte[] message4 = new byte[HASH_LENGTH + ivLength + (cyphertext.length - cleartextToEncypherOffset)]; @@ -3038,13 +3032,13 @@ return result; } - private SecretKey getTransientKey() { + private byte[] getTransientKey() { synchronized (authenticatorCache) { return transientKey; } } - private SecretKey computeJFKSharedKey(BigInteger exponential, byte[] nI, byte[] nR, String what) throws InvalidKeyException { + private byte[] computeJFKSharedKey(BigInteger exponential, byte[] nI, byte[] nR, String what) { assert("0".equals(what) || "1".equals(what) || "2".equals(what)); byte[] number = null; try { @@ -3061,7 +3055,7 @@ offset += NONCE_SIZE; System.arraycopy(number, 0, toHash, offset, number.length); - return new SecretKeySpec(HMAC.mac(HMAC.ALGORITHM.HmacSHA256, new SecretKeySpec(exponential.toByteArray(), "RAW"), toHash), "RAW"); + return HMAC.macWithSHA256(exponential.toByteArray(), toHash, HASH_LENGTH); } private long timeLastReset = -1; @@ -3086,10 +3080,7 @@ } timeLastReset = now; - // FIXME: Use the KeyGenerator! - byte[] trKey = new byte[TRANSIENT_KEY_SIZE]; - node.random.nextBytes(trKey); - transientKey = new SecretKeySpec(trKey, "RAW"); + node.random.nextBytes(transientKey); // reset the authenticator cache authenticatorCache.clear(); Modified: trunk/freenet/src/freenet/node/FailureTable.java =================================================================== --- trunk/freenet/src/freenet/node/FailureTable.java 2009-01-31 10:20:50 UTC (rev 25444) +++ trunk/freenet/src/freenet/node/FailureTable.java 2009-01-31 15:49:33 UTC (rev 25445) @@ -27,8 +27,6 @@ import freenet.support.io.NativeThread; // FIXME it is ESSENTIAL that we delete the ULPR data on requestors etc once we have found the key. -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; // Otherwise it will be much too easy to trace a request if an attacker busts the node afterwards. // We can use an HMAC or something to authenticate offers. @@ -61,7 +59,7 @@ /** Offers expire after 10 minutes */ static final int OFFER_EXPIRY_TIME = 10*60*1000; /** HMAC key for the offer authenticator */ - final SecretKey offerAuthenticatorKey; + final byte[] offerAuthenticatorKey; /** Clean up old data every 30 minutes to save memory and improve privacy */ static final int CLEANUP_PERIOD = 30*60*1000; @@ -72,10 +70,8 @@ entriesByKey = new LRUHashtable<Key,FailureTableEntry>(); blockOfferListByKey = new LRUHashtable<Key,BlockOfferList>(); this.node = node; - // FIXME: use KeyGenerator!! - byte[] offerAuthenticatorKey2 = new byte[32]; - node.random.nextBytes(offerAuthenticatorKey2); - offerAuthenticatorKey = new SecretKeySpec(offerAuthenticatorKey2, "RAW"); + offerAuthenticatorKey = new byte[32]; + node.random.nextBytes(offerAuthenticatorKey); logMINOR = Logger.shouldLog(Logger.MINOR, this); logDEBUG = Logger.shouldLog(Logger.DEBUG, this); offerExecutor = new SerialExecutor(NativeThread.HIGH_PRIORITY); Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java =================================================================== --- trunk/freenet/src/freenet/node/NodeDispatcher.java 2009-01-31 10:20:50 UTC (rev 25444) +++ trunk/freenet/src/freenet/node/NodeDispatcher.java 2009-01-31 15:49:33 UTC (rev 25445) @@ -21,7 +21,6 @@ import freenet.support.Logger; import freenet.support.LogThresholdCallback; import freenet.support.ShortBuffer; -import java.security.InvalidKeyException; /** * @author amphibian @@ -259,8 +258,7 @@ Key key = (Key) m.getObject(DMT.KEY); byte[] authenticator = ((ShortBuffer) m.getObject(DMT.OFFER_AUTHENTICATOR)).getData(); long uid = m.getLong(DMT.UID); - try{ - if(!HMAC.verify(HMAC.ALGORITHM.HmacSHA256, node.failureTable.offerAuthenticatorKey, key.getFullKey(), authenticator)) { + if(!HMAC.verifyWithSHA256(node.failureTable.offerAuthenticatorKey, key.getFullKey(), authenticator)) { Logger.error(this, "Invalid offer request from "+source+" : authenticator did not verify"); try { source.sendAsync(DMT.createFNPGetOfferedKeyInvalid(uid, DMT.GET_OFFERED_KEY_REJECTED_BAD_AUTHENTICATOR), null, node.failureTable.senderCounter); @@ -269,10 +267,6 @@ } return true; } - } catch (InvalidKeyException e) { - Logger.error(this, e.getMessage(), e); - return true; - } if(logMINOR) Logger.minor(this, "Valid GetOfferedKey for "+key+" from "+source); // Do we want it? We can RejectOverload if we don't have the bandwidth... Modified: trunk/freenet/src/freenet/node/PeerNode.java =================================================================== --- trunk/freenet/src/freenet/node/PeerNode.java 2009-01-31 10:20:50 UTC (rev 25444) +++ trunk/freenet/src/freenet/node/PeerNode.java 2009-01-31 15:49:33 UTC (rev 25445) @@ -72,8 +72,6 @@ import freenet.support.math.TimeDecayingRunningAverage; import freenet.support.transport.ip.HostnameSyntaxException; import freenet.support.transport.ip.IPUtil; -import java.security.InvalidKeyException; -import javax.crypto.SecretKey; /** * @author amphibian @@ -107,9 +105,9 @@ private byte[] jfkBuffer; //TODO: sync ? - protected SecretKey jfkKa; - protected SecretKey jfkKe; - protected SecretKey jfkKs; + protected byte[] jfkKa; + protected byte[] jfkKe; + protected byte[] jfkKs; protected byte[] jfkMyRef; // The following is used only if we are the initiator @@ -1838,7 +1836,7 @@ * @return The ID of the new PacketTracker. If this is different to the passed-in trackerID, then * it's a new tracker. -1 to indicate failure. */ - public long completedHandshake(long thisBootID, byte[] data, int offset, int length, BlockCipher encCipher, SecretKey encKey, Peer replyTo, boolean unverified, int negType, long trackerID, boolean isJFK4, boolean jfk4SameAsOld) { + public long completedHandshake(long thisBootID, byte[] data, int offset, int length, BlockCipher encCipher, byte[] encKey, Peer replyTo, boolean unverified, int negType, long trackerID, boolean isJFK4, boolean jfk4SameAsOld) { long now = System.currentTimeMillis(); if(logMINOR) Logger.minor(this, "Tracker ID "+trackerID+" isJFK4="+isJFK4+" jfk4SameAsOld="+jfk4SameAsOld); @@ -1968,7 +1966,7 @@ } else { // else it's a rekey } - newTracker = new SessionKey(this, packets, encCipher, encKey.getEncoded()); + newTracker = new SessionKey(this, packets, encCipher, encKey); if(logMINOR) Logger.minor(this, "New key tracker in completedHandshake: "+newTracker+" for "+packets+" for "+shortToString()+" neg type "+negType); if(unverified) { if(unverifiedTracker != null) { @@ -3480,18 +3478,13 @@ public void offer(Key key) { byte[] keyBytes = key.getFullKey(); // FIXME maybe the authenticator should be shorter than 32 bytes to save memory? - byte[] authenticator = null; - try { - authenticator = HMAC.mac(HMAC.ALGORITHM.HmacSHA256, node.failureTable.offerAuthenticatorKey, keyBytes); - Message msg = DMT.createFNPOfferKey(key, authenticator); - try { - sendAsync(msg, null, node.nodeStats.sendOffersCtr); - } catch (NotConnectedException e) { - // Ignore - } - } catch (InvalidKeyException k) { - Logger.error(this, "Invalid Key!", k); - } + byte[] authenticator = HMAC.macWithSHA256(node.failureTable.offerAuthenticatorKey, keyBytes, 32); + Message msg = DMT.createFNPOfferKey(key, authenticator); + try { + sendAsync(msg, null, node.nodeStats.sendOffersCtr); + } catch(NotConnectedException e) { + // Ignore + } } public OutgoingPacketMangler getOutgoingMangler() { _______________________________________________ cvs mailing list [email protected] http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs
