diff --git a/build.xml b/build.xml
index ace3210a52..c3aaba208d 100644
--- a/build.xml
+++ b/build.xml
@@ -825,9 +825,9 @@
additionalparam="-notimestamp"
doctitle="I2P Javadocs for Release ${release.number} Build ${i2p.build.number}${build.extra}"
windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}">
-
+
-
+
@@ -919,8 +919,8 @@
splitindex="true"
doctitle="I2P Unit Test Javadocs for Release ${release.number} Build ${i2p.build.number}${build.extra}"
windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}">
-
-
+
+
diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java
index 49c7223ea3..14aa275a40 100644
--- a/core/java/src/net/i2p/I2PAppContext.java
+++ b/core/java/src/net/i2p/I2PAppContext.java
@@ -15,7 +15,6 @@ import net.i2p.crypto.CryptixAESEngine;
import net.i2p.crypto.DSAEngine;
import net.i2p.crypto.ElGamalEngine;
import net.i2p.crypto.HMAC256Generator;
-import net.i2p.crypto.HMACGenerator;
import net.i2p.crypto.KeyGenerator;
import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SessionKeyManager;
@@ -76,7 +75,6 @@ public class I2PAppContext {
private ElGamalEngine _elGamalEngine;
private AESEngine _AESEngine;
private LogManager _logManager;
- private HMACGenerator _hmac;
private HMAC256Generator _hmac256;
private SHA256Generator _sha;
protected Clock _clock; // overridden in RouterContext
@@ -95,7 +93,6 @@ public class I2PAppContext {
private volatile boolean _elGamalEngineInitialized;
private volatile boolean _AESEngineInitialized;
private volatile boolean _logManagerInitialized;
- private volatile boolean _hmacInitialized;
private volatile boolean _hmac256Initialized;
private volatile boolean _shaInitialized;
protected volatile boolean _clockInitialized; // used in RouterContext
@@ -119,7 +116,7 @@ public class I2PAppContext {
// split up big lock on this to avoid deadlocks
private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(),
_lock5 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
- _lock9 = new Object(), _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(),
+ _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(),
_lock13 = new Object(), _lock14 = new Object(), _lock16 = new Object(),
_lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object();
@@ -735,29 +732,6 @@ public class I2PAppContext {
}
}
- /**
- * There is absolutely no good reason to make this context specific,
- * other than for consistency, and perhaps later we'll want to
- * include some stats.
- *
- * DEPRECATED - non-standard and used only by SSU.
- * To be moved from context to SSU.
- */
- public HMACGenerator hmac() {
- if (!_hmacInitialized)
- initializeHMAC();
- return _hmac;
- }
-
- private void initializeHMAC() {
- synchronized (_lock9) {
- if (_hmac == null) {
- _hmac= new HMACGenerator(this);
- }
- _hmacInitialized = true;
- }
- }
-
/**
* Un-deprecated in 0.9.38
*/
diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java
index e36b3ea85c..d2ff13d5e0 100644
--- a/core/java/src/net/i2p/crypto/HMAC256Generator.java
+++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java
@@ -13,8 +13,6 @@ import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
-import org.bouncycastle.oldcrypto.macs.I2PHMac;
-
/**
* Calculate the HMAC-SHA256 of a key+message.
* This is compatible with javax.crypto.Mac.getInstance("HmacSHA256").
@@ -28,31 +26,7 @@ public final class HMAC256Generator extends HMACGenerator {
/**
* @param context unused
*/
- public HMAC256Generator(I2PAppContext context) { super(context); }
-
- /**
- * @deprecated unused (not even by Syndie)
- * @throws UnsupportedOperationException since 0.9.12
- */
- @Override
- @Deprecated
- protected I2PHMac acquire() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Calculate the HMAC of the data with the given key
- *
- * @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
- * @deprecated unused (not even by Syndie)
- * @throws UnsupportedOperationException always
- * @since 0.9.12 overrides HMACGenerator
- */
- @Override
- @Deprecated
- public Hash calculate(SessionKey key, byte data[]) {
- throw new UnsupportedOperationException();
- }
+ public HMAC256Generator(I2PAppContext context) { super(); }
/**
* Calculate the HMAC of the data with the given key.
diff --git a/core/java/src/net/i2p/crypto/HMACGenerator.java b/core/java/src/net/i2p/crypto/HMACGenerator.java
index 4ba9bd27c9..444cb1145e 100644
--- a/core/java/src/net/i2p/crypto/HMACGenerator.java
+++ b/core/java/src/net/i2p/crypto/HMACGenerator.java
@@ -1,72 +1,21 @@
package net.i2p.crypto;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.concurrent.LinkedBlockingQueue;
-
-// following are for main() tests
-//import java.security.InvalidKeyException;
-//import java.security.Key;
-//import java.security.NoSuchAlgorithmException;
-//import javax.crypto.spec.SecretKeySpec;
-//import net.i2p.data.Base64;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import net.i2p.util.SimpleByteCache;
-import org.bouncycastle.oldcrypto.macs.I2PHMac;
-
/**
- * Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs
- * in {@link org.bouncycastle.oldcrypto.macs.I2PHMac}
+ * Calculate the HMAC of a key+message.
*
- * Keys are always 32 bytes.
- * This is used only by UDP.
- * Use deprecated outside the router, this may move to router.jar.
- *
- * NOTE THIS IS NOT COMPATIBLE with javax.crypto.Mac.getInstance("HmacMD5")
- * as we tell I2PHMac that the digest length is 32 bytes, so it generates
- * a different result.
- *
- * Quote jrandom:
- * "The HMAC is hardcoded to use SHA256 digest size
- * for backwards compatability. next time we have a backwards
- * incompatible change, we should update this."
- *
- * Does this mean he intended it to be compatible with MD5?
- * See also 2005-07-05 status notes.
+ * As of 0.9.42, this is just a stub.
+ * See net.i2p.router.transport.udp.SSUHMACGenerator for
+ * the HMAC used in SSU (what was originally this class),
+ * and SHA256Generator for the HMAC used in Syndie.
*
*/
-public class HMACGenerator {
- /** set of available HMAC instances for calculate */
- protected final LinkedBlockingQueue _available;
+public abstract class HMACGenerator {
- /**
- * @param context unused
- */
- public HMACGenerator(I2PAppContext context) {
- _available = new LinkedBlockingQueue(32);
- }
-
- /**
- * Calculate the HMAC of the data with the given key
- *
- * @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
- * @deprecated unused (not even by Syndie)
- */
- @Deprecated
- public Hash calculate(SessionKey key, byte data[]) {
- if ((key == null) || (key.getData() == null) || (data == null))
- throw new NullPointerException("Null arguments for HMAC");
- byte rv[] = acquireTmp();
- Arrays.fill(rv, (byte)0x0);
- calculate(key, data, 0, data.length, rv, 0);
- return new Hash(rv);
- }
+ public HMACGenerator() {}
/**
* Calculate the HMAC of the data with the given key
@@ -75,16 +24,7 @@ public class HMACGenerator {
* @param targetOffset offset into target to put the hmac
* @throws IllegalArgumentException for bad key or target too small
*/
- public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) {
- if ((key == null) || (key.getData() == null) || (data == null))
- throw new NullPointerException("Null arguments for HMAC");
-
- I2PHMac mac = acquire();
- mac.init(key.getData());
- mac.update(data, offset, length);
- mac.doFinal(target, targetOffset);
- release(mac);
- }
+ public abstract void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset);
/**
* Verify the MAC inline, reducing some unnecessary memory churn.
@@ -98,42 +38,9 @@ public class HMACGenerator {
* @param origMACLength how much of the MAC do we want to verify
* @throws IllegalArgumentException for bad key
*/
- public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength,
- byte origMAC[], int origMACOffset, int origMACLength) {
- if ((key == null) || (key.getData() == null) || (curData == null))
- throw new NullPointerException("Null arguments for HMAC");
-
- I2PHMac mac = acquire();
- mac.init(key.getData());
- mac.update(curData, curOffset, curLength);
- byte rv[] = acquireTmp();
- mac.doFinal(rv, 0);
- release(mac);
-
- boolean eq = DataHelper.eqCT(rv, 0, origMAC, origMACOffset, origMACLength);
- releaseTmp(rv);
- return eq;
- }
+ public abstract boolean verify(SessionKey key, byte curData[], int curOffset, int curLength,
+ byte origMAC[], int origMACOffset, int origMACLength);
- protected I2PHMac acquire() {
- I2PHMac rv = _available.poll();
- if (rv != null)
- return rv;
- // the HMAC is hardcoded to use SHA256 digest size
- // for backwards compatability. next time we have a backwards
- // incompatible change, we should update this by removing ", 32"
- // SEE NOTES ABOVE
- try {
- MessageDigest md = MessageDigest.getInstance("MD5");
- return new I2PHMac(md, 32);
- } catch (NoSuchAlgorithmException nsae) {
- throw new UnsupportedOperationException("MD5");
- }
- }
-
- private void release(I2PHMac mac) {
- _available.offer(mac);
- }
/**
* 32 bytes from the byte array cache.
@@ -147,62 +54,4 @@ public class HMACGenerator {
protected void releaseTmp(byte tmp[]) {
SimpleByteCache.release(tmp);
}
-
- //private static final int RUNS = 100000;
-
- /**
- * Test the BC and the JVM's implementations for speed
- */
-/**** All this did was prove that we aren't compatible with standard HmacMD5
- public static void main(String args[]) {
- if (args.length != 2) {
- System.err.println("Usage: HMACGenerator keySeedString dataString");
- return;
- }
-
- byte[] rand = SHA256Generator.getInstance().calculateHash(args[0].getBytes()).getData();
- byte[] data = args[1].getBytes();
- Key keyObj = new SecretKeySpec(rand, "HmacMD5");
-
- byte[] keyBytes = keyObj.getEncoded();
- System.out.println("key bytes (" + keyBytes.length + ") is [" + Base64.encode(keyBytes) + "]");
- SessionKey key = new SessionKey(keyBytes);
- System.out.println("session key is [" + key);
- System.out.println("key object is [" + keyObj);
-
- HMACGenerator gen = new HMACGenerator(I2PAppContext.getGlobalContext());
- byte[] result = new byte[16];
- long start = System.currentTimeMillis();
- for (int i = 0; i < RUNS; i++) {
- gen.calculate(key, data, 0, data.length, result, 0);
- if (i == 0)
- System.out.println("MAC [" + Base64.encode(result) + "]");
- }
- long time = System.currentTimeMillis() - start;
- System.out.println("Time for " + RUNS + " HMAC-MD5 computations:");
- System.out.println("BC time (ms): " + time);
-
- start = System.currentTimeMillis();
- javax.crypto.Mac mac;
- try {
- mac = javax.crypto.Mac.getInstance("HmacMD5");
- } catch (NoSuchAlgorithmException e) {
- System.err.println("Fatal: " + e);
- return;
- }
- for (int i = 0; i < RUNS; i++) {
- try {
- mac.init(keyObj);
- } catch (InvalidKeyException e) {
- System.err.println("Fatal: " + e);
- }
- byte[] sha = mac.doFinal(data);
- if (i == 0)
- System.out.println("MAC [" + Base64.encode(sha) + "]");
- }
- time = System.currentTimeMillis() - start;
-
- System.out.println("JVM time (ms): " + time);
- }
-****/
}
diff --git a/history.txt b/history.txt
index 81e3d08837..ef6d581a6c 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,10 @@
+2019-07-12 zzz
+ * Build: Move SSU HMAC implementation from core to router
+ * Test: Fix broken unit test build
+
+2019-07-11 zzz
+ * imagegen: Improve QR font rendering
+
2019-07-09 zzz
* NetDb:
- Fix NPE on store of Encrypted LS (ticket #2563)
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
index 11def9b7f3..200195f621 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
@@ -1619,7 +1619,7 @@ class PacketBuilder {
int hmacLen = totalSize + UDPPacket.IV_SIZE + 2;
//Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen);
byte[] ba = SimpleByteCache.acquire(Hash.HASH_LENGTH);
- _context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba, 0);
+ _transport.getHMAC().calculate(macKey, data, hmacOff, hmacLen, ba, 0);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Authenticating " + pkt.getLength() +
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
index 61f8364c1c..b0c20275e1 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
@@ -10,6 +10,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.util.CoDelBlockingQueue;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
+import net.i2p.data.SessionKey;
import net.i2p.util.I2PThread;
import net.i2p.util.LHMCache;
import net.i2p.util.Log;
@@ -181,6 +182,13 @@ class PacketHandler {
return rv;
}
+ /**
+ * @since 0.9.42
+ */
+ private boolean validate(UDPPacket packet, SessionKey key) {
+ return packet.validate(key, _transport.getHMAC());
+ }
+
/** the packet is from a peer we are establishing an outbound con to, but failed validation, so fallback */
private static final short OUTBOUND_FALLBACK = 1;
/** the packet is from a peer we are establishing an inbound con to, but failed validation, so fallback */
@@ -325,17 +333,17 @@ class PacketHandler {
private void receivePacket(UDPPacketReader reader, UDPPacket packet, PeerState state) {
_state = 17;
AuthType auth = AuthType.NONE;
- boolean isValid = packet.validate(state.getCurrentMACKey());
+ boolean isValid = validate(packet, state.getCurrentMACKey());
if (!isValid) {
_state = 18;
if (state.getNextMACKey() != null)
- isValid = packet.validate(state.getNextMACKey());
+ isValid = validate(packet, state.getNextMACKey());
if (!isValid) {
_state = 19;
if (_log.shouldLog(Log.INFO))
_log.info("Failed validation with existing con, trying as new con: " + packet);
- isValid = packet.validate(_transport.getIntroKey());
+ isValid = validate(packet, _transport.getIntroKey());
if (isValid) {
_state = 20;
// this is a stray packet from an inbound establishment
@@ -388,7 +396,7 @@ class PacketHandler {
*/
private void receivePacket(UDPPacketReader reader, UDPPacket packet, short peerType) {
_state = 27;
- boolean isValid = packet.validate(_transport.getIntroKey());
+ boolean isValid = validate(packet, _transport.getIntroKey());
if (!isValid) {
// Note that the vast majority of these are NOT corrupted packets, but
// packets for which we don't have the PeerState (i.e. SessionKey)
@@ -425,7 +433,7 @@ class PacketHandler {
}
if (ps.getRemotePort() == newPort) {
foundSamePort = true;
- } else if (packet.validate(ps.getCurrentMACKey())) {
+ } else if (validate(packet, ps.getCurrentMACKey())) {
packet.decrypt(ps.getCurrentCipherKey());
reader.initialize(packet);
if (_log.shouldLog(Log.WARN))
@@ -513,7 +521,7 @@ class PacketHandler {
}
boolean isValid = false;
if (state.getMACKey() != null) {
- isValid = packet.validate(state.getMACKey());
+ isValid = validate(packet, state.getMACKey());
if (isValid) {
if (_log.shouldLog(Log.INFO))
_log.info("Valid introduction packet received for inbound con: " + packet);
@@ -558,7 +566,7 @@ class PacketHandler {
boolean isValid = false;
if (state.getMACKey() != null) {
_state = 36;
- isValid = packet.validate(state.getMACKey());
+ isValid = validate(packet, state.getMACKey());
if (isValid) {
// this should be the Session Confirmed packet
if (_log.shouldLog(Log.INFO))
@@ -572,7 +580,7 @@ class PacketHandler {
}
// keys not yet exchanged, lets try it with the peer's intro key
- isValid = packet.validate(state.getIntroKey());
+ isValid = validate(packet, state.getIntroKey());
if (isValid) {
if (_log.shouldLog(Log.INFO))
_log.info("Valid packet received for " + state + " with Bob's intro key: " + packet);
diff --git a/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java b/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java
new file mode 100644
index 0000000000..cdd8edc5a0
--- /dev/null
+++ b/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java
@@ -0,0 +1,185 @@
+package net.i2p.router.transport.udp;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.concurrent.LinkedBlockingQueue;
+
+// following are for main() tests
+//import java.security.InvalidKeyException;
+//import java.security.Key;
+//import java.security.NoSuchAlgorithmException;
+//import javax.crypto.spec.SecretKeySpec;
+//import net.i2p.data.Base64;
+
+import net.i2p.crypto.HMACGenerator;
+import net.i2p.data.DataHelper;
+import net.i2p.data.Hash;
+import net.i2p.data.SessionKey;
+import net.i2p.util.SimpleByteCache;
+
+import org.bouncycastle.oldcrypto.macs.I2PHMac;
+
+/**
+ * Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs
+ * in {@link org.bouncycastle.oldcrypto.macs.I2PHMac}
+ *
+ * Keys are always 32 bytes.
+ * This is used only by UDP.
+ * Use deprecated outside the router, this may move to router.jar.
+ *
+ * NOTE THIS IS NOT COMPATIBLE with javax.crypto.Mac.getInstance("HmacMD5")
+ * as we tell I2PHMac that the digest length is 32 bytes, so it generates
+ * a different result.
+ *
+ * Quote jrandom:
+ * "The HMAC is hardcoded to use SHA256 digest size
+ * for backwards compatability. next time we have a backwards
+ * incompatible change, we should update this."
+ *
+ * Does this mean he intended it to be compatible with MD5?
+ * See also 2005-07-05 status notes.
+ *
+ * @since 0.9.42 moved from net.i2p.crypto.HMACGenerator
+ */
+class SSUHMACGenerator extends HMACGenerator {
+ /** set of available HMAC instances for calculate */
+ private final LinkedBlockingQueue _available;
+
+ public SSUHMACGenerator() {
+ super();
+ _available = new LinkedBlockingQueue(32);
+ }
+
+ /**
+ * Calculate the HMAC of the data with the given key
+ *
+ * @param target out parameter the first 16 bytes contain the HMAC, the last 16 bytes are zero
+ * @param targetOffset offset into target to put the hmac
+ * @throws IllegalArgumentException for bad key or target too small
+ */
+ public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) {
+ if ((key == null) || (key.getData() == null) || (data == null))
+ throw new NullPointerException("Null arguments for HMAC");
+
+ I2PHMac mac = acquire();
+ mac.init(key.getData());
+ mac.update(data, offset, length);
+ mac.doFinal(target, targetOffset);
+ release(mac);
+ }
+
+ /**
+ * Verify the MAC inline, reducing some unnecessary memory churn.
+ *
+ * @param key session key to verify the MAC with
+ * @param curData MAC to verify
+ * @param curOffset index into curData to MAC
+ * @param curLength how much data in curData do we want to run the HMAC over
+ * @param origMAC what do we expect the MAC of curData to equal
+ * @param origMACOffset index into origMAC
+ * @param origMACLength how much of the MAC do we want to verify
+ * @throws IllegalArgumentException for bad key
+ */
+ public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength,
+ byte origMAC[], int origMACOffset, int origMACLength) {
+ if ((key == null) || (key.getData() == null) || (curData == null))
+ throw new NullPointerException("Null arguments for HMAC");
+
+ I2PHMac mac = acquire();
+ mac.init(key.getData());
+ mac.update(curData, curOffset, curLength);
+ byte rv[] = acquireTmp();
+ mac.doFinal(rv, 0);
+ release(mac);
+
+ boolean eq = DataHelper.eqCT(rv, 0, origMAC, origMACOffset, origMACLength);
+ releaseTmp(rv);
+ return eq;
+ }
+
+ private I2PHMac acquire() {
+ I2PHMac rv = _available.poll();
+ if (rv != null)
+ return rv;
+ // the HMAC is hardcoded to use SHA256 digest size
+ // for backwards compatability. next time we have a backwards
+ // incompatible change, we should update this by removing ", 32"
+ // SEE NOTES ABOVE
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ return new I2PHMac(md, 32);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new UnsupportedOperationException("MD5");
+ }
+ }
+
+ private void release(I2PHMac mac) {
+ _available.offer(mac);
+ }
+
+ /**
+ * @since 0.9.42
+ */
+ public void clearCache() {
+ _available.clear();
+ }
+
+ //private static final int RUNS = 100000;
+
+ /**
+ * Test the BC and the JVM's implementations for speed
+ */
+/**** All this did was prove that we aren't compatible with standard HmacMD5
+ public static void main(String args[]) {
+ if (args.length != 2) {
+ System.err.println("Usage: HMACGenerator keySeedString dataString");
+ return;
+ }
+
+ byte[] rand = SHA256Generator.getInstance().calculateHash(args[0].getBytes()).getData();
+ byte[] data = args[1].getBytes();
+ Key keyObj = new SecretKeySpec(rand, "HmacMD5");
+
+ byte[] keyBytes = keyObj.getEncoded();
+ System.out.println("key bytes (" + keyBytes.length + ") is [" + Base64.encode(keyBytes) + "]");
+ SessionKey key = new SessionKey(keyBytes);
+ System.out.println("session key is [" + key);
+ System.out.println("key object is [" + keyObj);
+
+ HMACGenerator gen = new HMACGenerator(I2PAppContext.getGlobalContext());
+ byte[] result = new byte[16];
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < RUNS; i++) {
+ gen.calculate(key, data, 0, data.length, result, 0);
+ if (i == 0)
+ System.out.println("MAC [" + Base64.encode(result) + "]");
+ }
+ long time = System.currentTimeMillis() - start;
+ System.out.println("Time for " + RUNS + " HMAC-MD5 computations:");
+ System.out.println("BC time (ms): " + time);
+
+ start = System.currentTimeMillis();
+ javax.crypto.Mac mac;
+ try {
+ mac = javax.crypto.Mac.getInstance("HmacMD5");
+ } catch (NoSuchAlgorithmException e) {
+ System.err.println("Fatal: " + e);
+ return;
+ }
+ for (int i = 0; i < RUNS; i++) {
+ try {
+ mac.init(keyObj);
+ } catch (InvalidKeyException e) {
+ System.err.println("Fatal: " + e);
+ }
+ byte[] sha = mac.doFinal(data);
+ if (i == 0)
+ System.out.println("MAC [" + Base64.encode(sha) + "]");
+ }
+ time = System.currentTimeMillis() - start;
+
+ System.out.println("JVM time (ms): " + time);
+ }
+****/
+}
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java
index 1eeb4e0916..86c4055a21 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
+import net.i2p.crypto.HMACGenerator;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.SessionKey;
@@ -225,7 +226,7 @@ class UDPPacket implements CDQEntry {
* MAC matches, false otherwise.
*
*/
- public synchronized boolean validate(SessionKey macKey) {
+ public synchronized boolean validate(SessionKey macKey, HMACGenerator hmac) {
verifyNotReleased();
//_beforeValidate = _context.clock().now();
boolean eq = false;
@@ -244,14 +245,14 @@ class UDPPacket implements CDQEntry {
DataHelper.toLong(_validateBuf, off, 2, payloadLength /* ^ PacketBuilder.PROTOCOL_VERSION */ );
off += 2;
- eq = _context.hmac().verify(macKey, _validateBuf, 0, off, _data, _packet.getOffset(), MAC_SIZE);
+ eq = hmac.verify(macKey, _validateBuf, 0, off, _data, _packet.getOffset(), MAC_SIZE);
if (!eq) {
// this is relatively frequent, as you can get old keys in PacketHandler.
Log log = _context.logManager().getLog(UDPPacket.class);
if (log.shouldLog(Log.INFO)) {
byte[] calc = new byte[32];
- _context.hmac().calculate(macKey, _validateBuf, 0, off, calc, 0);
+ hmac.calculate(macKey, _validateBuf, 0, off, calc, 0);
StringBuilder str = new StringBuilder(512);
str.append("Bad HMAC:\n\t");
str.append(_packet.getLength()).append(" byte pkt, ");
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index a73429831b..6407dc9b5d 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import net.i2p.crypto.HMACGenerator;
import net.i2p.crypto.SigType;
import net.i2p.data.DatabaseEntry;
import net.i2p.data.DataHelper;
@@ -87,6 +88,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
private long _introducersSelectedOn;
private long _lastInboundReceivedOn;
private final DHSessionKeyBuilder.Factory _dhFactory;
+ private final SSUHMACGenerator _hmac;
private int _mtu;
private int _mtu_ipv6;
private boolean _mismatchLogged;
@@ -272,6 +274,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_introManager = new IntroductionManager(_context, this);
_introducersSelectedOn = -1;
_lastInboundReceivedOn = -1;
+ _hmac = new SSUHMACGenerator();
_mtu = PeerState.LARGE_MTU;
_mtu_ipv6 = PeerState.MIN_IPV6_MTU;
setupPort();
@@ -614,6 +617,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
UDPPacket.clearCache();
UDPAddress.clearCache();
_lastInboundIPv6 = 0;
+ _hmac.clearCache();
}
/**
@@ -2748,6 +2752,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
return _dhFactory;
}
+ /**
+ * @return the SSU HMAC
+ * @since 0.9.42
+ */
+ HMACGenerator getHMAC() {
+ return _hmac;
+ }
+
/**
* Does nothing
* @deprecated as of 0.9.31
diff --git a/core/java/src/org/bouncycastle/oldcrypto/Mac.java b/router/java/src/org/bouncycastle/oldcrypto/Mac.java
similarity index 98%
rename from core/java/src/org/bouncycastle/oldcrypto/Mac.java
rename to router/java/src/org/bouncycastle/oldcrypto/Mac.java
index aa3f7605fb..a55c19959e 100644
--- a/core/java/src/org/bouncycastle/oldcrypto/Mac.java
+++ b/router/java/src/org/bouncycastle/oldcrypto/Mac.java
@@ -31,6 +31,8 @@ package org.bouncycastle.oldcrypto;
* The base interface for implementations of message authentication codes (MACs).
*
* modified by jrandom to use the session key byte array directly
+ *
+ * Not a public API - Not for external use!
*/
public interface Mac
{
diff --git a/core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java b/router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java
similarity index 99%
rename from core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java
rename to router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java
index e39ef42781..646f8329e1 100644
--- a/core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java
+++ b/router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java
@@ -51,7 +51,7 @@ import org.bouncycastle.oldcrypto.Mac;
* As of 0.9.12, refactored to use standard MessageDigest.
*
* Deprecated - Do not use outside of router or Syndie.
- * To be moved to router.
+ * Not a public API - Not for external use!
*/
public class I2PHMac
implements Mac
diff --git a/core/java/src/org/bouncycastle/oldcrypto/macs/package.html b/router/java/src/org/bouncycastle/oldcrypto/macs/package.html
similarity index 86%
rename from core/java/src/org/bouncycastle/oldcrypto/macs/package.html
rename to router/java/src/org/bouncycastle/oldcrypto/macs/package.html
index 56de5a3940..5b57a27104 100644
--- a/core/java/src/org/bouncycastle/oldcrypto/macs/package.html
+++ b/router/java/src/org/bouncycastle/oldcrypto/macs/package.html
@@ -9,6 +9,9 @@ To avoid having to make two different versions of our Android app, we rename to
Ref: javax.crypto
and
this android issue.
+
+Moved from i2p.jar to router.jar as of 0.9.42.
+Not a public API! Not for external use!