diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 000000000..de77168d0
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/README.txt b/android/README.txt
new file mode 100644
index 000000000..e8886a579
--- /dev/null
+++ b/android/README.txt
@@ -0,0 +1,25 @@
+These instructions are for the 1.5 SDK.
+The build file is not compatible with the 1.1 SDK any more.
+
+#Unzip the android SDK in ../../
+#So then the android tools will be in ../../android-sdk-linux_x86-1.5_r2/tools/
+
+#then build the android apk file:
+ant debug
+
+# Create the android 1.5 virtual device
+# (don't make a custom hardware profile)
+../../android-sdk-linux_x86-1.5_r2/tools/android create avd --name i2p --target 2
+
+#then run the emulator:
+../../android-sdk-linux_x86-1.5_r2/tools/emulator -avd i2p &
+
+#then wait a couple minutes until the emulator is up
+#then install the I2P app
+ant install
+
+#then run the debugger
+../../android-sdk-linux_x86-1.5_r2/tools/ddms &
+
+#to rebuild and reinstall to emulator:
+ant reinstall
diff --git a/android/build.xml b/android/build.xml
new file mode 100644
index 000000000..2b8664dca
--- /dev/null
+++ b/android/build.xml
@@ -0,0 +1,352 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Creating output directories if needed...
+
+
+
+
+
+
+
+
+
+ Generating R.java / Manifest.java from the resources...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Compiling aidl files into Java classes...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converting compiled files and external libraries into ${out-folder}/${dex-file}...
+
+
+
+
+
+
+
+
+
+
+
+
+ Packaging resources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All generated packages need to be signed with jarsigner before they are published.
+
+
+
+
+ Installing ${out-debug-package} onto default emulator...
+
+
+
+
+
+
+
+ Installing ${out-debug-package} onto default emulator...
+
+
+
+
+
+
+
+
+
+ Uninstalling ${application-package} from the default emulator...
+
+
+
+
+
+
+
+
+ Android Ant Build. Available targets:
+ help: Displays this help.
+ debug: Builds the application and sign it with a debug key.
+ release: Builds the application. The generated apk file must be
+ signed before it is published.
+ install: Installs the debug package onto a running emulator or
+ device. This can only be used if the application has
+ not yet been installed.
+ reinstall: Installs the debug package on a running emulator or
+ device that already has the application.
+ The signatures must match.
+ uninstall: uninstall the application from a running emulator or
+ device.
+
+
diff --git a/android/default.properties b/android/default.properties
new file mode 100644
index 000000000..eba5c59ff
--- /dev/null
+++ b/android/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-2
diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml
new file mode 100644
index 000000000..d76411527
--- /dev/null
+++ b/android/res/layout/main.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/android/res/raw/logger_config b/android/res/raw/logger_config
new file mode 100644
index 000000000..2aeabb9f6
--- /dev/null
+++ b/android/res/raw/logger_config
@@ -0,0 +1,3 @@
+logger.defaultLevel=INFO
+logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR
+logger.record.net.i2p.stat.Rate=ERROR
diff --git a/android/res/raw/router_config b/android/res/raw/router_config
new file mode 100644
index 000000000..cf63ed56a
--- /dev/null
+++ b/android/res/raw/router_config
@@ -0,0 +1,16 @@
+# initial router.config
+# temp directory
+i2p.dir.temp=/data/data/net.i2p.router/files/tmp
+i2p.dir.pid=/data/data/net.i2p.router/files/tmp
+# save memory
+router.prng.buffers=2
+router.decayingBloomFilterM=20
+stat.full=false
+i2np.udp.maxConnections=30
+# no I2CP
+i2p.dummyClientFacade=true
+# for now
+i2np.ntcp.enable=false
+# not on android
+i2np.upnp.enable=false
+routerconsole.geoip.enable=false
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
new file mode 100644
index 000000000..983a304b9
--- /dev/null
+++ b/android/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ I2PAndroid
+
diff --git a/android/src/net/i2p/router/I2PAndroid.java b/android/src/net/i2p/router/I2PAndroid.java
new file mode 100644
index 000000000..ed626639c
--- /dev/null
+++ b/android/src/net/i2p/router/I2PAndroid.java
@@ -0,0 +1,142 @@
+package net.i2p.router;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.os.Bundle;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.List;
+
+import net.i2p.router.Router;
+import net.i2p.router.RouterLaunch;
+// import net.i2p.util.NativeBigInteger;
+
+public class I2PAndroid extends Activity
+{
+ static Context _context;
+ private static final String DIR = "/data/data/net.i2p.router/files";
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ _context = this; // Activity extends Context
+ debugStuff();
+ initialize();
+ // 300ms per run
+ // 5x slower than java on my server and 50x slower than native on my server
+ // NativeBigInteger.main(null);
+ }
+
+ public void onRestart()
+ {
+ System.err.println("onRestart called");
+ super.onRestart();
+ }
+
+ public void onStart()
+ {
+ System.err.println("onStart called");
+ super.onStart();
+ RouterLaunch.main(null);
+ System.err.println("Router.main finished");
+ }
+
+ public void onResume()
+ {
+ System.err.println("onResume called");
+ super.onResume();
+ }
+
+ public void onPause()
+ {
+ System.err.println("onPause called");
+ super.onPause();
+ }
+
+ public void onStop()
+ {
+ System.err.println("onStop called");
+ super.onStop();
+
+ // from routerconsole ContextHelper
+ List contexts = RouterContext.listContexts();
+ if ( (contexts == null) || (contexts.size() <= 0) )
+ throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
+ RouterContext ctx = (RouterContext)contexts.get(0);
+
+ // shutdown() doesn't return so use shutdownGracefully()
+ ctx.router().shutdownGracefully(Router.EXIT_HARD);
+ System.err.println("shutdown complete");
+ }
+
+ public void onDestroy()
+ {
+ System.err.println("onDestroy called");
+ super.onDestroy();
+ }
+
+ public static Context getContext() {
+ return _context;
+ }
+
+ private void debugStuff() {
+ System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
+ System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
+ System.err.println("java.version" + ": " + System.getProperty("java.version"));
+ System.err.println("os.arch" + ": " + System.getProperty("os.arch"));
+ System.err.println("os.name" + ": " + System.getProperty("os.name"));
+ System.err.println("os.version" + ": " + System.getProperty("os.version"));
+ System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
+ System.err.println("user.home" + ": " + System.getProperty("user.home"));
+ System.err.println("user.name" + ": " + System.getProperty("user.name"));
+ }
+
+ private void initialize() {
+ // Until we can edit the router.config on the device,
+ // copy it from the resource every time.
+ // File f = new I2PFile("router.config");
+ // if (!f.exists()) {
+ copyResourceToFile(R.raw.router_config, "router.config");
+ copyResourceToFile(R.raw.logger_config, "logger.config");
+ copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
+ // }
+
+ // Set up the locations so Router and WorkingDir can find them
+ System.setProperty("i2p.dir.base", DIR);
+ System.setProperty("i2p.dir.config", DIR);
+ System.setProperty("wrapper.logfile", DIR + "/wrapper.log");
+ }
+
+ private void copyResourceToFile(int resID, String f) {
+ InputStream in = null;
+ FileOutputStream out = null;
+
+ System.err.println("Creating file " + f + " from resource");
+ byte buf[] = new byte[4096];
+ try {
+ // Context methods
+ in = getResources().openRawResource(resID);
+ out = openFileOutput(f, 0);
+
+ int read = 0;
+ while ( (read = in.read(buf)) != -1)
+ out.write(buf, 0, read);
+
+ } catch (IOException ioe) {
+ } catch (Resources.NotFoundException nfe) {
+ } finally {
+ if (in != null) try { in.close(); } catch (IOException ioe) {}
+ if (out != null) try { out.close(); } catch (IOException ioe) {}
+ }
+ }
+
+}
diff --git a/android/src/net/i2p/util/LogWriter.java b/android/src/net/i2p/util/LogWriter.java
new file mode 100644
index 000000000..0babfab37
--- /dev/null
+++ b/android/src/net/i2p/util/LogWriter.java
@@ -0,0 +1,163 @@
+package net.i2p.util;
+
+/*
+ * public domain
+ *
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * bridge to android logging
+ *
+ * @author zzz
+ */
+class LogWriter implements Runnable {
+ private final static long CONFIG_READ_ITERVAL = 10 * 1000;
+ private long _lastReadConfig = 0;
+ private long _numBytesInCurrentFile = 0;
+ private OutputStream _currentOut; // = System.out
+ private int _rotationNum = -1;
+ private String _logFilenamePattern;
+ private File _currentFile;
+ private LogManager _manager;
+
+ private boolean _write;
+
+ private LogWriter() { // nop
+ }
+
+ public LogWriter(LogManager manager) {
+ _manager = manager;
+ }
+
+ public void stopWriting() {
+ _write = false;
+ }
+
+ public void run() {
+ _write = true;
+ try {
+ while (_write) {
+ flushRecords();
+ rereadConfig();
+ }
+ System.err.println("Done writing");
+ } catch (Exception e) {
+ System.err.println("Error writing the logs: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void flushRecords() { flushRecords(true); }
+ public void flushRecords(boolean shouldWait) {
+ try {
+ List records = _manager._removeAll();
+ if (records == null) return;
+ for (int i = 0; i < records.size(); i++) {
+ LogRecord rec = (LogRecord) records.get(i);
+ writeRecord(rec);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ if (shouldWait) {
+ try {
+ synchronized (this) {
+ this.wait(10*1000);
+ }
+ } catch (InterruptedException ie) { // nop
+ }
+ }
+ }
+ }
+
+ public String currentFile() {
+ return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
+ }
+
+ private void rereadConfig() {
+ long now = Clock.getInstance().now();
+ if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
+ _manager.rereadConfig();
+ _lastReadConfig = now;
+ }
+ }
+
+ private void writeRecord(LogRecord rec) {
+ if (rec.getThrowable() == null)
+ log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage());
+ else
+ log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage(), rec.getThrowable());
+ }
+
+ public void log(int priority, Class src, String name, String threadName, String msg) {
+ if (src != null) {
+ String tag = src.getName();
+ int dot = tag.lastIndexOf(".");
+ if (dot >= 0)
+ tag = tag.substring(dot + 1);
+ android.util.Log.println(toAndroidLevel(priority),
+ tag,
+ '[' + threadName + "] " + msg);
+ } else if (name != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ name,
+ '[' + threadName + "] " + msg);
+ else
+ android.util.Log.println(toAndroidLevel(priority),
+ threadName, msg);
+ }
+
+ public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) {
+ if (src != null) {
+ String tag = src.getName();
+ int dot = tag.lastIndexOf(".");
+ if (dot >= 0)
+ tag = tag.substring(dot + 1);
+ android.util.Log.println(toAndroidLevel(priority),
+ tag,
+ '[' + threadName + "] " + msg +
+ ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ } else if (name != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ name,
+ '[' + threadName + "] " + msg +
+ ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ else
+ android.util.Log.println(toAndroidLevel(priority),
+ threadName,
+ msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ }
+
+ private static int toAndroidLevel(int level) {
+ switch (level) {
+ case Log.DEBUG:
+ return android.util.Log.DEBUG;
+ case Log.INFO:
+ return android.util.Log.INFO;
+ case Log.WARN:
+ return android.util.Log.WARN;
+ case Log.ERROR:
+ case Log.CRIT:
+ default:
+ return android.util.Log.ERROR;
+ }
+ }
+
+ private static final String replace(String pattern, int num) {
+ char c[] = pattern.toCharArray();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < c.length; i++) {
+ if ( (c[i] != '#') && (c[i] != '@') )
+ buf.append(c[i]);
+ else
+ buf.append(num);
+ }
+ return buf.toString();
+ }
+}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
index 0aa250654..7d9b28e89 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ContextHelper.java
@@ -5,7 +5,7 @@ import java.util.List;
import net.i2p.data.Hash;
import net.i2p.router.RouterContext;
-class ContextHelper {
+public class ContextHelper {
public static RouterContext getContext(String contextId) {
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.size() <= 0) )
diff --git a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java
index 417d0fc72..504b87d76 100644
--- a/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java
+++ b/core/java/src/gnu/crypto/prng/AsyncFortunaStandalone.java
@@ -12,10 +12,11 @@ import net.i2p.util.Log;
* has been eaten)
*/
public class AsyncFortunaStandalone extends FortunaStandalone implements Runnable {
- private static final int BUFFERS = 16;
+ private static final int DEFAULT_BUFFERS = 16;
private static final int BUFSIZE = 256*1024;
- private final byte asyncBuffers[][] = new byte[BUFFERS][BUFSIZE];
- private final int status[] = new int[BUFFERS];
+ private int _bufferCount;
+ private final byte asyncBuffers[][];
+ private final int status[];
private int nextBuf = 0;
private I2PAppContext _context;
private Log _log;
@@ -27,7 +28,10 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
public AsyncFortunaStandalone(I2PAppContext context) {
super();
- for (int i = 0; i < BUFFERS; i++)
+ _bufferCount = context.getProperty("router.prng.buffers", DEFAULT_BUFFERS);
+ asyncBuffers = new byte[_bufferCount][BUFSIZE];
+ status = new int[_bufferCount];
+ for (int i = 0; i < _bufferCount; i++)
status[i] = STATUS_NEED_FILL;
_context = context;
context.statManager().createRateStat("prng.bufferWaitTime", "", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
@@ -80,11 +84,11 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
status[nextBuf] = STATUS_LIVE;
int prev=nextBuf-1;
if (prev<0)
- prev = BUFFERS-1;
+ prev = _bufferCount-1;
if (status[prev] == STATUS_LIVE)
status[prev] = STATUS_NEED_FILL;
nextBuf++;
- if (nextBuf >= BUFFERS)
+ if (nextBuf >= _bufferCount)
nextBuf = 0;
asyncBuffers.notify();
}
@@ -95,7 +99,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
int toFill = -1;
try {
synchronized (asyncBuffers) {
- for (int i = 0; i < BUFFERS; i++) {
+ for (int i = 0; i < _bufferCount; i++) {
if (status[i] == STATUS_NEED_FILL) {
status[i] = STATUS_FILLING;
toFill = i;
diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java
index 2fcaa7b5e..0335d1e7e 100644
--- a/core/java/src/net/i2p/crypto/HMAC256Generator.java
+++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java
@@ -7,7 +7,8 @@ import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.macs.I2PHMac;
/**
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
@@ -19,15 +20,15 @@ public class HMAC256Generator extends HMACGenerator {
public HMAC256Generator(I2PAppContext context) { super(context); }
@Override
- protected HMac acquire() {
+ protected I2PHMac acquire() {
synchronized (_available) {
if (_available.size() > 0)
- return (HMac)_available.remove(0);
+ return (I2PHMac)_available.remove(0);
}
// 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"
- return new HMac(new Sha256ForMAC());
+ return new I2PHMac(new Sha256ForMAC());
}
private class Sha256ForMAC extends Sha256Standalone implements Digest {
diff --git a/core/java/src/net/i2p/crypto/HMACGenerator.java b/core/java/src/net/i2p/crypto/HMACGenerator.java
index 8388590a2..b549c8855 100644
--- a/core/java/src/net/i2p/crypto/HMACGenerator.java
+++ b/core/java/src/net/i2p/crypto/HMACGenerator.java
@@ -10,7 +10,8 @@ import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.macs.I2PHMac;
/**
* Calculate the HMAC-MD5 of a key+message. All the good stuff occurs
@@ -49,7 +50,7 @@ public class HMACGenerator {
if ((key == null) || (key.getData() == null) || (data == null))
throw new NullPointerException("Null arguments for HMAC");
- HMac mac = acquire();
+ I2PHMac mac = acquire();
mac.init(key.getData());
mac.update(data, offset, length);
//byte rv[] = new byte[Hash.HASH_LENGTH];
@@ -73,7 +74,7 @@ public class HMACGenerator {
if ((key == null) || (key.getData() == null) || (curData == null))
throw new NullPointerException("Null arguments for HMAC");
- HMac mac = acquire();
+ I2PHMac mac = acquire();
mac.init(key.getData());
mac.update(curData, curOffset, curLength);
byte rv[] = acquireTmp();
@@ -86,17 +87,17 @@ public class HMACGenerator {
return eq;
}
- protected HMac acquire() {
+ protected I2PHMac acquire() {
synchronized (_available) {
if (_available.size() > 0)
- return (HMac)_available.remove(0);
+ return (I2PHMac)_available.remove(0);
}
// 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"
- return new HMac(new MD5Digest(), 32);
+ return new I2PHMac(new MD5Digest(), 32);
}
- private void release(HMac mac) {
+ private void release(Mac mac) {
synchronized (_available) {
if (_available.size() < 64)
_available.add(mac);
@@ -122,4 +123,4 @@ public class HMACGenerator {
_availableTmp.add((Object)tmp);
}
}
-}
\ No newline at end of file
+}
diff --git a/core/java/src/net/i2p/util/DecayingBloomFilter.java b/core/java/src/net/i2p/util/DecayingBloomFilter.java
index 164c8e453..8c375a66d 100644
--- a/core/java/src/net/i2p/util/DecayingBloomFilter.java
+++ b/core/java/src/net/i2p/util/DecayingBloomFilter.java
@@ -30,6 +30,7 @@ public class DecayingBloomFilter {
private boolean _keepDecaying;
private DecayEvent _decayEvent;
+ private static final int DEFAULT_M = 23;
private static final boolean ALWAYS_MISS = false;
/**
@@ -44,8 +45,12 @@ public class DecayingBloomFilter {
_context = context;
_log = context.logManager().getLog(DecayingBloomFilter.class);
_entryBytes = entryBytes;
- _current = new BloomSHA1(23, 11); //new BloomSHA1(23, 11);
- _previous = new BloomSHA1(23, 11); //new BloomSHA1(23, 11);
+ // this is instantiated in four different places, they may have different
+ // requirements, but for now use this as a gross method of memory reduction.
+ // m == 23 => 2MB each BloomSHA1 (8MB total)
+ int m = context.getProperty("router.decayingBloomFilterM", DEFAULT_M);
+ _current = new BloomSHA1(m, 11); //new BloomSHA1(23, 11);
+ _previous = new BloomSHA1(m, 11); //new BloomSHA1(23, 11);
_durationMs = durationMs;
int numExtenders = (32+ (entryBytes-1))/entryBytes - 1;
if (numExtenders < 0)
diff --git a/core/java/src/org/bouncycastle/crypto/macs/HMac.java b/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
similarity index 95%
rename from core/java/src/org/bouncycastle/crypto/macs/HMac.java
rename to core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
index 7176c8aca..a566e8a79 100644
--- a/core/java/src/org/bouncycastle/crypto/macs/HMac.java
+++ b/core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java
@@ -42,8 +42,12 @@ import org.bouncycastle.crypto.Mac;
* a frequently used buffer (called on doFinal). changes released into the public
* domain in 2005.
*
+ * This is renamed from HMac because the constructor HMac(digest, sz) does not exist
+ * in the standard bouncycastle library, thus it conflicts in JVMs that contain the
+ * standard library (Android).
+ *
*/
-public class HMac
+public class I2PHMac
implements Mac
{
private final static int BLOCK_LENGTH = 64;
@@ -56,12 +60,12 @@ implements Mac
private byte[] inputPad = new byte[BLOCK_LENGTH];
private byte[] outputPad = new byte[BLOCK_LENGTH];
- public HMac(
+ public I2PHMac(
Digest digest)
{
this(digest, digest.getDigestSize());
}
- public HMac(
+ public I2PHMac(
Digest digest, int sz)
{
this.digest = digest;