big ol' update to strip out the singletons, replacing them with

a rooted app context.  The core itself has its own I2PAppContext
(see its javadoc for, uh, docs), and the router extends that to
expose the router's singletons.  The main point of this is to
make it so that we can run multiple routers in the same JVM, even
to allow different apps in the same JVM to switch singleton
implementations (e.g. run some routers with one set of profile
calculators, and other routers with a different one).
There is still some work to be done regarding the actual boot up
of multiple routers in a JVM, as well as their configuration,
though the plan is to have the RouterContext override the
I2PAppContext's getProperty/getPropertyNames methods to read from
a config file (seperate ones per context) instead of using the
System.getProperty that the base I2PAppContext uses.
Once the multi-router is working, i'll shim in a VMCommSystem
that doesn't depend upon sockets or threads to read/write (and
that uses configurable message send delays / disconnects / etc,
perhaps using data from the routerContext.getProperty to drive it).
I could hold off until the sim is all working, but there's a
truckload of changes in here and I hate dealing with conflicts ;)
Everything works - I've been running 'er for a while and kicked
the tires a bit, but if you see something amiss, please let me
know.
This commit is contained in:
jrandom
2004-04-24 11:54:35 +00:00
committed by zzz
parent c29a6b95ae
commit 393b1d7674
217 changed files with 16662 additions and 15452 deletions

View File

@ -1,138 +1,140 @@
package net.i2p.crypto;
/*
/*
* Copyright (c) 2003, TheCrypto
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the TheCrypto may be used to endorse or promote
* products derived from this software without specific prior written
* - Neither the name of the TheCrypto may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import net.i2p.data.SessionKey;
import net.i2p.data.DataHelper;
import net.i2p.I2PAppContext;
public class AES256Bench {
private static I2PAppContext _context = new I2PAppContext();
public static void main(String args[]) {
char[] cplain = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
};
byte[] plain = new byte[cplain.length];
for (int x = 0; x < cplain.length; x++) {
plain[x] = (byte)cplain[x];
}
char[] ckey = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
byte[] bkey = new byte[ckey.length];
for (int x = 0; x < ckey.length; x++) {
bkey[x] = (byte)ckey[x];
}
SessionKey key = new SessionKey();
key.setData(bkey);
char[] civ = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x67, 0x54, 0x32, 0x10
};
byte[] iv = new byte[civ.length];
for (int x = 0; x < iv.length; x++) {
iv[x] = (byte)civ[x];
}
byte[] e = AESEngine.getInstance().encrypt(plain, key, iv);
byte[] d = AESEngine.getInstance().decrypt(e, key, iv);
boolean same = true;
for (int x = 0; x < d.length; x++) {
if (plain[x] != d[x]) {
same = false;
}
}
System.out.println("Standard test D(E(value)) == value? " + same);
plain = "1234567890123456".getBytes();
e = AESEngine.getInstance().encrypt(plain, key, iv);
d = AESEngine.getInstance().decrypt(e, key, iv);
same = DataHelper.eq(plain, d);
System.out.println("Different value test D(E(value)) == value? " + same);
System.out.println();
System.out.println();
long times = 100;
long encrypttime = 0;
long decrypttime = 0;
long maxE = 0;
long minE = 0;
long maxD = 0;
long minD = 0;
byte[] message = new byte[2*1024];
for (int i = 0; i < message.length; i++)
message[i] = (byte)((i%26)+'a');
for (int x = 0; x < times; x++) {
long startencrypt = System.currentTimeMillis();
e = AESEngine.getInstance().encrypt(message, key, iv);
long endencryptstartdecrypt = System.currentTimeMillis();
d = AESEngine.getInstance().decrypt(e, key, iv);
long enddecrypt = System.currentTimeMillis();
System.out.print(".");
encrypttime += endencryptstartdecrypt - startencrypt;
decrypttime += enddecrypt - endencryptstartdecrypt;
if (!DataHelper.eq(d, message)) {
System.out.println("Lengths: source [" + message.length + "] dest [" + d.length + "]");
System.out.println("Data: dest [" + DataHelper.toString(d, d.length) + "]");
throw new RuntimeException("Holy crap, decrypted != source message");
}
if ( (minE == 0) && (minD == 0) ) {
minE = endencryptstartdecrypt - startencrypt;
maxE = endencryptstartdecrypt - startencrypt;
minD = enddecrypt - endencryptstartdecrypt;
maxD = enddecrypt - endencryptstartdecrypt;
} else {
if (minE > endencryptstartdecrypt - startencrypt) minE = endencryptstartdecrypt - startencrypt;
if (maxE < endencryptstartdecrypt - startencrypt) maxE = endencryptstartdecrypt - startencrypt;
if (minD > enddecrypt - endencryptstartdecrypt) minD = enddecrypt - endencryptstartdecrypt;
if (maxD < enddecrypt - endencryptstartdecrypt) maxD = enddecrypt - endencryptstartdecrypt;
}
}
System.out.println();
System.out.println("Data size : " + message.length);
System.out.println("Encryption Time Average : " + (encrypttime/times) + "ms\ttotal: " + encrypttime + "ms\tmin: " + minE + "ms\tmax: " + maxE + "ms\tEncryption Bps: " + (times*message.length*1000)/encrypttime);
System.out.println("Decryption Time Average : " + (decrypttime/times) + "ms\ttotal: " + decrypttime + "ms\tmin: " + minD + "ms\tmax: " + maxD + "ms\tDecryption Bps: " + (times*message.length*1000)/decrypttime);
char[] cplain = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
};
byte[] plain = new byte[cplain.length];
for (int x = 0; x < cplain.length; x++) {
plain[x] = (byte)cplain[x];
}
char[] ckey = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
byte[] bkey = new byte[ckey.length];
for (int x = 0; x < ckey.length; x++) {
bkey[x] = (byte)ckey[x];
}
SessionKey key = new SessionKey();
key.setData(bkey);
char[] civ = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x67, 0x54, 0x32, 0x10
};
byte[] iv = new byte[civ.length];
for (int x = 0; x < iv.length; x++) {
iv[x] = (byte)civ[x];
}
byte[] e = _context.AESEngine().encrypt(plain, key, iv);
byte[] d = _context.AESEngine().decrypt(e, key, iv);
boolean same = true;
for (int x = 0; x < d.length; x++) {
if (plain[x] != d[x]) {
same = false;
}
}
System.out.println("Standard test D(E(value)) == value? " + same);
plain = "1234567890123456".getBytes();
e = _context.AESEngine().encrypt(plain, key, iv);
d = _context.AESEngine().decrypt(e, key, iv);
same = DataHelper.eq(plain, d);
System.out.println("Different value test D(E(value)) == value? " + same);
System.out.println();
System.out.println();
long times = 100;
long encrypttime = 0;
long decrypttime = 0;
long maxE = 0;
long minE = 0;
long maxD = 0;
long minD = 0;
byte[] message = new byte[2*1024];
for (int i = 0; i < message.length; i++)
message[i] = (byte)((i%26)+'a');
for (int x = 0; x < times; x++) {
long startencrypt = System.currentTimeMillis();
e = _context.AESEngine().encrypt(message, key, iv);
long endencryptstartdecrypt = System.currentTimeMillis();
d = _context.AESEngine().decrypt(e, key, iv);
long enddecrypt = System.currentTimeMillis();
System.out.print(".");
encrypttime += endencryptstartdecrypt - startencrypt;
decrypttime += enddecrypt - endencryptstartdecrypt;
if (!DataHelper.eq(d, message)) {
System.out.println("Lengths: source [" + message.length + "] dest [" + d.length + "]");
System.out.println("Data: dest [" + DataHelper.toString(d, d.length) + "]");
throw new RuntimeException("Holy crap, decrypted != source message");
}
if ( (minE == 0) && (minD == 0) ) {
minE = endencryptstartdecrypt - startencrypt;
maxE = endencryptstartdecrypt - startencrypt;
minD = enddecrypt - endencryptstartdecrypt;
maxD = enddecrypt - endencryptstartdecrypt;
} else {
if (minE > endencryptstartdecrypt - startencrypt) minE = endencryptstartdecrypt - startencrypt;
if (maxE < endencryptstartdecrypt - startencrypt) maxE = endencryptstartdecrypt - startencrypt;
if (minD > enddecrypt - endencryptstartdecrypt) minD = enddecrypt - endencryptstartdecrypt;
if (maxD < enddecrypt - endencryptstartdecrypt) maxD = enddecrypt - endencryptstartdecrypt;
}
}
System.out.println();
System.out.println("Data size : " + message.length);
System.out.println("Encryption Time Average : " + (encrypttime/times) + "ms\ttotal: " + encrypttime + "ms\tmin: " + minE + "ms\tmax: " + maxE + "ms\tEncryption Bps: " + (times*message.length*1000)/encrypttime);
System.out.println("Decryption Time Average : " + (decrypttime/times) + "ms\ttotal: " + decrypttime + "ms\tmin: " + minD + "ms\tmax: " + maxD + "ms\tDecryption Bps: " + (times*message.length*1000)/decrypttime);
}
}

View File

@ -1,13 +1,14 @@
package net.i2p.crypto;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import net.i2p.data.PublicKey;
@ -25,211 +26,216 @@ import java.util.HashSet;
class ElGamalAESEngineTest {
private final static Log _log = new Log(ElGamalAESEngineTest.class);
public void runRoundtripTest() {
try {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
String msg = "Hello world";
Set toBeDelivered = new HashSet();
SessionKey key = SessionKeyManager.getInstance().getCurrentKey(pubKey);
if (key == null)
key = SessionKeyManager.getInstance().createSession(pubKey);
byte[] encrypted = ElGamalAESEngine.encrypt(msg.getBytes(), pubKey, key, 64);
byte[] decrypted = ElGamalAESEngine.decrypt(encrypted, privKey);
if (decrypted == null)
throw new Exception("Failed to decrypt");
String read = new String(decrypted);
_log.debug("read: " + read);
_log.debug("Match? " + msg.equals(read));
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
private I2PAppContext _context;
public ElGamalAESEngineTest(I2PAppContext ctx) {
_context = ctx;
}
public void runRoundtripTest() {
try {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
String msg = "Hello world";
Set toBeDelivered = new HashSet();
SessionKey key = _context.sessionKeyManager().getCurrentKey(pubKey);
if (key == null)
key = _context.sessionKeyManager().createSession(pubKey);
byte[] encrypted = _context.elGamalAESEngine().encrypt(msg.getBytes(), pubKey, key, 64);
byte[] decrypted = _context.elGamalAESEngine().decrypt(encrypted, privKey);
if (decrypted == null)
throw new Exception("Failed to decrypt");
String read = new String(decrypted);
_log.debug("read: " + read);
_log.debug("Match? " + msg.equals(read));
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
}
public void runLoopTest(int runs) {
try {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
long e0 = 0;
long d0 = 0;
long eTot = 0;
long dTot = 0;
for (int i = 0; i < runs; i++) {
long times[] = runMessage(pubKey, privKey);
_log.debug("E[" + i + "] time: " + times[0] + "ms");
_log.debug("D["+i+"] time: " + times[1] + "ms");
if (i == 0) {
e0 = times[0];
d0 = times[1];
}
eTot += times[0];
dTot += times[1];
}
_log.debug("E average time: " + eTot/runs + "ms");
_log.debug("D average time: " + dTot/runs + "ms");
_log.debug("Total time to send and receive " + (runs) + "Kb: " + (eTot+dTot)+"ms");
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
try {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
long e0 = 0;
long d0 = 0;
long eTot = 0;
long dTot = 0;
for (int i = 0; i < runs; i++) {
long times[] = runMessage(pubKey, privKey);
_log.debug("E[" + i + "] time: " + times[0] + "ms");
_log.debug("D["+i+"] time: " + times[1] + "ms");
if (i == 0) {
e0 = times[0];
d0 = times[1];
}
eTot += times[0];
dTot += times[1];
}
_log.debug("E average time: " + eTot/runs + "ms");
_log.debug("D average time: " + dTot/runs + "ms");
_log.debug("Total time to send and receive " + (runs) + "Kb: " + (eTot+dTot)+"ms");
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
}
private long[] runMessage(PublicKey pubKey, PrivateKey privKey) throws Exception {
byte[] msg = new byte[400];
RandomSource.getInstance().nextBytes(msg);
SessionKey key = SessionKeyManager.getInstance().getCurrentKey(pubKey);
if (key == null)
key = SessionKeyManager.getInstance().createSession(pubKey);
long beforeE = Clock.getInstance().now();
byte[] encrypted = ElGamalAESEngine.encrypt(msg, pubKey, key, 1024);
long afterE = Clock.getInstance().now();
byte[] decrypted = ElGamalAESEngine.decrypt(encrypted, privKey);
long afterD = Clock.getInstance().now();
if (!DataHelper.eq(msg, decrypted)) {
_log.error("WTF, D(E(val)) != val");
return null;
}
long rv[] = new long[2];
rv[0] = afterE - beforeE;
rv[1] = afterD - afterE;
return rv;
byte[] msg = new byte[400];
RandomSource.getInstance().nextBytes(msg);
SessionKey key = _context.sessionKeyManager().getCurrentKey(pubKey);
if (key == null)
key = _context.sessionKeyManager().createSession(pubKey);
long beforeE = Clock.getInstance().now();
byte[] encrypted = _context.elGamalAESEngine().encrypt(msg, pubKey, key, 1024);
long afterE = Clock.getInstance().now();
byte[] decrypted = _context.elGamalAESEngine().decrypt(encrypted, privKey);
long afterD = Clock.getInstance().now();
if (!DataHelper.eq(msg, decrypted)) {
_log.error("WTF, D(E(val)) != val");
return null;
}
long rv[] = new long[2];
rv[0] = afterE - beforeE;
rv[1] = afterD - afterE;
return rv;
}
public void runAESTest() {
try {
SessionKey sessionKey = KeyGenerator.getInstance().generateSessionKey();
Hash h = SHA256Generator.getInstance().calculateHash(sessionKey.getData());
byte iv[] = new byte[16];
System.arraycopy(h.getData(), 0, iv, 0, 16);
String msg = "Hello world";
byte encrypted[] = ElGamalAESEngine.encryptAESBlock(msg.getBytes(), sessionKey, iv, null, null, 64);
_log.debug("** Encryption complete. Beginning decryption");
Set foundTags = new HashSet();
SessionKey foundKey = new SessionKey();
byte decrypted[] = ElGamalAESEngine.decryptAESBlock(encrypted, sessionKey, iv, null, foundTags, foundKey);
if (decrypted == null) throw new Exception("Decryption failed");
String read = new String(decrypted);
_log.debug("read: " + read);
_log.debug("Match? " + msg.equals(read));
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
try {
SessionKey sessionKey = KeyGenerator.getInstance().generateSessionKey();
Hash h = SHA256Generator.getInstance().calculateHash(sessionKey.getData());
byte iv[] = new byte[16];
System.arraycopy(h.getData(), 0, iv, 0, 16);
String msg = "Hello world";
byte encrypted[] = _context.elGamalAESEngine().encryptAESBlock(msg.getBytes(), sessionKey, iv, null, null, 64);
_log.debug("** Encryption complete. Beginning decryption");
Set foundTags = new HashSet();
SessionKey foundKey = new SessionKey();
byte decrypted[] = _context.elGamalAESEngine().decryptAESBlock(encrypted, sessionKey, iv, null, foundTags, foundKey);
if (decrypted == null) throw new Exception("Decryption failed");
String read = new String(decrypted);
_log.debug("read: " + read);
_log.debug("Match? " + msg.equals(read));
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
}
public void runBasicAESTest() {
try {
SessionKey sessionKey = KeyGenerator.getInstance().generateSessionKey();
Hash h = SHA256Generator.getInstance().calculateHash(sessionKey.getData());
byte iv[] = new byte[16];
System.arraycopy(h.getData(), 0, iv, 0, 16);
String msg = "Hello world01234012345678901234501234567890123450123456789012345";
h = SHA256Generator.getInstance().calculateHash(msg.getBytes());
_log.debug("Hash of entire aes block before encryption: \n" + DataHelper.toString(h.getData(), 32));
byte aesEncr[] = AESEngine.getInstance().encrypt(msg.getBytes(), sessionKey, iv);
byte aesDecr[] = AESEngine.getInstance().decrypt(aesEncr, sessionKey, iv);
h = SHA256Generator.getInstance().calculateHash(aesDecr);
_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
if (msg.equals(new String(aesDecr))) {
_log.debug("**AES Basic test passed!\n\n");
}
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
try {
SessionKey sessionKey = KeyGenerator.getInstance().generateSessionKey();
Hash h = SHA256Generator.getInstance().calculateHash(sessionKey.getData());
byte iv[] = new byte[16];
System.arraycopy(h.getData(), 0, iv, 0, 16);
String msg = "Hello world01234012345678901234501234567890123450123456789012345";
h = SHA256Generator.getInstance().calculateHash(msg.getBytes());
_log.debug("Hash of entire aes block before encryption: \n" + DataHelper.toString(h.getData(), 32));
byte aesEncr[] = _context.AESEngine().encrypt(msg.getBytes(), sessionKey, iv);
byte aesDecr[] = _context.AESEngine().decrypt(aesEncr, sessionKey, iv);
h = SHA256Generator.getInstance().calculateHash(aesDecr);
_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
if (msg.equals(new String(aesDecr))) {
_log.debug("**AES Basic test passed!\n\n");
}
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
}
public void runElGamalTest(int numLoops) {
for (int i = 0; i < numLoops; i++) {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey key = KeyGenerator.getInstance().generateSessionKey();
runBasicElGamalTest(key, pubKey, privKey);
}
for (int i = 0; i < numLoops; i++) {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey key = KeyGenerator.getInstance().generateSessionKey();
runBasicElGamalTest(key, pubKey, privKey);
}
}
public void runBasicElGamalTest(SessionKey key, PublicKey pubKey, PrivateKey privKey) {
try {
ByteArrayOutputStream elgSrc = new ByteArrayOutputStream(256);
key.writeBytes(elgSrc);
byte preIV[] = new byte[32];
RandomSource.getInstance().nextBytes(preIV);
elgSrc.write(preIV);
// byte rnd[] = new byte[191];
// RandomSource.getInstance().nextBytes(rnd);
// elgSrc.write(rnd);
elgSrc.flush();
byte elgEncr[] = ElGamalEngine.getInstance().encrypt(elgSrc.toByteArray(), pubKey);
byte elgDecr[] = ElGamalEngine.getInstance().decrypt(elgEncr, privKey);
ByteArrayInputStream bais = new ByteArrayInputStream(elgDecr);
SessionKey nk = new SessionKey();
nk.readBytes(bais);
byte postpreIV[] = new byte[32];
int read = bais.read(postpreIV);
if (read != postpreIV.length) {
// hmm, this can't really happen...
throw new Exception("Somehow ElGamal broke and 256 bytes is less than 32 bytes...");
}
// ignore the next 192 bytes
boolean eq = (DataHelper.eq(preIV, postpreIV) && DataHelper.eq(key, nk));
if (!eq) {
_log.error("elgEncr.length: " + elgEncr.length + " elgDecr.length: " + elgDecr.length);
_log.error("Pre IV.................: " + DataHelper.toString(preIV, 32));
_log.error("Pre IV after decryption: " + DataHelper.toString(postpreIV, 32));
_log.error("SessionKey.................: " + DataHelper.toString(key.getData(), 32));
_log.error("SessionKey after decryption: " + DataHelper.toString(nk.getData(), 32));
_log.error("PublicKey: " + DataHelper.toDecimalString(pubKey.getData(), pubKey.getData().length));
_log.error("PrivateKey: " + DataHelper.toDecimalString(privKey.getData(), privKey.getData().length));
throw new Exception("Not equal!");
} else {
_log.debug("Basic ElG D(E(val)) == val");
}
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
try {
ByteArrayOutputStream elgSrc = new ByteArrayOutputStream(256);
key.writeBytes(elgSrc);
byte preIV[] = new byte[32];
RandomSource.getInstance().nextBytes(preIV);
elgSrc.write(preIV);
// byte rnd[] = new byte[191];
// RandomSource.getInstance().nextBytes(rnd);
// elgSrc.write(rnd);
elgSrc.flush();
byte elgEncr[] = _context.elGamalEngine().encrypt(elgSrc.toByteArray(), pubKey);
byte elgDecr[] = _context.elGamalEngine().decrypt(elgEncr, privKey);
ByteArrayInputStream bais = new ByteArrayInputStream(elgDecr);
SessionKey nk = new SessionKey();
nk.readBytes(bais);
byte postpreIV[] = new byte[32];
int read = bais.read(postpreIV);
if (read != postpreIV.length) {
// hmm, this can't really happen...
throw new Exception("Somehow ElGamal broke and 256 bytes is less than 32 bytes...");
}
// ignore the next 192 bytes
boolean eq = (DataHelper.eq(preIV, postpreIV) && DataHelper.eq(key, nk));
if (!eq) {
_log.error("elgEncr.length: " + elgEncr.length + " elgDecr.length: " + elgDecr.length);
_log.error("Pre IV.................: " + DataHelper.toString(preIV, 32));
_log.error("Pre IV after decryption: " + DataHelper.toString(postpreIV, 32));
_log.error("SessionKey.................: " + DataHelper.toString(key.getData(), 32));
_log.error("SessionKey after decryption: " + DataHelper.toString(nk.getData(), 32));
_log.error("PublicKey: " + DataHelper.toDecimalString(pubKey.getData(), pubKey.getData().length));
_log.error("PrivateKey: " + DataHelper.toDecimalString(privKey.getData(), privKey.getData().length));
throw new Exception("Not equal!");
} else {
_log.debug("Basic ElG D(E(val)) == val");
}
} catch (Exception e) {
_log.error("Error", e);
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
System.exit(0);
}
}
public static void main(String args[]) {
ElGamalAESEngineTest tst = new ElGamalAESEngineTest();
Object o = YKGenerator.class;
try { Thread.sleep(120*1000); } catch (InterruptedException ie) {}
tst.runBasicAESTest();
tst.runAESTest();
tst.runRoundtripTest();
tst.runElGamalTest(2);
// test bug
for (int i = 0; i < 3; i++)
tst.runLoopTest(1);
// test throughput
tst.runLoopTest(5);
net.i2p.stat.SimpleStatDumper.dumpStats(Log.CRIT);
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
I2PAppContext context = new I2PAppContext();
ElGamalAESEngineTest tst = new ElGamalAESEngineTest(context);
Object o = YKGenerator.class;
try { Thread.sleep(120*1000); } catch (InterruptedException ie) {}
tst.runBasicAESTest();
tst.runAESTest();
tst.runRoundtripTest();
tst.runElGamalTest(2);
// test bug
for (int i = 0; i < 3; i++)
tst.runLoopTest(1);
// test throughput
tst.runLoopTest(5);
net.i2p.stat.SimpleStatDumper.dumpStats(context, Log.CRIT);
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
}
}

View File

@ -1,96 +1,98 @@
package net.i2p.crypto;
/*
/*
* Copyright (c) 2003, TheCrypto
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the TheCrypto may be used to endorse or promote
* products derived from this software without specific prior written
* - Neither the name of the TheCrypto may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import net.i2p.data.DataHelper;
import net.i2p.data.PrivateKey;
import net.i2p.data.PublicKey;
import net.i2p.I2PAppContext;
public class ElGamalBench {
public static void main(String args[]) {
int times = 100;
long keygentime = 0;
long encrypttime = 0;
long decrypttime = 0;
long maxKey = 0;
long minKey = 0;
long maxE = 0;
long minE = 0;
long maxD = 0;
long minD = 0;
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
byte[] message = new byte[222];
for (int i = 0; i < message.length; i++)
message[i] = (byte)((i%26)+'a');
for (int x = 0; x < times; x++) {
long startkeys = System.currentTimeMillis();
keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubkey = (PublicKey)keys[0];
PrivateKey privkey = (PrivateKey)keys[1];
long endkeys = System.currentTimeMillis();
long startencrypt = System.currentTimeMillis();
byte[] e = ElGamalEngine.getInstance().encrypt(message, pubkey);
long endencryptstartdecrypt = System.currentTimeMillis();
byte[] d = ElGamalEngine.getInstance().decrypt(e, privkey);
long enddecrypt = System.currentTimeMillis();
System.out.print(".");
keygentime += endkeys - startkeys;
encrypttime += endencryptstartdecrypt - startencrypt;
decrypttime += enddecrypt - endencryptstartdecrypt;
if (!DataHelper.eq(d, message)) {
System.out.println("Lengths: source [" + message.length + "] dest [" + d.length + "]");
byte hash1[] = SHA256Generator.getInstance().calculateHash(message).getData();
byte hash2[] = SHA256Generator.getInstance().calculateHash(d).getData();
System.out.println("Hashes: source [" + DataHelper.toString(hash1, hash1.length) + "] dest [" + DataHelper.toString(hash2, hash2.length) + "]");
throw new RuntimeException("Holy crap, decrypted != source message");
}
if ( (minKey == 0) && (minE == 0) && (minD == 0) ) {
minKey = endkeys - startkeys;
maxKey = endkeys - startkeys;
minE = endencryptstartdecrypt - startencrypt;
maxE = endencryptstartdecrypt - startencrypt;
minD = enddecrypt - endencryptstartdecrypt;
maxD = enddecrypt - endencryptstartdecrypt;
} else {
if (minKey > endkeys - startkeys) minKey = endkeys - startkeys;
if (maxKey < endkeys - startkeys) maxKey = endkeys - startkeys;
if (minE > endencryptstartdecrypt - startencrypt) minE = endencryptstartdecrypt - startencrypt;
if (maxE < endencryptstartdecrypt - startencrypt) maxE = endencryptstartdecrypt - startencrypt;
if (minD > enddecrypt - endencryptstartdecrypt) minD = enddecrypt - endencryptstartdecrypt;
if (maxD < enddecrypt - endencryptstartdecrypt) maxD = enddecrypt - endencryptstartdecrypt;
}
}
System.out.println();
System.out.println("Key Generation Time Average: " + (keygentime/times) + "\ttotal: " + keygentime + "\tmin: " + minKey + "\tmax: " + maxKey + "\tKeygen/second: " + (keygentime == 0 ? "NaN" : ""+(times*1000)/keygentime));
System.out.println("Encryption Time Average : " + (encrypttime/times) + "\ttotal: " + encrypttime + "\tmin: " + minE + "\tmax: " + maxE + "\tEncryption Bps: " + (times*message.length*1000)/encrypttime);
System.out.println("Decryption Time Average : " + (decrypttime/times) + "\ttotal: " + decrypttime + "\tmin: " + minD + "\tmax: " + maxD + "\tDecryption Bps: " + (times*message.length*1000)/decrypttime);
}
private static I2PAppContext _context = new I2PAppContext();
public static void main(String args[]) {
int times = 100;
long keygentime = 0;
long encrypttime = 0;
long decrypttime = 0;
long maxKey = 0;
long minKey = 0;
long maxE = 0;
long minE = 0;
long maxD = 0;
long minD = 0;
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
byte[] message = new byte[222];
for (int i = 0; i < message.length; i++)
message[i] = (byte)((i%26)+'a');
for (int x = 0; x < times; x++) {
long startkeys = System.currentTimeMillis();
keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubkey = (PublicKey)keys[0];
PrivateKey privkey = (PrivateKey)keys[1];
long endkeys = System.currentTimeMillis();
long startencrypt = System.currentTimeMillis();
byte[] e = _context.elGamalEngine().encrypt(message, pubkey);
long endencryptstartdecrypt = System.currentTimeMillis();
byte[] d = _context.elGamalEngine().decrypt(e, privkey);
long enddecrypt = System.currentTimeMillis();
System.out.print(".");
keygentime += endkeys - startkeys;
encrypttime += endencryptstartdecrypt - startencrypt;
decrypttime += enddecrypt - endencryptstartdecrypt;
if (!DataHelper.eq(d, message)) {
System.out.println("Lengths: source [" + message.length + "] dest [" + d.length + "]");
byte hash1[] = SHA256Generator.getInstance().calculateHash(message).getData();
byte hash2[] = SHA256Generator.getInstance().calculateHash(d).getData();
System.out.println("Hashes: source [" + DataHelper.toString(hash1, hash1.length) + "] dest [" + DataHelper.toString(hash2, hash2.length) + "]");
throw new RuntimeException("Holy crap, decrypted != source message");
}
if ( (minKey == 0) && (minE == 0) && (minD == 0) ) {
minKey = endkeys - startkeys;
maxKey = endkeys - startkeys;
minE = endencryptstartdecrypt - startencrypt;
maxE = endencryptstartdecrypt - startencrypt;
minD = enddecrypt - endencryptstartdecrypt;
maxD = enddecrypt - endencryptstartdecrypt;
} else {
if (minKey > endkeys - startkeys) minKey = endkeys - startkeys;
if (maxKey < endkeys - startkeys) maxKey = endkeys - startkeys;
if (minE > endencryptstartdecrypt - startencrypt) minE = endencryptstartdecrypt - startencrypt;
if (maxE < endencryptstartdecrypt - startencrypt) maxE = endencryptstartdecrypt - startencrypt;
if (minD > enddecrypt - endencryptstartdecrypt) minD = enddecrypt - endencryptstartdecrypt;
if (maxD < enddecrypt - endencryptstartdecrypt) maxD = enddecrypt - endencryptstartdecrypt;
}
}
System.out.println();
System.out.println("Key Generation Time Average: " + (keygentime/times) + "\ttotal: " + keygentime + "\tmin: " + minKey + "\tmax: " + maxKey + "\tKeygen/second: " + (keygentime == 0 ? "NaN" : ""+(times*1000)/keygentime));
System.out.println("Encryption Time Average : " + (encrypttime/times) + "\ttotal: " + encrypttime + "\tmin: " + minE + "\tmax: " + maxE + "\tEncryption Bps: " + (times*message.length*1000)/encrypttime);
System.out.println("Decryption Time Average : " + (decrypttime/times) + "\ttotal: " + decrypttime + "\tmin: " + minD + "\tmax: " + maxD + "\tDecryption Bps: " + (times*message.length*1000)/decrypttime);
}
}

View File

@ -1,9 +1,9 @@
package net.i2p.crypto;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
@ -16,6 +16,7 @@ import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import net.i2p.I2PAppContext;
import java.util.HashSet;
import java.util.Set;
@ -24,383 +25,384 @@ import java.util.Set;
*
* session key management unit tests:
*
* Run tagsIncluded useTag rekey
* Run tagsIncluded useTag rekey
* // no sessions
* 1 no no no
* 2 no no no
* 1 no no no
* 2 no no no
* // session
* 3 yes (2) no no
* 4 no yes no
* 5 yes (2) yes no
* 6 no yes no
* 7 no yes no
* 3 yes (2) no no
* 4 no yes no
* 5 yes (2) yes no
* 6 no yes no
* 7 no yes no
* // rekeying
* 8 yes (2) no no
* 9 no yes no
* 10 yes (2) yes yes
* 11 no yes no
* 12 no yes no
* 8 yes (2) no no
* 9 no yes no
* 10 yes (2) yes yes
* 11 no yes no
* 12 no yes no
* // long session
* 13-1000 20 tags every 10 messages, rekey every 50
* 13-1000 20 tags every 10 messages, rekey every 50
*/
public class SessionEncryptionTest {
private final static Log _log = new Log(SessionEncryptionTest.class);
private static I2PAppContext _context = new I2PAppContext();
public static void main(String args[]) {
SessionEncryptionTest test = new SessionEncryptionTest();
try {
//test.testNoSessions();
//test.testSessions();
//test.testRekeying();
test.testLongSession();
} catch (Throwable t) {
_log.error("Error running tests", t);
}
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
SessionEncryptionTest test = new SessionEncryptionTest();
try {
//test.testNoSessions();
//test.testSessions();
//test.testRekeying();
test.testLongSession();
} catch (Throwable t) {
_log.error("Error running tests", t);
}
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
}
/**
* Run tagsIncluded useTag rekey
* 1 no no no
* 2 no no no
* Run tagsIncluded useTag rekey
* 1 no no no
* 2 no no no
*/
public void testNoSessions() throws Exception {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = SessionKeyManager.getInstance().createSession(pubKey);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte emsg1[] = ElGamalAESEngine.encrypt(msg1, pubKey, curKey, 64);
byte dmsg1[] = ElGamalAESEngine.decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: No sessions msg 1");
else
_log.error("FAILED: No sessions msg 1");
byte emsg2[] = ElGamalAESEngine.encrypt(msg2, pubKey, curKey, 64);
byte dmsg2[] = ElGamalAESEngine.decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: No sessions msg 2");
else
_log.error("FAILED: No sessions msg 2");
}
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = _context.sessionKeyManager().createSession(pubKey);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte emsg1[] = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, 64);
byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: No sessions msg 1");
else
_log.error("FAILED: No sessions msg 1");
byte emsg2[] = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, 64);
byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: No sessions msg 2");
else
_log.error("FAILED: No sessions msg 2");
}
/**
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes no
* 4 no yes no
* 5 no yes no
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes no
* 4 no yes no
* 5 no yes no
*/
public void testSessions() throws Exception {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = SessionKeyManager.getInstance().createSession(pubKey);
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet firstTags = new HashSet();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet secondTags = new HashSet();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte[] msg3 = "msg 3".getBytes();
byte[] msg4 = "msg 4".getBytes();
byte[] msg5 = "msg 5".getBytes();
byte emsg1[] = ElGamalAESEngine.encrypt(msg1, pubKey, curKey, firstTags, 64);
byte dmsg1[] = ElGamalAESEngine.decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: Sessions msg 1");
else {
_log.error("FAILED: Sessions msg 1");
return;
}
SessionKeyManager.getInstance().tagsDelivered(pubKey, curKey, firstTags);
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
SessionTag curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 2");
return;
}
byte emsg2[] = ElGamalAESEngine.encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte dmsg2[] = ElGamalAESEngine.decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: Sessions msg 2");
else {
_log.error("FAILED: Sessions msg 2");
return;
}
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 3");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 3");
return;
}
byte emsg3[] = ElGamalAESEngine.encrypt(msg3, pubKey, curKey, secondTags, curTag, 64);
byte dmsg3[] = ElGamalAESEngine.decrypt(emsg3, privKey);
if (DataHelper.eq(dmsg3, msg3))
_log.info("PASSED: Sessions msg 3");
else {
_log.error("FAILED: Sessions msg 3");
return;
}
SessionKeyManager.getInstance().tagsDelivered(pubKey, curKey, secondTags);
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 4");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 4");
return;
}
byte emsg4[] = ElGamalAESEngine.encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte dmsg4[] = ElGamalAESEngine.decrypt(emsg4, privKey);
if (DataHelper.eq(dmsg4, msg4))
_log.info("PASSED: Sessions msg 4");
else {
_log.error("FAILED: Sessions msg 4");
return;
}
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 5");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 5");
return;
}
byte emsg5[] = ElGamalAESEngine.encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte dmsg5[] = ElGamalAESEngine.decrypt(emsg5, privKey);
if (DataHelper.eq(dmsg5, msg5))
_log.info("PASSED: Sessions msg 5");
else {
_log.error("FAILED: Sessions msg 5");
return;
}
}
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = _context.sessionKeyManager().createSession(pubKey);
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet firstTags = new HashSet();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet secondTags = new HashSet();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte[] msg3 = "msg 3".getBytes();
byte[] msg4 = "msg 4".getBytes();
byte[] msg5 = "msg 5".getBytes();
byte emsg1[] = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, 64);
byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: Sessions msg 1");
else {
_log.error("FAILED: Sessions msg 1");
return;
}
_context.sessionKeyManager().tagsDelivered(pubKey, curKey, firstTags);
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 2");
return;
}
byte emsg2[] = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: Sessions msg 2");
else {
_log.error("FAILED: Sessions msg 2");
return;
}
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 3");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 3");
return;
}
byte emsg3[] = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, 64);
byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey);
if (DataHelper.eq(dmsg3, msg3))
_log.info("PASSED: Sessions msg 3");
else {
_log.error("FAILED: Sessions msg 3");
return;
}
_context.sessionKeyManager().tagsDelivered(pubKey, curKey, secondTags);
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 4");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 4");
return;
}
byte emsg4[] = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey);
if (DataHelper.eq(dmsg4, msg4))
_log.info("PASSED: Sessions msg 4");
else {
_log.error("FAILED: Sessions msg 4");
return;
}
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 5");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 5");
return;
}
byte emsg5[] = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey);
if (DataHelper.eq(dmsg5, msg5))
_log.info("PASSED: Sessions msg 5");
else {
_log.error("FAILED: Sessions msg 5");
return;
}
}
/**
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes yes
* 4 no yes no
* 5 no yes no
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes yes
* 4 no yes no
* 5 no yes no
*/
public void testRekeying() throws Exception {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = SessionKeyManager.getInstance().createSession(pubKey);
SessionKey nextKey = KeyGenerator.getInstance().generateSessionKey();
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet firstTags = new HashSet();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet secondTags = new HashSet();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte[] msg3 = "msg 3".getBytes();
byte[] msg4 = "msg 4".getBytes();
byte[] msg5 = "msg 5".getBytes();
byte emsg1[] = ElGamalAESEngine.encrypt(msg1, pubKey, curKey, firstTags, 64);
byte dmsg1[] = ElGamalAESEngine.decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: Sessions msg 1");
else {
_log.error("FAILED: Sessions msg 1");
return;
}
SessionKeyManager.getInstance().tagsDelivered(pubKey, curKey, firstTags);
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
SessionTag curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 2");
return;
}
byte emsg2[] = ElGamalAESEngine.encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte dmsg2[] = ElGamalAESEngine.decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: Sessions msg 2");
else {
_log.error("FAILED: Sessions msg 2");
return;
}
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 3");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 3");
return;
}
byte emsg3[] = ElGamalAESEngine.encrypt(msg3, pubKey, curKey, secondTags, curTag, nextKey, 64);
byte dmsg3[] = ElGamalAESEngine.decrypt(emsg3, privKey);
if (DataHelper.eq(dmsg3, msg3))
_log.info("PASSED: Sessions msg 3");
else {
_log.error("FAILED: Sessions msg 3");
return;
}
SessionKeyManager.getInstance().tagsDelivered(pubKey, nextKey, secondTags); // note nextKey not curKey
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 4");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 4");
return;
}
byte emsg4[] = ElGamalAESEngine.encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte dmsg4[] = ElGamalAESEngine.decrypt(emsg4, privKey);
if (DataHelper.eq(dmsg4, msg4))
_log.info("PASSED: Sessions msg 4");
else {
_log.error("FAILED: Sessions msg 4");
return;
}
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 5");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 5");
return;
}
byte emsg5[] = ElGamalAESEngine.encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte dmsg5[] = ElGamalAESEngine.decrypt(emsg5, privKey);
if (DataHelper.eq(dmsg5, msg5))
_log.info("PASSED: Sessions msg 5");
else {
_log.error("FAILED: Sessions msg 5");
return;
}
}
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = _context.sessionKeyManager().createSession(pubKey);
SessionKey nextKey = KeyGenerator.getInstance().generateSessionKey();
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet firstTags = new HashSet();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet secondTags = new HashSet();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = "msg 1".getBytes();
byte[] msg2 = "msg 2".getBytes();
byte[] msg3 = "msg 3".getBytes();
byte[] msg4 = "msg 4".getBytes();
byte[] msg5 = "msg 5".getBytes();
byte emsg1[] = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, 64);
byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey);
if (DataHelper.eq(dmsg1, msg1))
_log.info("PASSED: Sessions msg 1");
else {
_log.error("FAILED: Sessions msg 1");
return;
}
_context.sessionKeyManager().tagsDelivered(pubKey, curKey, firstTags);
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 2");
return;
}
byte emsg2[] = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey);
if (DataHelper.eq(dmsg2, msg2))
_log.info("PASSED: Sessions msg 2");
else {
_log.error("FAILED: Sessions msg 2");
return;
}
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 3");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 3");
return;
}
byte emsg3[] = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, nextKey, 64);
byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey);
if (DataHelper.eq(dmsg3, msg3))
_log.info("PASSED: Sessions msg 3");
else {
_log.error("FAILED: Sessions msg 3");
return;
}
_context.sessionKeyManager().tagsDelivered(pubKey, nextKey, secondTags); // note nextKey not curKey
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 4");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 4");
return;
}
byte emsg4[] = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey);
if (DataHelper.eq(dmsg4, msg4))
_log.info("PASSED: Sessions msg 4");
else {
_log.error("FAILED: Sessions msg 4");
return;
}
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
if (curTag == null) {
_log.error("Not able to consume next tag for message 5");
return;
}
if (curKey == null) {
_log.error("Not able to consume next KEY for message 5");
return;
}
byte emsg5[] = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey);
if (DataHelper.eq(dmsg5, msg5))
_log.info("PASSED: Sessions msg 5");
else {
_log.error("FAILED: Sessions msg 5");
return;
}
}
/**
* 20 tags every 10 messages, rekey every 50
* 20 tags every 10 messages, rekey every 50
*/
public void testLongSession() throws Exception {
int num = 1000;
long start = Clock.getInstance().now();
testLongSession(num);
long end = Clock.getInstance().now();
long time = end - start;
float msEach = (float)num / time;
_log.error("Test long session duration: " + num + " messages in " + time + "ms (or " + msEach + "ms each)");
int num = 1000;
long start = Clock.getInstance().now();
testLongSession(num);
long end = Clock.getInstance().now();
long time = end - start;
float msEach = (float)num / time;
_log.error("Test long session duration: " + num + " messages in " + time + "ms (or " + msEach + "ms each)");
}
public void testLongSession(int numMsgs) throws Exception {
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = SessionKeyManager.getInstance().createSession(pubKey);
for (int i = 0; i < numMsgs; i++) {
Set tags = null;
SessionKey nextKey = null;
curKey = SessionKeyManager.getInstance().getCurrentKey(pubKey);
SessionTag curTag = SessionKeyManager.getInstance().consumeNextAvailableTag(pubKey, curKey);
int availTags = SessionKeyManager.getInstance().getAvailableTags(pubKey, curKey);
if ((availTags < 1)) {
tags = generateNewTags(50);
_log.info("Generating new tags");
} else {
_log.info("Tags already available: " + availTags + " curTag: " + curTag);
}
if (i % 50 == 0)
nextKey = KeyGenerator.getInstance().generateSessionKey();
byte[] msg = ("msg " + i).getBytes();
byte emsg[] = ElGamalAESEngine.encrypt(msg, pubKey, curKey, tags, curTag, nextKey, 64);
byte dmsg[] = ElGamalAESEngine.decrypt(emsg, privKey);
if (DataHelper.eq(dmsg, msg))
_log.info("PASSED: Long session msg " + i);
else {
_log.error("FAILED: Long session msg " + i);
return;
}
if ( (tags != null) && (tags.size() > 0) ) {
if (nextKey == null) {
SessionKeyManager.getInstance().tagsDelivered(pubKey, curKey, tags);
} else {
SessionKeyManager.getInstance().tagsDelivered(pubKey, nextKey, tags);
}
}
}
Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey)keys[0];
PrivateKey privKey = (PrivateKey)keys[1];
SessionKey curKey = _context.sessionKeyManager().createSession(pubKey);
for (int i = 0; i < numMsgs; i++) {
Set tags = null;
SessionKey nextKey = null;
curKey = _context.sessionKeyManager().getCurrentKey(pubKey);
SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey);
int availTags = _context.sessionKeyManager().getAvailableTags(pubKey, curKey);
if ((availTags < 1)) {
tags = generateNewTags(50);
_log.info("Generating new tags");
} else {
_log.info("Tags already available: " + availTags + " curTag: " + curTag);
}
if (i % 50 == 0)
nextKey = KeyGenerator.getInstance().generateSessionKey();
byte[] msg = ("msg " + i).getBytes();
byte emsg[] = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, tags, curTag, nextKey, 64);
byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey);
if (DataHelper.eq(dmsg, msg))
_log.info("PASSED: Long session msg " + i);
else {
_log.error("FAILED: Long session msg " + i);
return;
}
if ( (tags != null) && (tags.size() > 0) ) {
if (nextKey == null) {
_context.sessionKeyManager().tagsDelivered(pubKey, curKey, tags);
} else {
_context.sessionKeyManager().tagsDelivered(pubKey, nextKey, tags);
}
}
}
}
private Set generateNewTags(int numTags) {
Set tags = new HashSet(numTags);
for (int i = 0; i < numTags; i++)
tags.add(new SessionTag(true));
return tags;
Set tags = new HashSet(numTags);
for (int i = 0; i < numTags; i++)
tags.add(new SessionTag(true));
return tags;
}
}

View File

@ -15,6 +15,7 @@ import java.io.InputStream;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataStructure;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/**
* Utility class for wrapping data structure tests
@ -23,6 +24,7 @@ import net.i2p.util.Log;
*/
public abstract class StructureTest implements TestDataGenerator, TestDataPrinter {
private static final Log _log = new Log(StructureTest.class);
protected static I2PAppContext _context = I2PAppContext.getGlobalContext();
public abstract DataStructure createDataStructure() throws DataFormatException;
public abstract DataStructure createStructureToRead();