merge of '6ad44c8ad61fa5a65207491cab744ddfa8f0f3ca'

and 'db7c4479731f94687d64bea76eafeb4c62e14f1a'
This commit is contained in:
m1xxy
2011-06-03 01:31:31 +00:00
29 changed files with 334 additions and 87 deletions

View File

@ -28,7 +28,7 @@ ant debug
../../android-sdk-linux_86/tools/emulator -avd i2p &
#then wait a couple minutes until the emulator is up
#then install the I2P app
#then install the I2P app (ONE TIME ONLY)
ant install
#then run the debugger
@ -36,3 +36,5 @@ ant install
#to rebuild and reinstall to emulator:
ant reinstall
# Now click on the I2P icon on your phone!

1
android/build.properties Normal file
View File

@ -0,0 +1 @@
application-package=net.i2p.router

View File

@ -76,6 +76,9 @@
<mkdir dir="tmp" />
<unjar src="../build/i2p.jar" dest="tmp/" />
<delete file="tmp/net/i2p/util/LogWriter.class" />
<delete file="tmp/net/i2p/util/SecureDirectory.class" />
<delete file="tmp/net/i2p/util/SecureFile.class" />
<delete file="tmp/net/i2p/util/SecureFileOutputStream.class" />
<!-- org.bouncycastle.crypto already in android
but we need a little trickery because our HMac is incompatible...
and the libs aren't in the SDK to compile against??? -->
@ -237,6 +240,7 @@
<target name="compile" depends="buildrouter, resource-src, aidl">
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
destdir="${out-classes}"
includeantruntime="false"
bootclasspathref="android.target.classpath">
<src path="${source-folder}" />
<src path="${gen-folder}" />
@ -280,6 +284,12 @@
<!-- Package the application and sign it with a debug key.
This is the default target when building. It is used for debug. -->
<!--
I2P when this fails 365 days later because the key expired, delete ~/.android/debug.keystore
Then do 'ant uninstall' (since the new key doesn't match the old key)
Then do 'ant install'
See http://developer.android.com/guide/publishing/app-signing.html for more info
-->
<target name="debug" depends="dex, package-resources">
<apkbuilder
outfolder="${out-folder}"
@ -327,12 +337,12 @@
</exec>
</target>
<!-- Uinstall the package from the default emulator -->
<!-- Uninstall the package from the default emulator -->
<target name="uninstall">
<echo>Uninstalling ${application-package} from the default emulator...</echo>
<exec executable="${adb}" failonerror="true">
<arg value="uninstall" />
<arg path="${application-package}" />
<arg value="${application-package}" />
</exec>
</target>

View File

@ -6,17 +6,27 @@ i2p.dir.pid=/data/data/net.i2p.router/files/tmp
prng.buffers=2
router.decayingBloomFilterM=20
stat.full=false
i2np.udp.maxConnections=30
#
# no I2CP
#
i2p.dummyClientFacade=true
# for now
#
##### Transport
#
#
# NTCP
#
#i2np.ntcp.enable=false
i2np.ntcp.maxConnections=8
#
# UDP crashes the JVM, don't know why
#
i2np.udp.enable=false
i2np.udp.maxConnections=12
#
# no COMM at all!!!
#i2p.vmCommSystem=true
#
# not on android
i2np.upnp.enable=false
routerconsole.geoip.enable=false

View File

@ -46,6 +46,7 @@ public class I2PAndroid extends Activity
{
System.err.println("onStart called");
super.onStart();
// net.i2p.crypto.DSAEngine.main(null);
RouterLaunch.main(null);
System.err.println("Router.main finished");
}

View File

@ -10,6 +10,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Queue;
/**
* bridge to android logging
@ -56,12 +57,22 @@ class LogWriter implements Runnable {
public void flushRecords() { flushRecords(true); }
public void flushRecords(boolean shouldWait) {
try {
List records = _manager._removeAll();
// zero copy, drain the manager queue directly
Queue<LogRecord> records = _manager.getQueue();
if (records == null) return;
for (int i = 0; i < records.size(); i++) {
LogRecord rec = (LogRecord) records.get(i);
if (!records.isEmpty()) {
LogRecord rec;
while ((rec = records.poll()) != null) {
writeRecord(rec);
}
try {
if (_currentOut != null)
_currentOut.flush();
} catch (IOException ioe) {
//if (++_diskFullMessageCount < MAX_DISKFULL_MESSAGES)
System.err.println("Error writing the router log - disk full? " + ioe);
}
}
} catch (Throwable t) {
t.printStackTrace();
} finally {

View File

@ -0,0 +1,22 @@
package net.i2p.util;
import java.io.File;
/**
* setXXX() not available until API level 9 (Platform Version 2.3)
* @since 0.8.7
*/
public class SecureDirectory extends File {
public SecureDirectory(String pathname) {
super(pathname);
}
public SecureDirectory(String parent, String child) {
super(parent, child);
}
public SecureDirectory(File parent, String child) {
super(parent, child);
}
}

View File

@ -0,0 +1,22 @@
package net.i2p.util;
import java.io.File;
/**
* setXXX() not available until API level 9 (Platform Version 2.3)
* @since 0.8.7
*/
public class SecureFile extends SecureDirectory {
public SecureFile(String pathname) {
super(pathname);
}
public SecureFile(String parent, String child) {
super(parent, child);
}
public SecureFile(File parent, String child) {
super(parent, child);
}
}

View File

@ -0,0 +1,53 @@
package net.i2p.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import net.i2p.I2PAppContext;
/**
* setXXX() not available until API level 9 (Platform Version 2.3)
* @since 0.8.7
*/
public class SecureFileOutputStream extends FileOutputStream {
/**
* super()
*/
public SecureFileOutputStream(String file) throws FileNotFoundException {
super(file);
}
/**
* super()
*/
public SecureFileOutputStream(String file, boolean append) throws FileNotFoundException {
super(file, append);
}
/**
* super()
*/
public SecureFileOutputStream(File file) throws FileNotFoundException {
super(file);
}
/**
* super()
*/
public SecureFileOutputStream(File file, boolean append) throws FileNotFoundException {
super(file, append);
}
/** @return false */
static boolean canSetPerms() {
return false;
}
/**
* noop
*/
public static void setPerms(File f) {
}
}

View File

@ -26,7 +26,7 @@ dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=**/*.html
excludes=**/*.html,**/*.txt
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
file.reference.i2p.jar=../../core/java/build/i2p.jar
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar

View File

@ -557,7 +557,8 @@ public class Storage
private static final char[] ILLEGAL = new char[] {
'<', '>', ':', '"', '/', '\\', '|', '?', '*',
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
0x7f };
/**
* Removes 'suspicious' characters from the given file name.

View File

@ -824,7 +824,8 @@
<!-- thazzit -->
</target>
<target name="test" depends="buildProperties" >
<target name="test" depends="buildProperties, jbigi" >
<mkdir dir="reports/core/junit/" />
<ant dir="core/java/" target="test" />
</target>
<target name="junit.report" depends="buildProperties" >

View File

@ -99,7 +99,7 @@
<pathelement path="${classpath}" />
<pathelement location="./build/obj_test" />
<pathelement location="./build/obj" />
<pathelement location="../../installer/lib/jbigi/jbigi.jar" />
<pathelement location="../../build/jbigi.jar" />
<pathelement location="${with.cobertura}" />
</classpath>
<batchtest todir="../../reports/core/junit/">

View File

@ -687,14 +687,14 @@ public class I2PAppContext {
}
}
/** @deprecated unused */
/** @deprecated used only by syndie */
public HMAC256Generator hmac256() {
if (!_hmac256Initialized)
initializeHMAC256();
return _hmac256;
}
/** @deprecated unused */
/** @deprecated used only by syndie */
private void initializeHMAC256() {
synchronized (this) {
if (_hmac256 == null) {

View File

@ -91,14 +91,12 @@ public class ElGamalAESEngine {
SessionTag st = new SessionTag(tag);
SessionKey key = keyManager.consumeTag(st);
SessionKey foundKey = new SessionKey();
foundKey.setData(null);
SessionKey usedKey = new SessionKey();
Set foundTags = new HashSet();
byte decrypted[] = null;
boolean wasExisting = false;
if (key != null) {
//if (_log.shouldLog(Log.DEBUG)) _log.debug("Key is known for tag " + st);
usedKey.setData(key.getData());
long id = _context.random().nextLong();
if (_log.shouldLog(Log.DEBUG))
_log.debug(id + ": Decrypting existing session encrypted with tag: " + st.toString() + ": key: " + key.toBase64() + ": " + data.length + " bytes: " + Base64.encode(data, 0, 64));
@ -138,7 +136,7 @@ public class ElGamalAESEngine {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Found key: " + foundKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting);
keyManager.tagsReceived(foundKey, foundTags);
} else {
} else if (usedKey.getData() != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Used key: " + usedKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting);
keyManager.tagsReceived(usedKey, foundTags);
@ -160,11 +158,12 @@ public class ElGamalAESEngine {
* the decryptAESBlock method & structure.
*
* @param foundTags set which is filled with any sessionTags found during decryption
* @param foundKey session key which may be filled with a new sessionKey found during decryption
* @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption
* @param usedKey out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success.
*
* @return null if decryption fails
*/
byte[] decryptNewSession(byte data[], PrivateKey targetPrivateKey, Set foundTags, SessionKey usedKey,
private byte[] decryptNewSession(byte data[], PrivateKey targetPrivateKey, Set foundTags, SessionKey usedKey,
SessionKey foundKey) throws DataFormatException {
if (data == null) {
//if (_log.shouldLog(Log.WARN)) _log.warn("Data is null, unable to decrypt new session");
@ -231,11 +230,13 @@ public class ElGamalAESEngine {
* If anything doesn't match up in decryption, it falls back to decryptNewSession
*
* @param foundTags set which is filled with any sessionTags found during decryption
* @param foundKey session key which may be filled with a new sessionKey found during decryption
* @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption
* @param usedKey out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success.
*
* @return decrypted data or null on failure
*
*/
byte[] decryptExistingSession(byte data[], SessionKey key, PrivateKey targetPrivateKey, Set foundTags,
private byte[] decryptExistingSession(byte data[], SessionKey key, PrivateKey targetPrivateKey, Set foundTags,
SessionKey usedKey, SessionKey foundKey) throws DataFormatException {
byte preIV[] = new byte[32];
System.arraycopy(data, 0, preIV, 0, preIV.length);
@ -243,8 +244,6 @@ public class ElGamalAESEngine {
byte iv[] = new byte[16];
System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
usedKey.setData(key.getData());
//_log.debug("Pre IV for decryptExistingSession: " + DataHelper.toString(preIV, 32));
//_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32));
byte decrypted[] = decryptAESBlock(data, 32, data.length-32, key, iv, preIV, foundTags, foundKey);
@ -267,6 +266,7 @@ public class ElGamalAESEngine {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Decrypt with an EXISTING session tag successfull, # tags read: " + foundTags.size(),
// new Exception("Decrypted by"));
usedKey.setData(key.getData());
return decrypted;
}
@ -287,13 +287,17 @@ public class ElGamalAESEngine {
* consume it, but if it is null, record the keys, etc as part of a new session.
*
* @param foundTags set which is filled with any sessionTags found during decryption
* @param foundKey session key which may be filled with a new sessionKey found during decryption
* @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption
* @return decrypted data or null on failure
*/
byte[] decryptAESBlock(byte encrypted[], SessionKey key, byte iv[],
private byte[] decryptAESBlock(byte encrypted[], SessionKey key, byte iv[],
byte sentTag[], Set foundTags, SessionKey foundKey) throws DataFormatException {
return decryptAESBlock(encrypted, 0, encrypted.length, key, iv, sentTag, foundTags, foundKey);
}
/*
* Note: package private for ElGamalTest.testAES()
*/
byte[] decryptAESBlock(byte encrypted[], int offset, int encryptedLen, SessionKey key, byte iv[],
byte sentTag[], Set foundTags, SessionKey foundKey) throws DataFormatException {
//_log.debug("iv for decryption: " + DataHelper.toString(iv, 16));
@ -448,7 +452,7 @@ public class ElGamalAESEngine {
* </pre>
*
*/
byte[] encryptNewSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery,
private byte[] encryptNewSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery,
SessionKey newKey, long paddedSize) {
//_log.debug("Encrypting to a NEW session");
byte elgSrcData[] = new byte[SessionKey.KEYSIZE_BYTES+32+158];
@ -511,7 +515,7 @@ public class ElGamalAESEngine {
* </pre>
*
*/
byte[] encryptExistingSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery,
private byte[] encryptExistingSession(byte data[], PublicKey target, SessionKey key, Set tagsForDelivery,
SessionTag currentTag, SessionKey newKey, long paddedSize) {
//_log.debug("Encrypting to an EXISTING session");
byte rawTag[] = currentTag.getData();
@ -542,12 +546,14 @@ public class ElGamalAESEngine {
* - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
* </pre>
*
* Note: package private for ElGamalTest.testAES()
*/
final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey,
long paddedSize) {
return encryptAESBlock(data, key, iv, tagsForDelivery, newKey, paddedSize, 0);
}
final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey,
private final byte[] encryptAESBlock(byte data[], SessionKey key, byte[] iv, Set tagsForDelivery, SessionKey newKey,
long paddedSize, int prefixBytes) {
//_log.debug("iv for encryption: " + DataHelper.toString(iv, 16));
//_log.debug("Encrypting AES");
@ -616,6 +622,7 @@ public class ElGamalAESEngine {
context.random().nextBytes(rv);
return rv;
}
final static int getPaddingSize(int curSize, long minPaddedSize) {
int diff = 0;
if (curSize < minPaddedSize) {

View File

@ -13,9 +13,12 @@ import org.bouncycastle.crypto.macs.I2PHMac;
/**
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
* in {@link org.bouncycastle.crypto.macs.I2PHMac} and
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
* {@link net.i2p.crypto.Sha256Standalone}.
*
* deprecated unused
* This should be compatible with javax.crypto.Mac.getInstance("HmacSHA256")
* but that is untested.
*
* deprecated used only by syndie
*/
public class HMAC256Generator extends HMACGenerator {
public HMAC256Generator(I2PAppContext context) { super(context); }

View File

@ -3,41 +3,67 @@ package net.i2p.crypto;
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.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.macs.I2PHMac;
/**
* Calculate the HMAC-MD5 of a key+message. All the good stuff occurs
* Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs
* in {@link org.bouncycastle.crypto.macs.I2PHMac} and
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
*
* 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.
*
*/
public class HMACGenerator {
private I2PAppContext _context;
/** set of available HMAC instances for calculate */
protected final LinkedBlockingQueue<I2PHMac> _available;
/** set of available byte[] buffers for verify */
private final LinkedBlockingQueue<byte[]> _availableTmp;
/**
* @param context unused
*/
public HMACGenerator(I2PAppContext context) {
_context = context;
_available = new LinkedBlockingQueue(32);
_availableTmp = 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
*/
public Hash calculate(SessionKey key, byte data[]) {
if ((key == null) || (key.getData() == null) || (data == null))
throw new NullPointerException("Null arguments for HMAC");
byte rv[] = new byte[Hash.HASH_LENGTH];
byte rv[] = acquireTmp();
Arrays.fill(rv, (byte)0x0);
calculate(key, data, 0, data.length, rv, 0);
return new Hash(rv);
}
@ -52,10 +78,8 @@ public class HMACGenerator {
I2PHMac mac = acquire();
mac.init(key.getData());
mac.update(data, offset, length);
//byte rv[] = new byte[Hash.HASH_LENGTH];
mac.doFinal(target, targetOffset);
release(mac);
//return new Hash(rv);
}
/**
@ -77,7 +101,6 @@ public class HMACGenerator {
mac.init(key.getData());
mac.update(curData, curOffset, curLength);
byte rv[] = acquireTmp();
//byte rv[] = new byte[Hash.HASH_LENGTH];
mac.doFinal(rv, 0);
release(mac);
@ -93,6 +116,7 @@ public class HMACGenerator {
// 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
return new I2PHMac(new MD5Digest(), 32);
}
@ -100,17 +124,74 @@ public class HMACGenerator {
_available.offer(mac);
}
// temp buffers for verify(..)
/**
* Not really tmp, just from the byte array cache.
* Does NOT zero.
*/
private byte[] acquireTmp() {
byte rv[] = _availableTmp.poll();
if (rv != null)
Arrays.fill(rv, (byte)0x0);
else
rv = new byte[Hash.HASH_LENGTH];
byte rv[] = SimpleByteCache.acquire(Hash.HASH_LENGTH);
return rv;
}
private void releaseTmp(byte tmp[]) {
_availableTmp.offer(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);
}
****/
}

View File

@ -20,6 +20,7 @@ import net.i2p.data.SessionKey;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.Clock;
import net.i2p.util.Log;
import net.i2p.util.NativeBigInteger;
@ -29,19 +30,18 @@ import net.i2p.util.RandomSource;
* @author jrandom
*/
public class KeyGenerator {
private Log _log;
private I2PAppContext _context;
private final Log _log;
private final I2PAppContext _context;
public KeyGenerator(I2PAppContext context) {
_log = context.logManager().getLog(KeyGenerator.class);
_context = context;
}
public static KeyGenerator getInstance() {
return I2PAppContext.getGlobalContext().keyGenerator();
}
/** Generate a private 256 bit session key
* @return session key
*/
@ -84,11 +84,11 @@ public class KeyGenerator {
* index 1 is a PrivateKey
* @return pair of keys
*/
public Object[] generatePKIKeypair() {
public SimpleDataStructure[] generatePKIKeypair() {
BigInteger a = new NativeBigInteger(PUBKEY_EXPONENT_SIZE, _context.random());
BigInteger aalpha = CryptoConstants.elgg.modPow(a, CryptoConstants.elgp);
Object[] keys = new Object[2];
SimpleDataStructure[] keys = new SimpleDataStructure[2];
keys[0] = new PublicKey();
keys[1] = new PrivateKey();
byte[] k0 = aalpha.toByteArray();
@ -97,8 +97,8 @@ public class KeyGenerator {
// bigInteger.toByteArray returns SIGNED integers, but since they'return positive,
// signed two's complement is the same as unsigned
((PublicKey) keys[0]).setData(padBuffer(k0, PublicKey.KEYSIZE_BYTES));
((PrivateKey) keys[1]).setData(padBuffer(k1, PrivateKey.KEYSIZE_BYTES));
keys[0].setData(padBuffer(k0, PublicKey.KEYSIZE_BYTES));
keys[1].setData(padBuffer(k1, PrivateKey.KEYSIZE_BYTES));
return keys;
}
@ -120,8 +120,8 @@ public class KeyGenerator {
* index 1 is a SigningPrivateKey
* @return pair of keys
*/
public Object[] generateSigningKeypair() {
Object[] keys = new Object[2];
public SimpleDataStructure[] generateSigningKeypair() {
SimpleDataStructure[] keys = new SimpleDataStructure[2];
BigInteger x = null;
// make sure the random key is less than the DSA q
@ -135,8 +135,8 @@ public class KeyGenerator {
byte k0[] = padBuffer(y.toByteArray(), SigningPublicKey.KEYSIZE_BYTES);
byte k1[] = padBuffer(x.toByteArray(), SigningPrivateKey.KEYSIZE_BYTES);
((SigningPublicKey) keys[0]).setData(k0);
((SigningPrivateKey) keys[1]).setData(k1);
keys[0].setData(k0);
keys[1].setData(k1);
return keys;
}

View File

@ -32,6 +32,9 @@ public final class SHA256Generator {
_useGnu = useGnu;
}
/**
* @param context unused
*/
public SHA256Generator(I2PAppContext context) {
_digests = new LinkedBlockingQueue(32);
}

View File

@ -41,7 +41,7 @@ public class SessionKey extends SimpleDataStructure {
*/
@Override
public void setData(byte[] data) {
_data = data;
super.setData(data);
_preparedKey = null;
}

View File

@ -15,7 +15,9 @@ import net.i2p.data.DataHelper;
*/
public class ReusableGZIPOutputStream extends ResettableGZIPOutputStream {
// Apache Harmony 5.0M13 Deflater doesn't work after reset()
private static final boolean ENABLE_CACHING = !System.getProperty("java.vendor").startsWith("Apache");
// Neither does Android
private static final boolean ENABLE_CACHING = !(System.getProperty("java.vendor").startsWith("Apache") ||
System.getProperty("java.vendor").contains("Android"));
private static final LinkedBlockingQueue<ReusableGZIPOutputStream> _available;
static {
if (ENABLE_CACHING)

View File

@ -27,9 +27,10 @@ package org.bouncycastle.crypto.macs;
*/
//import org.bouncycastle.crypto.CipherParameters;
import java.util.ArrayList;
import java.util.Arrays;
import net.i2p.util.SimpleByteCache;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Mac;
@ -65,6 +66,11 @@ implements Mac
{
this(digest, digest.getDigestSize());
}
/**
* @param sz override the digest's size
* SEE NOTES in HMACGenerator about why this isn't compatible with standard HmacMD5
*/
public I2PHMac(
Digest digest, int sz)
{
@ -165,28 +171,14 @@ implements Mac
return len;
}
/**
* list of buffers - index 0 is the cache for 32 byte arrays, while index 1 is the cache for 16 byte arrays
*/
private static ArrayList _tmpBuf[] = new ArrayList[] { new ArrayList(), new ArrayList() };
private static byte[] acquireTmp(int sz) {
byte rv[] = null;
synchronized (_tmpBuf[sz == 32 ? 0 : 1]) {
if (!_tmpBuf[sz == 32 ? 0 : 1].isEmpty())
rv = (byte[])_tmpBuf[sz == 32 ? 0 : 1].remove(0);
}
if (rv != null)
byte[] rv = SimpleByteCache.acquire(sz);
Arrays.fill(rv, (byte)0x0);
else
rv = new byte[sz];
return rv;
}
private static void releaseTmp(byte buf[]) {
if (buf == null) return;
synchronized (_tmpBuf[buf.length == 32 ? 0 : 1]) {
if (_tmpBuf[buf.length == 32 ? 0 : 1].size() < 100)
_tmpBuf[buf.length == 32 ? 0 : 1].add((Object)buf);
}
SimpleByteCache.release(buf);
}
/**

View File

@ -1,3 +1,15 @@
2011-06-02 zzz
* Android: Build fixes
* Crypto:
- HMAC Javadocs and cleanups
- HMAC Use SimpleByteCache
* ElGamalAESEngine: Fixups required after SessionKey enforcement
* Reseed: Give up on a seed after 90% of fetches fail
* SessionKey: Enforce data size and prevent reuse
2011-06-02 sponge
* Remove txt file in BOB.jar as per zzz's request.
2011-06-01 zzz
* Crypto:
- Use java.security.MessageDigest instead of bundled GNU SHA-256 code

View File

@ -150,12 +150,15 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
int len = Hash.HASH_LENGTH + 1 + 4; // key+type+replyToken
if (_replyToken > 0)
len += 4 + Hash.HASH_LENGTH; // replyTunnel+replyGateway
if (_dbEntry.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
int type = _dbEntry.getType();
if (type == DatabaseEntry.KEY_TYPE_LEASESET) {
_byteCache = _dbEntry.toByteArray();
} else if (_dbEntry.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
} else if (type == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
byte uncompressed[] = _dbEntry.toByteArray();
_byteCache = DataHelper.compress(uncompressed);
len += 2;
} else {
throw new IllegalStateException("Invalid key type " + type);
}
len += _byteCache.length;
return len;
@ -166,7 +169,7 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
if (_dbEntry == null) throw new I2NPMessageException("Missing entry");
int type = _dbEntry.getType();
if (type != DatabaseEntry.KEY_TYPE_LEASESET && type != DatabaseEntry.KEY_TYPE_ROUTERINFO)
throw new I2NPMessageException("Invalid key type");
throw new I2NPMessageException("Invalid key type " + type);
// Use the hash of the DatabaseEntry
System.arraycopy(getKey().getData(), 0, out, curIndex, Hash.HASH_LENGTH);

View File

@ -311,8 +311,11 @@ public class Router {
}
public RouterInfo getRouterInfo() { return _routerInfo; }
public void setRouterInfo(RouterInfo info) {
_routerInfo = info;
if (_log.shouldLog(Log.INFO))
_log.info("setRouterInfo() : " + info, new Exception("I did it"));
if (info != null)
_context.jobQueue().addJob(new PersistRouterInfoJob(_context));
}
@ -614,6 +617,10 @@ public class Router {
}
}
// hard and ugly
if (System.getProperty("wrapper.version") != null)
_log.log(Log.CRIT, "Restarting with new router identity");
else
_log.log(Log.CRIT, "Shutting down because old router identity was invalid - restart I2P");
finalShutdown(EXIT_HARD_RESTART);
}

View File

@ -121,7 +121,7 @@ public class RouterContext extends I2PAppContext {
public void initAll() {
if (getBooleanProperty("i2p.dummyClientFacade"))
System.err.println("i2p.dummpClientFacade currently unsupported");
System.err.println("i2p.dummyClientFacade currently unsupported");
_clientManagerFacade = new ClientManagerFacadeImpl(this);
// removed since it doesn't implement InternalClientManager for now
//else

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 15;
public final static long BUILD = 16;
/** for example "-test" */
public final static String EXTRA = "";

View File

@ -65,7 +65,7 @@ public class PublishLocalRouterInfoJob extends JobImpl {
try {
getContext().netDb().publish(ri);
} catch (IllegalArgumentException iae) {
_log.log(Log.CRIT, "Error publishing our identity - corrupt?", iae);
_log.log(Log.CRIT, "Error publishing our identity - corrupt? Restart required", iae);
getContext().router().rebuildNewIdentity();
}
} catch (DataFormatException dfe) {

View File

@ -344,6 +344,9 @@ public class Reseeder {
} catch (IOException e) {
errors++;
}
// Give up on this one after 10 with only 0 or 1 good
if (errors >= 10 && fetched <= 1)
break;
}
System.err.println("Reseed got " + fetched + " router infos from " + seedURL + " with " + errors + " errors");