From 2e3fd0abf2e1030dea9f8aa3c82967d771c01caf Mon Sep 17 00:00:00 2001 From: jrandom <jrandom> Date: Thu, 8 Apr 2004 04:54:58 +0000 Subject: [PATCH] great renaming (cont.) --- .../java/test/net/i2p/crypto/AES256Bench.java | 138 ++++++ core/java/test/net/i2p/crypto/DSABench.java | 92 ++++ .../net/i2p/crypto/ElGamalAESEngineTest.java | 235 ++++++++++ .../test/net/i2p/crypto/ElGamalBench.java | 96 +++++ .../java/test/net/i2p/crypto/SHA256Bench.java | 99 +++++ .../net/i2p/crypto/SessionEncryptionTest.java | 406 ++++++++++++++++++ .../test/net/i2p/data/AbuseReasonTest.java | 30 ++ .../test/net/i2p/data/AbuseSeverityTest.java | 30 ++ core/java/test/net/i2p/data/BooleanTest.java | 59 +++ .../test/net/i2p/data/CertificateTest.java | 34 ++ .../i2p/data/CreateLeaseSetMessageTest.java | 37 ++ .../i2p/data/CreateSessionMessageTest.java | 31 ++ core/java/test/net/i2p/data/DateTest.java | 60 +++ .../test/net/i2p/data/DestinationTest.java | 38 ++ .../i2p/data/DestroySessionMessageTest.java | 31 ++ .../net/i2p/data/DisconnectMessageTest.java | 30 ++ core/java/test/net/i2p/data/HashTest.java | 33 ++ core/java/test/net/i2p/data/LeaseSetTest.java | 38 ++ core/java/test/net/i2p/data/LeaseTest.java | 41 ++ core/java/test/net/i2p/data/MappingTest.java | 64 +++ .../java/test/net/i2p/data/MessageIdTest.java | 30 ++ .../i2p/data/MessagePayloadMessageTest.java | 56 +++ .../i2p/data/MessageStatusMessageTest.java | 35 ++ core/java/test/net/i2p/data/PayloadTest.java | 65 +++ .../test/net/i2p/data/PrivateKeyTest.java | 33 ++ .../java/test/net/i2p/data/PublicKeyTest.java | 33 ++ .../data/ReceiveMessageBeginMessageTest.java | 33 ++ .../data/ReceiveMessageEndMessageTest.java | 33 ++ .../net/i2p/data/ReportAbuseMessageTest.java | 37 ++ .../i2p/data/RequestLeaseSetMessageTest.java | 38 ++ .../test/net/i2p/data/RouterAddressTest.java | 42 ++ .../test/net/i2p/data/RouterIdentityTest.java | 38 ++ .../test/net/i2p/data/RouterInfoTest.java | 85 ++++ .../net/i2p/data/SendMessageMessageTest.java | 56 +++ .../test/net/i2p/data/SessionConfigTest.java | 42 ++ .../java/test/net/i2p/data/SessionIdTest.java | 30 ++ .../test/net/i2p/data/SessionKeyTest.java | 33 ++ .../i2p/data/SessionStatusMessageTest.java | 32 ++ .../java/test/net/i2p/data/SignatureTest.java | 33 ++ .../net/i2p/data/SigningPrivateKeyTest.java | 33 ++ .../net/i2p/data/SigningPublicKeyTest.java | 33 ++ core/java/test/net/i2p/data/StringTest.java | 59 +++ .../java/test/net/i2p/data/StructureTest.java | 60 +++ core/java/test/net/i2p/data/TestData.java | 150 +++++++ .../test/net/i2p/data/TestDataGenerator.java | 16 + .../test/net/i2p/data/TestDataPrinter.java | 18 + core/java/test/net/i2p/data/TunnelIdTest.java | 30 ++ .../net/i2p/data/UnsignedIntegerTest.java | 59 +++ 48 files changed, 2864 insertions(+) create mode 100644 core/java/test/net/i2p/crypto/AES256Bench.java create mode 100644 core/java/test/net/i2p/crypto/DSABench.java create mode 100644 core/java/test/net/i2p/crypto/ElGamalAESEngineTest.java create mode 100644 core/java/test/net/i2p/crypto/ElGamalBench.java create mode 100644 core/java/test/net/i2p/crypto/SHA256Bench.java create mode 100644 core/java/test/net/i2p/crypto/SessionEncryptionTest.java create mode 100644 core/java/test/net/i2p/data/AbuseReasonTest.java create mode 100644 core/java/test/net/i2p/data/AbuseSeverityTest.java create mode 100644 core/java/test/net/i2p/data/BooleanTest.java create mode 100644 core/java/test/net/i2p/data/CertificateTest.java create mode 100644 core/java/test/net/i2p/data/CreateLeaseSetMessageTest.java create mode 100644 core/java/test/net/i2p/data/CreateSessionMessageTest.java create mode 100644 core/java/test/net/i2p/data/DateTest.java create mode 100644 core/java/test/net/i2p/data/DestinationTest.java create mode 100644 core/java/test/net/i2p/data/DestroySessionMessageTest.java create mode 100644 core/java/test/net/i2p/data/DisconnectMessageTest.java create mode 100644 core/java/test/net/i2p/data/HashTest.java create mode 100644 core/java/test/net/i2p/data/LeaseSetTest.java create mode 100644 core/java/test/net/i2p/data/LeaseTest.java create mode 100644 core/java/test/net/i2p/data/MappingTest.java create mode 100644 core/java/test/net/i2p/data/MessageIdTest.java create mode 100644 core/java/test/net/i2p/data/MessagePayloadMessageTest.java create mode 100644 core/java/test/net/i2p/data/MessageStatusMessageTest.java create mode 100644 core/java/test/net/i2p/data/PayloadTest.java create mode 100644 core/java/test/net/i2p/data/PrivateKeyTest.java create mode 100644 core/java/test/net/i2p/data/PublicKeyTest.java create mode 100644 core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java create mode 100644 core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java create mode 100644 core/java/test/net/i2p/data/ReportAbuseMessageTest.java create mode 100644 core/java/test/net/i2p/data/RequestLeaseSetMessageTest.java create mode 100644 core/java/test/net/i2p/data/RouterAddressTest.java create mode 100644 core/java/test/net/i2p/data/RouterIdentityTest.java create mode 100644 core/java/test/net/i2p/data/RouterInfoTest.java create mode 100644 core/java/test/net/i2p/data/SendMessageMessageTest.java create mode 100644 core/java/test/net/i2p/data/SessionConfigTest.java create mode 100644 core/java/test/net/i2p/data/SessionIdTest.java create mode 100644 core/java/test/net/i2p/data/SessionKeyTest.java create mode 100644 core/java/test/net/i2p/data/SessionStatusMessageTest.java create mode 100644 core/java/test/net/i2p/data/SignatureTest.java create mode 100644 core/java/test/net/i2p/data/SigningPrivateKeyTest.java create mode 100644 core/java/test/net/i2p/data/SigningPublicKeyTest.java create mode 100644 core/java/test/net/i2p/data/StringTest.java create mode 100644 core/java/test/net/i2p/data/StructureTest.java create mode 100644 core/java/test/net/i2p/data/TestData.java create mode 100644 core/java/test/net/i2p/data/TestDataGenerator.java create mode 100644 core/java/test/net/i2p/data/TestDataPrinter.java create mode 100644 core/java/test/net/i2p/data/TunnelIdTest.java create mode 100644 core/java/test/net/i2p/data/UnsignedIntegerTest.java diff --git a/core/java/test/net/i2p/crypto/AES256Bench.java b/core/java/test/net/i2p/crypto/AES256Bench.java new file mode 100644 index 0000000000..05718e4f26 --- /dev/null +++ b/core/java/test/net/i2p/crypto/AES256Bench.java @@ -0,0 +1,138 @@ +package net.i2p.crypto; + +/* + * Copyright (c) 2003, TheCrypto + * All rights reserved. + * + * 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 + * 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 + * 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 + * 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 + * POSSIBILITY OF SUCH DAMAGE. + */ + +import net.i2p.data.SessionKey; +import net.i2p.data.DataHelper; + +public class AES256Bench { + + 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); + } +} + diff --git a/core/java/test/net/i2p/crypto/DSABench.java b/core/java/test/net/i2p/crypto/DSABench.java new file mode 100644 index 0000000000..5d29e1d073 --- /dev/null +++ b/core/java/test/net/i2p/crypto/DSABench.java @@ -0,0 +1,92 @@ +package net.i2p.crypto; + +/* + * Copyright (c) 2003, TheCrypto + * All rights reserved. + * + * 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 + * 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 + * 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 + * 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 + * POSSIBILITY OF SUCH DAMAGE. + */ + +import net.i2p.data.Signature; +import net.i2p.data.SigningPrivateKey; +import net.i2p.data.SigningPublicKey; + +public class DSABench { + public static void main(String args[]) { + int times = 100; + long keygentime = 0; + long signtime = 0; + long verifytime = 0; + long maxKey = 0; + long minKey = 0; + long maxS = 0; + long minS = 0; + long maxV = 0; + long minV = 0; + Object[] keys = KeyGenerator.getInstance().generateSigningKeypair(); + byte[] message = new byte[32+32]; + 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().generateSigningKeypair(); + SigningPublicKey pubkey = (SigningPublicKey)keys[0]; + SigningPrivateKey privkey = (SigningPrivateKey)keys[1]; + long endkeys = System.currentTimeMillis(); + long startsign = System.currentTimeMillis(); + Signature s = DSAEngine.getInstance().sign(message, privkey); + long endsignstartverify = System.currentTimeMillis(); + boolean v = DSAEngine.getInstance().verifySignature(s, message, pubkey); + long endverify = System.currentTimeMillis(); + System.out.print("."); + keygentime += endkeys - startkeys; + signtime += endsignstartverify - startsign; + verifytime += endverify - endsignstartverify; + if (!v) { + throw new RuntimeException("Holy crap, did not verify"); + } + if ( (minKey == 0) && (minS == 0) && (minV == 0) ) { + minKey = endkeys - startkeys; + maxKey = endkeys - startkeys; + minS = endsignstartverify - startsign; + maxS = endsignstartverify - startsign; + minV = endverify - endsignstartverify; + maxV = endverify - endsignstartverify; + } else { + if (minKey > endkeys - startkeys) minKey = endkeys - startkeys; + if (maxKey < endkeys - startkeys) maxKey = endkeys - startkeys; + if (minS > endsignstartverify - startsign) minS = endsignstartverify - startsign; + if (maxS < endsignstartverify - startsign) maxS = endsignstartverify - startsign; + if (minV > endverify - endsignstartverify) minV = endverify - endsignstartverify; + if (maxV < endverify - endsignstartverify) maxV = endverify - endsignstartverify; + } + } + 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("Signing Time Average : " + (signtime/times) + "\ttotal: " + signtime + "\tmin: " + minS + "\tmax: " + maxS + "\tSigning Bps: " + (times*message.length*1000)/signtime); + System.out.println("Verification Time Average : " + (verifytime/times) + "\ttotal: " + verifytime + "\tmin: " + minV + "\tmax: " + maxV + "\tDecryption Bps: " + (times*message.length*1000)/verifytime); + } +} + diff --git a/core/java/test/net/i2p/crypto/ElGamalAESEngineTest.java b/core/java/test/net/i2p/crypto/ElGamalAESEngineTest.java new file mode 100644 index 0000000000..afe2548aa4 --- /dev/null +++ b/core/java/test/net/i2p/crypto/ElGamalAESEngineTest.java @@ -0,0 +1,235 @@ +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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.Hash; +import net.i2p.data.SessionKey; +import net.i2p.data.PublicKey; +import net.i2p.data.PrivateKey; +import net.i2p.data.DataHelper; +import net.i2p.util.RandomSource; +import net.i2p.util.Log; +import net.i2p.util.Clock; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import java.util.Set; +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); + } + } + + 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); + } + } + + 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; + } + + 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); + } + } + + 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); + } + } + + 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); + } + } + + 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); + } + } + + 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) {} + } +} diff --git a/core/java/test/net/i2p/crypto/ElGamalBench.java b/core/java/test/net/i2p/crypto/ElGamalBench.java new file mode 100644 index 0000000000..64ca0aa845 --- /dev/null +++ b/core/java/test/net/i2p/crypto/ElGamalBench.java @@ -0,0 +1,96 @@ +package net.i2p.crypto; + +/* + * Copyright (c) 2003, TheCrypto + * All rights reserved. + * + * 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 + * 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 + * 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 + * 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 + * POSSIBILITY OF SUCH DAMAGE. + */ + +import net.i2p.data.DataHelper; +import net.i2p.data.PrivateKey; +import net.i2p.data.PublicKey; + +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); + } +} + diff --git a/core/java/test/net/i2p/crypto/SHA256Bench.java b/core/java/test/net/i2p/crypto/SHA256Bench.java new file mode 100644 index 0000000000..05527a0e22 --- /dev/null +++ b/core/java/test/net/i2p/crypto/SHA256Bench.java @@ -0,0 +1,99 @@ +package net.i2p.crypto; + +/* + * Copyright (c) 2003, TheCrypto + * All rights reserved. + * + * 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 + * 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 + * 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 + * 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 + * POSSIBILITY OF SUCH DAMAGE. + */ + +import net.i2p.data.Hash; + +public class SHA256Bench { + public static void main(String args[]) { + Hash asdfs = SHA256Generator.getInstance().calculateHash("qwerty".getBytes()); + + int times = 100; + long shorttime = 0; + long medtime = 0; + long longtime = 0; + long minShort = 0; + long maxShort = 0; + long minMed = 0; + long maxMed = 0; + long minLong = 0; + long maxLong = 0; + byte[] smess = new String("abc").getBytes(); + StringBuffer buf = new StringBuffer(); + for (int x = 0; x < 10*1024; x++) { + buf.append("a"); + } + byte[] mmess = buf.toString().getBytes(); // new String("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").getBytes(); + buf = new StringBuffer(); + for (int x = 0; x < 1000000; x++) { + buf.append("a"); + } + byte[] lmess = buf.toString().getBytes(); + // warm up the engines + SHA256Generator.getInstance().calculateHash(smess); + SHA256Generator.getInstance().calculateHash(mmess); + SHA256Generator.getInstance().calculateHash(lmess); + // now do it + for (int x = 0; x < times; x++) { + long startshort = System.currentTimeMillis(); + Hash s = SHA256Generator.getInstance().calculateHash(smess); + long endshortstartmed = System.currentTimeMillis(); + Hash m = SHA256Generator.getInstance().calculateHash(mmess); + long endmedstartlong = System.currentTimeMillis(); + Hash l = SHA256Generator.getInstance().calculateHash(lmess); + long endlong = System.currentTimeMillis(); + System.out.print("."); + shorttime += endshortstartmed - startshort; + medtime += endmedstartlong - endshortstartmed; + longtime += endlong - endmedstartlong; + + if ((minShort == 0) && (minMed == 0) && (minLong == 0) ) { + minShort = endshortstartmed - startshort; + maxShort = endshortstartmed - startshort; + minMed = endmedstartlong - endshortstartmed; + maxMed = endmedstartlong - endshortstartmed; + minLong = endlong - endmedstartlong; + maxLong = endlong - endmedstartlong; + } else { + if (minShort > endshortstartmed - startshort) minShort = endshortstartmed - startshort; + if (maxShort < endshortstartmed - startshort) maxShort = endshortstartmed - startshort; + if (minMed > endmedstartlong - endshortstartmed) minMed = endmedstartlong - endshortstartmed; + if (maxMed < endmedstartlong - endshortstartmed) maxMed = endmedstartlong - endshortstartmed; + if (minLong > endlong - endmedstartlong) minLong = endlong - endmedstartlong; + if (maxLong < endlong - endmedstartlong) maxLong = endlong - endmedstartlong; + } + } + System.out.println(); + System.out.println("Short Message Time Average : " + (shorttime/times) + "\ttotal: " + shorttime + "\tmin: " + minShort + "\tmax: " + maxShort + "\tBps: " + (shorttime == 0 ? "NaN" : ""+(times*smess.length)/shorttime)); + System.out.println("Medium Message Time Average : " + (medtime/times) + "\ttotal: " + medtime + "\tmin: " + minMed + "\tmax: " + maxMed + "\tBps: " + (times*mmess.length*1000)/medtime); + System.out.println("Long Message Time Average : " + (longtime/times) + "\ttotal: " + longtime + "\tmin: " + minLong + "\tmax: " + maxLong + "\tBps: " + (times*lmess.length*1000)/longtime); + } +} + diff --git a/core/java/test/net/i2p/crypto/SessionEncryptionTest.java b/core/java/test/net/i2p/crypto/SessionEncryptionTest.java new file mode 100644 index 0000000000..5a1364e55e --- /dev/null +++ b/core/java/test/net/i2p/crypto/SessionEncryptionTest.java @@ -0,0 +1,406 @@ +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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.PublicKey; +import net.i2p.data.PrivateKey; +import net.i2p.data.SessionKey; +import net.i2p.data.SessionTag; +import net.i2p.data.DataHelper; + +import net.i2p.util.Log; +import net.i2p.util.Clock; + +import java.util.HashSet; +import java.util.Set; + +/** + * + * session key management unit tests: + * + * Run tagsIncluded useTag rekey + * // no sessions + * 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 + * // rekeying + * 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 + */ +public class SessionEncryptionTest { + private final static Log _log = new Log(SessionEncryptionTest.class); + 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) {} + } + + /** + * 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"); + } + + /** + * 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; + } + } + + /** + * 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; + } + } + + + /** + * 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)"); + } + + 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); + } + } + } + } + + private Set generateNewTags(int numTags) { + Set tags = new HashSet(numTags); + for (int i = 0; i < numTags; i++) + tags.add(new SessionTag(true)); + return tags; + } +} diff --git a/core/java/test/net/i2p/data/AbuseReasonTest.java b/core/java/test/net/i2p/data/AbuseReasonTest.java new file mode 100644 index 0000000000..eebe5f9ac0 --- /dev/null +++ b/core/java/test/net/i2p/data/AbuseReasonTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.AbuseReason; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class AbuseReasonTest extends StructureTest { + static { + TestData.registerTest(new AbuseReasonTest(), "AbuseReason"); + } + public DataStructure createDataStructure() throws DataFormatException { + AbuseReason res = new AbuseReason(); + res.setReason("Because they're mean"); + return res; + } + public DataStructure createStructureToRead() { return new AbuseReason(); } +} diff --git a/core/java/test/net/i2p/data/AbuseSeverityTest.java b/core/java/test/net/i2p/data/AbuseSeverityTest.java new file mode 100644 index 0000000000..ffdb1b0632 --- /dev/null +++ b/core/java/test/net/i2p/data/AbuseSeverityTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.AbuseSeverity; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class AbuseSeverityTest extends StructureTest { + static { + TestData.registerTest(new AbuseSeverityTest(), "AbuseSeverity"); + } + public DataStructure createDataStructure() throws DataFormatException { + AbuseSeverity sev = new AbuseSeverity(); + sev.setSeverity(64); + return sev; + } + public DataStructure createStructureToRead() { return new AbuseSeverity(); } +} diff --git a/core/java/test/net/i2p/data/BooleanTest.java b/core/java/test/net/i2p/data/BooleanTest.java new file mode 100644 index 0000000000..aa6c4a03ca --- /dev/null +++ b/core/java/test/net/i2p/data/BooleanTest.java @@ -0,0 +1,59 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.util.Log; + +/** + * Test harness for the boolean structure + * + * @author jrandom + */ +class BooleanTest implements TestDataGenerator, TestDataPrinter { + static { + TestData.registerGenerator(new BooleanTest(), "Boolean"); + TestData.registerPrinter(new BooleanTest(), "Boolean"); + } + private static final Log _log = new Log(BooleanTest.class); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DataHelper.writeBoolean(baos, Boolean.TRUE); + return baos.toByteArray(); + } catch (DataFormatException dfe) { + _log.error("Error writing the boolean", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the boolean", ioe); + return null; + } + } + + public String testData(InputStream inputStream) { + try { + Boolean b = DataHelper.readBoolean(inputStream); + return ""+b; + } catch (DataFormatException dfe) { + _log.error("Error reading the boolean", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the boolean", ioe); + return null; + } + } + + +} diff --git a/core/java/test/net/i2p/data/CertificateTest.java b/core/java/test/net/i2p/data/CertificateTest.java new file mode 100644 index 0000000000..df39ec9e27 --- /dev/null +++ b/core/java/test/net/i2p/data/CertificateTest.java @@ -0,0 +1,34 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.Certificate; +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class CertificateTest extends StructureTest { + static { + TestData.registerTest(new CertificateTest(), "Certificate"); + } + public DataStructure createDataStructure() throws DataFormatException { + Certificate cert = new Certificate(); + byte data[] = new byte[32]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + cert.setPayload(data); + cert.setCertificateType(Certificate.CERTIFICATE_TYPE_NULL); + return cert; + } + public DataStructure createStructureToRead() { return new Certificate(); } +} diff --git a/core/java/test/net/i2p/data/CreateLeaseSetMessageTest.java b/core/java/test/net/i2p/data/CreateLeaseSetMessageTest.java new file mode 100644 index 0000000000..e2150ff452 --- /dev/null +++ b/core/java/test/net/i2p/data/CreateLeaseSetMessageTest.java @@ -0,0 +1,37 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.LeaseSet; +import net.i2p.data.PrivateKey; +import net.i2p.data.SigningPrivateKey; +import net.i2p.data.i2cp.CreateLeaseSetMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing CreateLeaseSetMessage objects + * + * @author jrandom + */ +class CreateLeaseSetMessageTest extends StructureTest { + static { + TestData.registerTest(new CreateLeaseSetMessageTest(), "CreateLeaseSetMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + CreateLeaseSetMessage msg = new CreateLeaseSetMessage(); + msg.setPrivateKey((PrivateKey)(new PrivateKeyTest()).createDataStructure()); + msg.setSigningPrivateKey((SigningPrivateKey)(new SigningPrivateKeyTest()).createDataStructure()); + msg.setLeaseSet((LeaseSet)(new LeaseSetTest()).createDataStructure()); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new CreateLeaseSetMessage(); } +} diff --git a/core/java/test/net/i2p/data/CreateSessionMessageTest.java b/core/java/test/net/i2p/data/CreateSessionMessageTest.java new file mode 100644 index 0000000000..8ba444beec --- /dev/null +++ b/core/java/test/net/i2p/data/CreateSessionMessageTest.java @@ -0,0 +1,31 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.CreateSessionMessage; +import net.i2p.data.i2cp.SessionConfig; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class CreateSessionMessageTest extends StructureTest { + static { + TestData.registerTest(new CreateSessionMessageTest(), "CreateSessionMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + CreateSessionMessage msg = new CreateSessionMessage(); + msg.setSessionConfig((SessionConfig)(new SessionConfigTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new CreateSessionMessage(); } +} diff --git a/core/java/test/net/i2p/data/DateTest.java b/core/java/test/net/i2p/data/DateTest.java new file mode 100644 index 0000000000..616a3f2793 --- /dev/null +++ b/core/java/test/net/i2p/data/DateTest.java @@ -0,0 +1,60 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.util.Log; + +/** + * Test harness for the boolean structure + * + * @author jrandom + */ +class DateTest implements TestDataGenerator, TestDataPrinter { + static { + TestData.registerGenerator(new DateTest(), "Date"); + TestData.registerPrinter(new DateTest(), "Date"); + } + private static final Log _log = new Log(DateTest.class); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DataHelper.writeDate(baos, new Date()); + return baos.toByteArray(); + } catch (DataFormatException dfe) { + _log.error("Error writing the date", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the date", ioe); + return null; + } + } + + public String testData(InputStream inputStream) { + try { + Date d = DataHelper.readDate(inputStream); + return ""+d; + } catch (DataFormatException dfe) { + _log.error("Error reading the date", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the date", ioe); + return null; + } + } + + +} diff --git a/core/java/test/net/i2p/data/DestinationTest.java b/core/java/test/net/i2p/data/DestinationTest.java new file mode 100644 index 0000000000..8d49776391 --- /dev/null +++ b/core/java/test/net/i2p/data/DestinationTest.java @@ -0,0 +1,38 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.Certificate; +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Destination; +import net.i2p.data.PublicKey; +import net.i2p.data.SigningPublicKey; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class DestinationTest extends StructureTest { + static { + TestData.registerTest(new DestinationTest(), "Destination"); + } + public DataStructure createDataStructure() throws DataFormatException { + Destination dest = new Destination(); + StructureTest tst = new CertificateTest(); + dest.setCertificate((Certificate)tst.createDataStructure()); + tst = new PublicKeyTest(); + dest.setPublicKey((PublicKey)tst.createDataStructure()); + tst = new SigningPublicKeyTest(); + dest.setSigningPublicKey((SigningPublicKey)tst.createDataStructure()); + return dest; + } + public DataStructure createStructureToRead() { return new Destination(); } +} diff --git a/core/java/test/net/i2p/data/DestroySessionMessageTest.java b/core/java/test/net/i2p/data/DestroySessionMessageTest.java new file mode 100644 index 0000000000..42aedcea1b --- /dev/null +++ b/core/java/test/net/i2p/data/DestroySessionMessageTest.java @@ -0,0 +1,31 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.DestroySessionMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class DestroySessionMessageTest extends StructureTest { + static { + TestData.registerTest(new DestroySessionMessageTest(), "DestroySessionMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + DestroySessionMessage msg = new DestroySessionMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new DestroySessionMessage(); } +} diff --git a/core/java/test/net/i2p/data/DisconnectMessageTest.java b/core/java/test/net/i2p/data/DisconnectMessageTest.java new file mode 100644 index 0000000000..22575fd6d7 --- /dev/null +++ b/core/java/test/net/i2p/data/DisconnectMessageTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.DisconnectMessage; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class DisconnectMessageTest extends StructureTest { + static { + TestData.registerTest(new DisconnectMessageTest(), "DisconnectMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + DisconnectMessage msg = new DisconnectMessage(); + msg.setReason("Because I say so"); + return msg; + } + public DataStructure createStructureToRead() { return new DisconnectMessage(); } +} diff --git a/core/java/test/net/i2p/data/HashTest.java b/core/java/test/net/i2p/data/HashTest.java new file mode 100644 index 0000000000..08f278c00a --- /dev/null +++ b/core/java/test/net/i2p/data/HashTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Hash; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class HashTest extends StructureTest { + static { + TestData.registerTest(new HashTest(), "Hash"); + } + public DataStructure createDataStructure() throws DataFormatException { + Hash hash = new Hash(); + byte data[] = new byte[32]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + hash.setData(data); + return hash; + } + public DataStructure createStructureToRead() { return new Hash(); } +} diff --git a/core/java/test/net/i2p/data/LeaseSetTest.java b/core/java/test/net/i2p/data/LeaseSetTest.java new file mode 100644 index 0000000000..2bfa07c32d --- /dev/null +++ b/core/java/test/net/i2p/data/LeaseSetTest.java @@ -0,0 +1,38 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Destination; +import net.i2p.data.LeaseSet; +import net.i2p.data.PublicKey; +import net.i2p.data.Signature; +import net.i2p.data.SigningPublicKey; + +/** + * Test harness for loading / storing Lease objects + * + * @author jrandom + */ +class LeaseSetTest extends StructureTest { + static { + TestData.registerTest(new LeaseSetTest(), "LeaseSet"); + } + public DataStructure createDataStructure() throws DataFormatException { + LeaseSet leaseSet = new LeaseSet(); + leaseSet.setDestination((Destination)(new DestinationTest()).createDataStructure()); + leaseSet.setEncryptionKey((PublicKey)(new PublicKeyTest()).createDataStructure()); + leaseSet.setSignature((Signature)(new SignatureTest()).createDataStructure()); + leaseSet.setSigningKey((SigningPublicKey)(new SigningPublicKeyTest()).createDataStructure()); + //leaseSet.setVersion(42l); + return leaseSet; + } + public DataStructure createStructureToRead() { return new LeaseSet(); } +} diff --git a/core/java/test/net/i2p/data/LeaseTest.java b/core/java/test/net/i2p/data/LeaseTest.java new file mode 100644 index 0000000000..9f214ed23f --- /dev/null +++ b/core/java/test/net/i2p/data/LeaseTest.java @@ -0,0 +1,41 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.Date; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Lease; +import net.i2p.data.RouterIdentity; +import net.i2p.data.TunnelId; + +/** + * Test harness for loading / storing Lease objects + * + * @author jrandom + */ +class LeaseTest extends StructureTest { + static { + TestData.registerTest(new LeaseTest(), "Lease"); + } + public DataStructure createDataStructure() throws DataFormatException { + Lease lease = new Lease(); + StructureTest tst = new DestinationTest(); + lease.setEndDate(new Date(1000*60*2)); + //lease.setStartDate(new Date(1000*60)); + tst = new RouterIdentityTest(); + lease.setRouterIdentity((RouterIdentity)tst.createDataStructure()); + tst = new TunnelIdTest(); + lease.setTunnelId((TunnelId)tst.createDataStructure()); + + return lease; + } + public DataStructure createStructureToRead() { return new Lease(); } +} diff --git a/core/java/test/net/i2p/data/MappingTest.java b/core/java/test/net/i2p/data/MappingTest.java new file mode 100644 index 0000000000..b1b8bf9e0c --- /dev/null +++ b/core/java/test/net/i2p/data/MappingTest.java @@ -0,0 +1,64 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.util.Log; + +/** + * Test harness for the mapping structure (in java, a Properties map) + * + * @author jrandom + */ +class MappingTest implements TestDataGenerator, TestDataPrinter { + static { + TestData.registerGenerator(new MappingTest(), "Mapping"); + TestData.registerPrinter(new MappingTest(), "Mapping"); + } + private static final Log _log = new Log(MappingTest.class); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Properties options = new Properties(); + options.setProperty("key1", "val1"); + options.setProperty("key2", "val2"); + options.setProperty("key3", "val3"); + try { + DataHelper.writeProperties(baos, options); + return baos.toByteArray(); + } catch (DataFormatException dfe) { + _log.error("Error writing the mapping", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the mapping", ioe); + return null; + } + } + + public String testData(InputStream inputStream) { + try { + Properties options = DataHelper.readProperties(inputStream); + return DataHelper.toString(options); + } catch (DataFormatException dfe) { + _log.error("Error reading the mapping", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the mapping", ioe); + return null; + } + } + + +} diff --git a/core/java/test/net/i2p/data/MessageIdTest.java b/core/java/test/net/i2p/data/MessageIdTest.java new file mode 100644 index 0000000000..e92d26f378 --- /dev/null +++ b/core/java/test/net/i2p/data/MessageIdTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.MessageId; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class MessageIdTest extends StructureTest { + static { + TestData.registerTest(new MessageIdTest(), "MessageId"); + } + public DataStructure createDataStructure() throws DataFormatException { + MessageId id = new MessageId(); + id.setMessageId(101); + return id; + } + public DataStructure createStructureToRead() { return new MessageId(); } +} diff --git a/core/java/test/net/i2p/data/MessagePayloadMessageTest.java b/core/java/test/net/i2p/data/MessagePayloadMessageTest.java new file mode 100644 index 0000000000..8234a518e6 --- /dev/null +++ b/core/java/test/net/i2p/data/MessagePayloadMessageTest.java @@ -0,0 +1,56 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Payload; +import net.i2p.data.i2cp.MessageId; +import net.i2p.data.i2cp.MessagePayloadMessage; +import net.i2p.data.i2cp.SessionId; +import net.i2p.util.Log; + +/** + * Test harness for loading / storing SendMessageMessage objects + * + * @author jrandom + */ +class MessagePayloadMessageTest extends StructureTest { + private final static Log _log = new Log(MessagePayloadMessage.class); + + static { + TestData.registerTest(new MessagePayloadMessageTest(), "MessagePayloadMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + MessagePayloadMessage msg = new MessagePayloadMessage(); + msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setPayload((Payload)(new PayloadTest()).createDataStructure()); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new MessagePayloadMessage(); } + public String testData(InputStream inputStream) { + try { + DataStructure structure = createStructureToRead(); + structure.readBytes(inputStream); + ((MessagePayloadMessage)structure).getPayload().setUnencryptedData(((MessagePayloadMessage)structure).getPayload().getEncryptedData()); + return structure.toString(); + } catch (DataFormatException dfe) { + _log.error("Error reading the data structure", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the data structure", ioe); + return null; + } + } + +} diff --git a/core/java/test/net/i2p/data/MessageStatusMessageTest.java b/core/java/test/net/i2p/data/MessageStatusMessageTest.java new file mode 100644 index 0000000000..7b2db8c994 --- /dev/null +++ b/core/java/test/net/i2p/data/MessageStatusMessageTest.java @@ -0,0 +1,35 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.MessageId; +import net.i2p.data.i2cp.MessageStatusMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing MessageStatusMessage objects + * + * @author jrandom + */ +class MessageStatusMessageTest extends StructureTest { + static { + TestData.registerTest(new MessageStatusMessageTest(), "MessageStatusMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + MessageStatusMessage msg = new MessageStatusMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setSize(1024*1024*42L); + msg.setStatus(MessageStatusMessage.STATUS_AVAILABLE); + return msg; + } + public DataStructure createStructureToRead() { return new MessageStatusMessage(); } +} diff --git a/core/java/test/net/i2p/data/PayloadTest.java b/core/java/test/net/i2p/data/PayloadTest.java new file mode 100644 index 0000000000..2fe01de778 --- /dev/null +++ b/core/java/test/net/i2p/data/PayloadTest.java @@ -0,0 +1,65 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Destination; +import net.i2p.data.Hash; +import net.i2p.data.Payload; +import net.i2p.data.SessionKey; +import net.i2p.util.Log; + +/** + * Test harness for loading / storing Payload objects + * + * @author jrandom + */ +class PayloadTest extends StructureTest { + private final static Log _log = new Log(PayloadTest.class); + + static { + TestData.registerTest(new PayloadTest(), "Payload"); + } + public DataStructure createDataStructure() throws DataFormatException { + Payload payload = new Payload(); + SessionKey key = (SessionKey)(new SessionKeyTest()).createDataStructure(); + //payload.setEncryptionKey(key); + byte data[] = "Hello, I2P".getBytes(); + payload.setUnencryptedData(data); + Hash hash = (Hash)(new HashTest()).createDataStructure(); + //payload.setHash(hash); + Destination target = (Destination)(new DestinationTest()).createDataStructure(); + payload.setEncryptedData(data); + //payload.encryptPayload(target, 128); + return payload; + } + public DataStructure createStructureToRead() { return new Payload(); } + + public String testData(InputStream inputStream) { + try { + DataStructure structure = createStructureToRead(); + structure.readBytes(inputStream); + Payload payload = (Payload)structure; + payload.setUnencryptedData(payload.getEncryptedData()); + //((Payload)structure).decryptPayload((PrivateKey)(new PrivateKeyTest()).createDataStructure()); + return structure.toString(); + } catch (DataFormatException dfe) { + _log.error("Error reading the data structure", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the data structure", ioe); + return null; + } + } + +} diff --git a/core/java/test/net/i2p/data/PrivateKeyTest.java b/core/java/test/net/i2p/data/PrivateKeyTest.java new file mode 100644 index 0000000000..6b78e2610c --- /dev/null +++ b/core/java/test/net/i2p/data/PrivateKeyTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.PrivateKey; + +/** + * Test harness for loading / storing PrivateKey objects + * + * @author jrandom + */ +class PrivateKeyTest extends StructureTest { + static { + TestData.registerTest(new PrivateKeyTest(), "PrivateKey"); + } + public DataStructure createDataStructure() throws DataFormatException { + PrivateKey privateKey = new PrivateKey(); + byte data[] = new byte[PrivateKey.KEYSIZE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + privateKey.setData(data); + return privateKey; + } + public DataStructure createStructureToRead() { return new PrivateKey(); } +} diff --git a/core/java/test/net/i2p/data/PublicKeyTest.java b/core/java/test/net/i2p/data/PublicKeyTest.java new file mode 100644 index 0000000000..8fe78cef6a --- /dev/null +++ b/core/java/test/net/i2p/data/PublicKeyTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.PublicKey; + +/** + * Test harness for loading / storing PublicKey objects + * + * @author jrandom + */ +class PublicKeyTest extends StructureTest { + static { + TestData.registerTest(new PublicKeyTest(), "PublicKey"); + } + public DataStructure createDataStructure() throws DataFormatException { + PublicKey publicKey = new PublicKey(); + byte data[] = new byte[PublicKey.KEYSIZE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + publicKey.setData(data); + return publicKey; + } + public DataStructure createStructureToRead() { return new PublicKey(); } +} diff --git a/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java b/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java new file mode 100644 index 0000000000..140a9b8071 --- /dev/null +++ b/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.MessageId; +import net.i2p.data.i2cp.ReceiveMessageBeginMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class ReceiveMessageBeginMessageTest extends StructureTest { + static { + TestData.registerTest(new ReceiveMessageBeginMessageTest(), "ReceiveMessageBeginMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + ReceiveMessageBeginMessage msg = new ReceiveMessageBeginMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new ReceiveMessageBeginMessage(); } +} diff --git a/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java b/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java new file mode 100644 index 0000000000..c1c34b5d17 --- /dev/null +++ b/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.MessageId; +import net.i2p.data.i2cp.ReceiveMessageEndMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class ReceiveMessageEndMessageTest extends StructureTest { + static { + TestData.registerTest(new ReceiveMessageEndMessageTest(), "ReceiveMessageEndMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + ReceiveMessageEndMessage msg = new ReceiveMessageEndMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new ReceiveMessageEndMessage(); } +} diff --git a/core/java/test/net/i2p/data/ReportAbuseMessageTest.java b/core/java/test/net/i2p/data/ReportAbuseMessageTest.java new file mode 100644 index 0000000000..7696946359 --- /dev/null +++ b/core/java/test/net/i2p/data/ReportAbuseMessageTest.java @@ -0,0 +1,37 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.AbuseReason; +import net.i2p.data.i2cp.AbuseSeverity; +import net.i2p.data.i2cp.MessageId; +import net.i2p.data.i2cp.ReportAbuseMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class ReportAbuseMessageTest extends StructureTest { + static { + TestData.registerTest(new ReportAbuseMessageTest(), "ReportAbuseMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + ReportAbuseMessage msg = new ReportAbuseMessage(); + msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setReason((AbuseReason)(new AbuseReasonTest()).createDataStructure()); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setSeverity((AbuseSeverity)(new AbuseSeverityTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new ReportAbuseMessage(); } +} diff --git a/core/java/test/net/i2p/data/RequestLeaseSetMessageTest.java b/core/java/test/net/i2p/data/RequestLeaseSetMessageTest.java new file mode 100644 index 0000000000..3bcb546c86 --- /dev/null +++ b/core/java/test/net/i2p/data/RequestLeaseSetMessageTest.java @@ -0,0 +1,38 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.Date; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.RouterIdentity; +import net.i2p.data.TunnelId; +import net.i2p.data.i2cp.RequestLeaseSetMessage; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing RequestLeaseSetMessage objects + * + * @author jrandom + */ +class RequestLeaseSetMessageTest extends StructureTest { + static { + TestData.registerTest(new RequestLeaseSetMessageTest(), "RequestLeaseSetMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + RequestLeaseSetMessage msg = new RequestLeaseSetMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setEndDate(new Date(1000*60*60*12)); + msg.addEndpoint((RouterIdentity)(new RouterIdentityTest()).createDataStructure(), + (TunnelId)(new TunnelIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new RequestLeaseSetMessage(); } +} diff --git a/core/java/test/net/i2p/data/RouterAddressTest.java b/core/java/test/net/i2p/data/RouterAddressTest.java new file mode 100644 index 0000000000..6c48d53f17 --- /dev/null +++ b/core/java/test/net/i2p/data/RouterAddressTest.java @@ -0,0 +1,42 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.Date; +import java.util.Properties; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.RouterAddress; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class RouterAddressTest extends StructureTest { + static { + TestData.registerTest(new RouterAddressTest(), "RouterAddress"); + } + public DataStructure createDataStructure() throws DataFormatException { + RouterAddress addr = new RouterAddress(); + byte data[] = new byte[32]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + addr.setCost(42); + addr.setExpiration(new Date(1000*60*60*24)); // jan 2 1970 + Properties options = new Properties(); + options.setProperty("hostname", "localhost"); + options.setProperty("portnum", "1234"); + addr.setOptions(options); + addr.setTransportStyle("Blah"); + return addr; + } + public DataStructure createStructureToRead() { return new RouterAddress(); } +} diff --git a/core/java/test/net/i2p/data/RouterIdentityTest.java b/core/java/test/net/i2p/data/RouterIdentityTest.java new file mode 100644 index 0000000000..82a8e6cd81 --- /dev/null +++ b/core/java/test/net/i2p/data/RouterIdentityTest.java @@ -0,0 +1,38 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.Certificate; +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.PublicKey; +import net.i2p.data.RouterIdentity; +import net.i2p.data.SigningPublicKey; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class RouterIdentityTest extends StructureTest { + static { + TestData.registerTest(new RouterIdentityTest(), "RouterIdentity"); + } + public DataStructure createDataStructure() throws DataFormatException { + RouterIdentity ident = new RouterIdentity(); + Certificate cert = (Certificate)(new CertificateTest()).createDataStructure(); + ident.setCertificate(cert); + PublicKey pk = (PublicKey)(new PublicKeyTest()).createDataStructure(); + ident.setPublicKey(pk); + SigningPublicKey k = (SigningPublicKey)(new SigningPublicKeyTest()).createDataStructure(); + ident.setSigningPublicKey(k); + return ident; + } + public DataStructure createStructureToRead() { return new RouterIdentity(); } +} diff --git a/core/java/test/net/i2p/data/RouterInfoTest.java b/core/java/test/net/i2p/data/RouterInfoTest.java new file mode 100644 index 0000000000..1f3f7d48bc --- /dev/null +++ b/core/java/test/net/i2p/data/RouterInfoTest.java @@ -0,0 +1,85 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.HashSet; +import java.util.Properties; + +import net.i2p.crypto.KeyGenerator; +import net.i2p.data.Certificate; +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.PrivateKey; +import net.i2p.data.PublicKey; +import net.i2p.data.RouterIdentity; +import net.i2p.data.RouterInfo; +import net.i2p.data.SigningPrivateKey; +import net.i2p.data.SigningPublicKey; +import net.i2p.util.Log; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class RouterInfoTest extends StructureTest { + private final static Log _log = new Log(RouterInfoTest.class); + static { + TestData.registerTest(new RouterInfoTest(), "RouterInfo"); + } + public DataStructure createDataStructure() throws DataFormatException { + RouterInfo info = new RouterInfo(); + HashSet addresses = new HashSet(); + DataStructure structure = (new RouterAddressTest()).createDataStructure(); + addresses.add(structure); + info.setAddresses(addresses); + + PublicKey pubKey = null; + SigningPublicKey signingPubKey = null; + PrivateKey privKey = null; + SigningPrivateKey signingPrivKey = null; + + Object obj[] = KeyGenerator.getInstance().generatePKIKeypair(); + pubKey = (PublicKey)obj[0]; + privKey = (PrivateKey)obj[1]; + obj = KeyGenerator.getInstance().generateSigningKeypair(); + signingPubKey = (SigningPublicKey)obj[0]; + signingPrivKey = (SigningPrivateKey)obj[1]; + + _log.debug("SigningPublicKey: " + signingPubKey); + _log.debug("SigningPrivateKey: " + signingPrivKey); + + RouterIdentity ident = new RouterIdentity(); + ident.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null)); + ident.setPublicKey(pubKey); + ident.setSigningPublicKey(signingPubKey); + + info.setIdentity(ident); + + Properties options = new Properties(); + for (int i = 0; i < 16; i++) { + options.setProperty("option." + i, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890$:." + i); + } + options.setProperty("netConnectionSpeed", "OC12"); + info.setOptions(options); + + HashSet peers = new HashSet(); + structure = (new HashTest()).createDataStructure(); + peers.add(structure); + info.setPeers(peers); + info.setPublished(System.currentTimeMillis()); + + //info.setVersion(69); + + info.sign(signingPrivKey); + + return info; + } + public DataStructure createStructureToRead() { return new RouterInfo(); } +} diff --git a/core/java/test/net/i2p/data/SendMessageMessageTest.java b/core/java/test/net/i2p/data/SendMessageMessageTest.java new file mode 100644 index 0000000000..019147ba96 --- /dev/null +++ b/core/java/test/net/i2p/data/SendMessageMessageTest.java @@ -0,0 +1,56 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Destination; +import net.i2p.data.Payload; +import net.i2p.data.i2cp.SendMessageMessage; +import net.i2p.data.i2cp.SessionId; +import net.i2p.util.Log; + +/** + * Test harness for loading / storing SendMessageMessage objects + * + * @author jrandom + */ +class SendMessageMessageTest extends StructureTest { + private final static Log _log = new Log(SendMessageMessageTest.class); + + static { + TestData.registerTest(new SendMessageMessageTest(), "SendMessageMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + SendMessageMessage msg = new SendMessageMessage(); + msg.setDestination((Destination)(new DestinationTest()).createDataStructure()); + msg.setPayload((Payload)(new PayloadTest()).createDataStructure()); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + return msg; + } + public DataStructure createStructureToRead() { return new SendMessageMessage(); } + public String testData(InputStream inputStream) { + try { + DataStructure structure = createStructureToRead(); + structure.readBytes(inputStream); + ((SendMessageMessage)structure).getPayload().setUnencryptedData(((SendMessageMessage)structure).getPayload().getEncryptedData()); + return structure.toString(); + } catch (DataFormatException dfe) { + _log.error("Error reading the data structure", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the data structure", ioe); + return null; + } + } + +} diff --git a/core/java/test/net/i2p/data/SessionConfigTest.java b/core/java/test/net/i2p/data/SessionConfigTest.java new file mode 100644 index 0000000000..c5f72d40ae --- /dev/null +++ b/core/java/test/net/i2p/data/SessionConfigTest.java @@ -0,0 +1,42 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.Properties; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Destination; +import net.i2p.data.Signature; +import net.i2p.data.SigningPrivateKey; +import net.i2p.data.i2cp.SessionConfig; + +/** + * Test harness for loading / storing Hash objects + * + * @author jrandom + */ +class SessionConfigTest extends StructureTest { + static { + TestData.registerTest(new SessionConfigTest(), "SessionConfig"); + } + public DataStructure createDataStructure() throws DataFormatException { + SessionConfig cfg = new SessionConfig(); + cfg.setDestination((Destination)(new DestinationTest()).createDataStructure()); + cfg.setSignature((Signature)(new SignatureTest()).createDataStructure()); + Properties options = new Properties(); + options.setProperty("routerHost", "localhost"); + options.setProperty("routerPort", "54321"); + options.setProperty("routerSecret", "blah"); + cfg.setOptions(options); + cfg.signSessionConfig((SigningPrivateKey)(new SigningPrivateKeyTest()).createDataStructure()); + return cfg; + } + public DataStructure createStructureToRead() { return new SessionConfig(); } +} diff --git a/core/java/test/net/i2p/data/SessionIdTest.java b/core/java/test/net/i2p/data/SessionIdTest.java new file mode 100644 index 0000000000..2be8a9f148 --- /dev/null +++ b/core/java/test/net/i2p/data/SessionIdTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.SessionId; + +/** + * Test harness for loading / storing SessionId objects + * + * @author jrandom + */ +class SessionIdTest extends StructureTest { + static { + TestData.registerTest(new SessionIdTest(), "SessionId"); + } + public DataStructure createDataStructure() throws DataFormatException { + SessionId id = new SessionId(); + id.setSessionId(7); + return id; + } + public DataStructure createStructureToRead() { return new SessionId(); } +} diff --git a/core/java/test/net/i2p/data/SessionKeyTest.java b/core/java/test/net/i2p/data/SessionKeyTest.java new file mode 100644 index 0000000000..862056e9e9 --- /dev/null +++ b/core/java/test/net/i2p/data/SessionKeyTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.SessionKey; + +/** + * Test harness for loading / storing SessionKey objects + * + * @author jrandom + */ +class SessionKeyTest extends StructureTest { + static { + TestData.registerTest(new SessionKeyTest(), "SessionKey"); + } + public DataStructure createDataStructure() throws DataFormatException { + SessionKey key = new SessionKey(); + byte data[] = new byte[SessionKey.KEYSIZE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + key.setData(data); + return key; + } + public DataStructure createStructureToRead() { return new SessionKey(); } +} diff --git a/core/java/test/net/i2p/data/SessionStatusMessageTest.java b/core/java/test/net/i2p/data/SessionStatusMessageTest.java new file mode 100644 index 0000000000..0626272db7 --- /dev/null +++ b/core/java/test/net/i2p/data/SessionStatusMessageTest.java @@ -0,0 +1,32 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.i2cp.SessionId; +import net.i2p.data.i2cp.SessionStatusMessage; + +/** + * Test harness for loading / storing SessionStatusMessage objects + * + * @author jrandom + */ +class SessionStatusMessageTest extends StructureTest { + static { + TestData.registerTest(new SessionStatusMessageTest(), "SessionStatusMessage"); + } + public DataStructure createDataStructure() throws DataFormatException { + SessionStatusMessage msg = new SessionStatusMessage(); + msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setStatus(SessionStatusMessage.STATUS_CREATED); + return msg; + } + public DataStructure createStructureToRead() { return new SessionStatusMessage(); } +} diff --git a/core/java/test/net/i2p/data/SignatureTest.java b/core/java/test/net/i2p/data/SignatureTest.java new file mode 100644 index 0000000000..f49eb15869 --- /dev/null +++ b/core/java/test/net/i2p/data/SignatureTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.Signature; + +/** + * Test harness for loading / storing Signature objects + * + * @author jrandom + */ +class SignatureTest extends StructureTest { + static { + TestData.registerTest(new SignatureTest(), "Signature"); + } + public DataStructure createDataStructure() throws DataFormatException { + Signature sig = new Signature(); + byte data[] = new byte[Signature.SIGNATURE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + sig.setData(data); + return sig; + } + public DataStructure createStructureToRead() { return new Signature(); } +} diff --git a/core/java/test/net/i2p/data/SigningPrivateKeyTest.java b/core/java/test/net/i2p/data/SigningPrivateKeyTest.java new file mode 100644 index 0000000000..e89193a9f2 --- /dev/null +++ b/core/java/test/net/i2p/data/SigningPrivateKeyTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.SigningPrivateKey; + +/** + * Test harness for loading / storing SigningPrivateKey objects + * + * @author jrandom + */ +class SigningPrivateKeyTest extends StructureTest { + static { + TestData.registerTest(new SigningPrivateKeyTest(), "SigningPrivateKey"); + } + public DataStructure createDataStructure() throws DataFormatException { + SigningPrivateKey privateKey = new SigningPrivateKey(); + byte data[] = new byte[SigningPrivateKey.KEYSIZE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + privateKey.setData(data); + return privateKey; + } + public DataStructure createStructureToRead() { return new SigningPrivateKey(); } +} diff --git a/core/java/test/net/i2p/data/SigningPublicKeyTest.java b/core/java/test/net/i2p/data/SigningPublicKeyTest.java new file mode 100644 index 0000000000..72129cf3b7 --- /dev/null +++ b/core/java/test/net/i2p/data/SigningPublicKeyTest.java @@ -0,0 +1,33 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.SigningPublicKey; + +/** + * Test harness for loading / storing PublicKey objects + * + * @author jrandom + */ +class SigningPublicKeyTest extends StructureTest { + static { + TestData.registerTest(new SigningPublicKeyTest(), "SigningPublicKey"); + } + public DataStructure createDataStructure() throws DataFormatException { + SigningPublicKey publicKey = new SigningPublicKey(); + byte data[] = new byte[SigningPublicKey.KEYSIZE_BYTES]; + for (int i = 0; i < data.length; i++) + data[i] = (byte)(i%16); + publicKey.setData(data); + return publicKey; + } + public DataStructure createStructureToRead() { return new SigningPublicKey(); } +} diff --git a/core/java/test/net/i2p/data/StringTest.java b/core/java/test/net/i2p/data/StringTest.java new file mode 100644 index 0000000000..7647666a0b --- /dev/null +++ b/core/java/test/net/i2p/data/StringTest.java @@ -0,0 +1,59 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.util.Log; + +/** + * Test harness for the boolean structure + * + * @author jrandom + */ +class StringTest implements TestDataGenerator, TestDataPrinter { + static { + TestData.registerGenerator(new StringTest(), "String"); + TestData.registerPrinter(new StringTest(), "String"); + } + private static final Log _log = new Log(StringTest.class); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DataHelper.writeString(baos, "Hello, I2P"); + return baos.toByteArray(); + } catch (DataFormatException dfe) { + _log.error("Error writing the string", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the string", ioe); + return null; + } + } + + public String testData(InputStream inputStream) { + try { + String str = DataHelper.readString(inputStream); + return ""+str; + } catch (DataFormatException dfe) { + _log.error("Error reading the string", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the string", ioe); + return null; + } + } + + +} diff --git a/core/java/test/net/i2p/data/StructureTest.java b/core/java/test/net/i2p/data/StructureTest.java new file mode 100644 index 0000000000..df6089a265 --- /dev/null +++ b/core/java/test/net/i2p/data/StructureTest.java @@ -0,0 +1,60 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.util.Log; + +/** + * Utility class for wrapping data structure tests + * + * @author jrandom + */ +abstract class StructureTest implements TestDataGenerator, TestDataPrinter { + private static final Log _log = new Log(StructureTest.class); + + public abstract DataStructure createDataStructure() throws DataFormatException; + public abstract DataStructure createStructureToRead(); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DataStructure structure = createDataStructure(); + structure.writeBytes(baos); + } catch (DataFormatException dfe) { + _log.error("Error writing the data structure", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the data structure", ioe); + return null; + } + return baos.toByteArray(); + } + + public String testData(InputStream inputStream) { + try { + DataStructure structure = createStructureToRead(); + structure.readBytes(inputStream); + return structure.toString() + "\n\nIn base 64: " + structure.toBase64(); + } catch (DataFormatException dfe) { + _log.error("Error reading the data structure", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the data structure", ioe); + return null; + } + } + + +} diff --git a/core/java/test/net/i2p/data/TestData.java b/core/java/test/net/i2p/data/TestData.java new file mode 100644 index 0000000000..89f213c5a7 --- /dev/null +++ b/core/java/test/net/i2p/data/TestData.java @@ -0,0 +1,150 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.util.HashMap; +import java.util.Iterator; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; + +import net.i2p.util.Log; + +/** + * Test harness for loading / storing data structures + * + * @author jrandom + */ +public class TestData { + private final static Log _log = new Log(TestData.class); + private final static String HELP = "\nUsage: TestData generate objectType outFile\n" + + " TestData display objectType inFile\n" + + " TestData test objectType tempFile\n" + + "Known types: "; + + private final static String OP_GENERATE = "generate"; + private final static String OP_DISPLAY = "display"; + private final static String OP_TEST = "test"; + + private final static HashMap _generators; + private final static HashMap _printers; + static { + _generators = new HashMap(); + _generators.put("NullType", new TestDataGenerator() { public byte[] getData() { return new byte[1]; } }); + + _printers = new HashMap(); + _printers.put("NullType", new TestDataPrinter() { public String testData(InputStream in) { return "Null data read successfully"; } }); + } + + static void registerTest(StructureTest test, String name) { + registerGenerator(test, name); + registerPrinter(test, name); + } + static void registerGenerator(TestDataGenerator test, String name) { + _generators.put(name, test); + } + static void registerPrinter(TestDataPrinter test, String name) { + _printers.put(name, test); + } + + public static void main(String args[]) { + if (args.length < 1) { + showHelp(); + return; + } + + if (OP_GENERATE.equalsIgnoreCase(args[0])) { + validateTest(args[1]); + if (args.length != 3) { + showHelp(); + return; + } + generate(args[1], args[2]); + return; + } else if (OP_DISPLAY.equalsIgnoreCase(args[0])) { + validateTest(args[1]); + if (args.length != 3) { + showHelp(); + return; + } + display(args[1], args[2]); + } else if (OP_TEST.equalsIgnoreCase(args[0])) { + validateTest(args[1]); + if (args.length != 3) { + showHelp(); + return; + } + generate(args[1], args[2]); + display(args[1], args[2]); + } else { + showHelp(); + } + try { Thread.sleep(2000); } catch (InterruptedException ie) {} + } + + private static void validateTest(String objectType) { + try { + String clsName = TestData.class.getPackage().getName() + "." + objectType + "Test"; + Class.forName(clsName); + } catch (Throwable t) { + _log.error("Error validating the object type", t); + } + } + + public static void generate(String objectType, String outFile) { + TestDataGenerator gen = (TestDataGenerator)_generators.get(objectType); + byte[] data = gen.getData(); + if (data == null) { + _log.error("Error generating the data. fail"); + return; + } + try { + File f = new File(outFile); + FileOutputStream out = new FileOutputStream(f); + out.write(data); + out.flush(); + out.close(); + _log.debug("Wrote the file out to " + f.getAbsolutePath()); + } catch (IOException ioe) { + _log.error("Error writing out the object", ioe); + } + } + + public static void display(String type, String inFile) { + try { + File f = new File(inFile); + FileInputStream in = new FileInputStream(f); + TestDataPrinter printer = (TestDataPrinter)_printers.get(type); + String display = printer.testData(in); + in.close(); + _log.info("Displaying " + inFile + " of type: " + type); + _log.info(display); + } catch (IOException ioe) { + _log.error("Error reading the file to display", ioe); + } + } + + private static String listTypes() { + StringBuffer buf = new StringBuffer(); + for (Iterator iter = _generators.keySet().iterator(); iter.hasNext(); ) { + String type = (String)iter.next(); + buf.append(type); + if (iter.hasNext()) + buf.append(", "); + } + return buf.toString(); + } + + public static void showHelp() { + _log.info(HELP+listTypes()); + } +} diff --git a/core/java/test/net/i2p/data/TestDataGenerator.java b/core/java/test/net/i2p/data/TestDataGenerator.java new file mode 100644 index 0000000000..371b72d6c3 --- /dev/null +++ b/core/java/test/net/i2p/data/TestDataGenerator.java @@ -0,0 +1,16 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +/** + * Defines a method to create the serialization of an object + */ +public interface TestDataGenerator { + public byte[] getData(); +} diff --git a/core/java/test/net/i2p/data/TestDataPrinter.java b/core/java/test/net/i2p/data/TestDataPrinter.java new file mode 100644 index 0000000000..b95ac8531c --- /dev/null +++ b/core/java/test/net/i2p/data/TestDataPrinter.java @@ -0,0 +1,18 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.InputStream; + +/** + * Defines a method to read the serialization of an object and display it + */ +public interface TestDataPrinter { + public String testData(InputStream stream); +} diff --git a/core/java/test/net/i2p/data/TunnelIdTest.java b/core/java/test/net/i2p/data/TunnelIdTest.java new file mode 100644 index 0000000000..0dbf8c3ee5 --- /dev/null +++ b/core/java/test/net/i2p/data/TunnelIdTest.java @@ -0,0 +1,30 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataStructure; +import net.i2p.data.TunnelId; + +/** + * Test harness for loading / storing TunnelId objects + * + * @author jrandom + */ +class TunnelIdTest extends StructureTest { + static { + TestData.registerTest(new TunnelIdTest(), "TunnelId"); + } + public DataStructure createDataStructure() throws DataFormatException { + TunnelId id = new TunnelId(); + id.setTunnelId(42); + return id; + } + public DataStructure createStructureToRead() { return new TunnelId(); } +} diff --git a/core/java/test/net/i2p/data/UnsignedIntegerTest.java b/core/java/test/net/i2p/data/UnsignedIntegerTest.java new file mode 100644 index 0000000000..50ace12c30 --- /dev/null +++ b/core/java/test/net/i2p/data/UnsignedIntegerTest.java @@ -0,0 +1,59 @@ +package net.i2p.data; +/* + * 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 + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.util.Log; + +/** + * Test harness for the numerical structure (in java, an UnsignedInteger) + * + * @author jrandom + */ +class UnsignedIntegerTest implements TestDataGenerator, TestDataPrinter { + static { + TestData.registerGenerator(new UnsignedIntegerTest(), "UnsignedInteger"); + TestData.registerPrinter(new UnsignedIntegerTest(), "UnsignedInteger"); + } + private static final Log _log = new Log(UnsignedIntegerTest.class); + + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DataHelper.writeLong(baos, 4, 42); + return baos.toByteArray(); + } catch (DataFormatException dfe) { + _log.error("Error writing the integer", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error writing the integer", ioe); + return null; + } + } + + public String testData(InputStream inputStream) { + try { + long val = DataHelper.readLong(inputStream, 4); + return ""+val; + } catch (DataFormatException dfe) { + _log.error("Error reading the integer", dfe); + return null; + } catch (IOException ioe) { + _log.error("Error reading the integer", ioe); + return null; + } + } + + +} -- GitLab