diff --git a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java index b3a7b4339223647678d9bac91a54f7603146be55..4c0319f9bbf5cd3b78c7d536a3a7aeea0ec09d2e 100644 --- a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java +++ b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java @@ -304,8 +304,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { * Preliminary, not fully supported, see proposal 154. * * @throws IllegalStateException if key or tag previously set, to protect saved checksum - * @param encryptKey non-null - * @param encryptTag non-null + * @param pubKey non-null * @since 0.9.46 */ public void setReplySession(PublicKey pubKey) { diff --git a/router/java/src/net/i2p/router/crypto/ratchet/RatchetPayload.java b/router/java/src/net/i2p/router/crypto/ratchet/RatchetPayload.java index d290238fdc005e77a8904bbd01a69f58b8c5ec25..59cabe29b5669772c5a14147a07385bca4afae11 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/RatchetPayload.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/RatchetPayload.java @@ -67,7 +67,6 @@ class RatchetPayload { public void gotAck(int id, int n); /** - * @param di may be null * @since 0.9.46 */ public void gotAckRequest(); diff --git a/router/java/src/net/i2p/router/crypto/ratchet/RatchetSessionTag.java b/router/java/src/net/i2p/router/crypto/ratchet/RatchetSessionTag.java index 948b80c2e598911bf45d3ede8d1799dc4ab53f88..a5dc55b6ee1148f5297b873f6b4f15ffa491c2a1 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/RatchetSessionTag.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/RatchetSessionTag.java @@ -1,11 +1,9 @@ package net.i2p.router.crypto.ratchet; -import java.util.Arrays; - import net.i2p.data.Base64; /** - * 8 bytes, usually of random data. + * 8 bytes of random data. * Does not extend SessionTag or DataStructure to save space * * @since 0.9.44 @@ -25,18 +23,38 @@ public class RatchetSessionTag { _data = RatchetPayload.fromLong8(val, 0); } + /** + * @return data as a byte array + */ public byte[] getData() { byte[] rv = new byte[LENGTH]; RatchetPayload.toLong8(rv, 0, _data); return rv; } + /** + * @return data as a long value + * @since 0.9.46 + */ + public long getLong() { + return _data; + } + public int length() { return LENGTH; } + /** 12 chars */ public String toBase64() { - return Base64.encode(getData()); + // for efficiency + //return Base64.encode(getData()); + StringBuilder buf = new StringBuilder(12); + for (int i = 58; i > 0; i -= 6) { + buf.append(Base64.ALPHABET_I2P.charAt(((int) (_data >> i)) & 0x3f)); + } + buf.append(Base64.ALPHABET_I2P.charAt(((int) (_data << 2)) & 0x3c)); + buf.append('='); + return buf.toString(); } /** @@ -56,10 +74,20 @@ public class RatchetSessionTag { @Override public String toString() { - StringBuilder buf = new StringBuilder(64); + StringBuilder buf = new StringBuilder(33); buf.append("[RatchetSessionTag: "); buf.append(toBase64()); buf.append(']'); return buf.toString(); } + +/**** + public static void main(String[] args) { + // test toBase64() + long l = net.i2p.util.RandomSource.getInstance().nextLong(); + RatchetSessionTag tag = new RatchetSessionTag(l); + System.out.println(tag.toBase64()); + System.out.println(Base64.encode(tag.getData())); + } +****/ } diff --git a/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java b/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java index 2e1475daf399dbd5af3ed4e96f1b77e41256d9cd..06a06b049b0dad103ab8e5878aa8b3412c5e3878 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java @@ -227,7 +227,9 @@ class RatchetTagSet implements TagSetHandle { } /** - * The identifier for the session. + * The root key for the tag set. + * Used to match the OB and IB ES tagset 0, where both + * will have the same root key. * Not used for cryptographic operations after setup. */ public SessionKey getAssociatedKey() { @@ -285,11 +287,6 @@ class RatchetTagSet implements TagSetHandle { return _created + Math.min(_timeout, RatchetSKM.SESSION_PENDING_DURATION_MS); } - /** for debugging */ - public int getOriginalSize() { - return _originalSize; - } - /** * unused tags generated * @return 0 for outbound @@ -365,22 +362,6 @@ class RatchetTagSet implements TagSetHandle { return new SessionKey(_nextRootKey); } - /** - * tags still available - * inbound only - * testing only - */ - private List<RatchetSessionTag> getTags() { - if (_sessionTags == null) - return Collections.emptyList(); - int sz = _sessionTags.size(); - List<RatchetSessionTag> rv = new ArrayList<RatchetSessionTag>(sz); - for (int i = 0; i < sz; i++) { - rv.add(_sessionTags.valueAt(i)); - } - return rv; - } - /** * first tag still available, or null * inbound only @@ -407,8 +388,8 @@ class RatchetTagSet implements TagSetHandle { if (idx < 0) { Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class); if (log.shouldWarn()) - log.warn("Tag not found " + Base64.encode(tag.getData()) + - " Remaining tags: " + getTags(), new Exception()); + log.warn("Tag not found " + tag.toBase64() + + " in:\n" + toString(), new Exception()); return null; } _acked = true; @@ -443,7 +424,7 @@ class RatchetTagSet implements TagSetHandle { // dup or some other error Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class); if (log.shouldWarn()) - log.warn("No key found for tag " + Base64.encode(tag.getData()) + " at index " + idx + + log.warn("No key found for tag " + tag.toBase64() + " at index " + idx + " tagnum = " + tagnum + " lastkey = " + _lastKey, new Exception()); return null; } @@ -540,14 +521,9 @@ class RatchetTagSet implements TagSetHandle { return new SessionKeyAndNonce(key, _id, _lastKey, _remoteKey); } - /** - * For outbound only, call when we can use it. - */ - public void setAcked() { _acked = true; } - /** * For inbound, returns true after first consume() call. - * For outbound, returns true after set. + * For outbound, returns true after first consumeNextKey() call. */ public boolean getAcked() { return _acked; } @@ -584,11 +560,11 @@ class RatchetTagSet implements TagSetHandle { PublicKey pk = getRemoteKey(); if (pk != null) buf.append("\nRemote Public Key: ").append(pk.toBase64()); - buf.append("\nRoot Key: ").append(_key.toBase64()); + buf.append("\nRoot Key: ").append(_key.toBase64()); if (_tagsetKey != null) buf.append("\nTagset Key: ").append(_tagsetKey.toBase64()); if (_nextKey != null) - buf.append("\nNext Key: ").append(_nextKey); + buf.append("\nNext Key: ").append(_nextKey); int sz = size(); buf.append("\nSize: ").append(sz) .append(" Orig: ").append(_originalSize) @@ -601,36 +577,52 @@ class RatchetTagSet implements TagSetHandle { RatchetSessionTag tag = _sessionTags.valueAt(i); if (tag == null) continue; - buf.append("\n " + n + '\t' + Base64.encode(tag.getData())); + buf.append("\n ").append(n).append('\t').append(tag.toBase64()); if (_sessionKeys != null) { byte[] key = _sessionKeys.get(n); if (key != null) - buf.append('\t' + Base64.encode(key)); + buf.append('\t').append(Base64.encode(key)); else - buf.append("\tdeferred"); + buf.append("\tTBD"); } } } return buf.toString(); } + /** + * tags still available + * inbound only + * testing only + */ /**** + private List<RatchetSessionTag> getTags() { + if (_sessionTags == null) + return Collections.emptyList(); + int sz = _sessionTags.size(); + List<RatchetSessionTag> rv = new ArrayList<RatchetSessionTag>(sz); + for (int i = 0; i < sz; i++) { + rv.add(_sessionTags.valueAt(i)); + } + return rv; + } + public static void main(String[] args) { SessionKey k1 = new SessionKey(new byte[32]); SessionKey k2 = new SessionKey(new byte[32]); System.out.println("Send test"); HKDF hkdf = new HKDF(I2PAppContext.getGlobalContext()); - RatchetTagSet rts = new RatchetTagSet(hkdf, k1, k2, 0, 0); + RatchetTagSet rts = new RatchetTagSet(hkdf, k1, k2, 0, 0, 0); System.out.println("TAGNUM\tTAG\t\tKEY"); for (int i = 0; i < 20; i++) { RatchetSessionTag tag = rts.consumeNext(); SessionKey key = rts.consumeNextKey(); - System.out.println(i + "\t" + Base64.encode(tag.getData()) + '\t' + Base64.encode(key.getData())); + System.out.println(i + "\t" + tag.toBase64() + '\t' + key.toBase64()); } System.out.println("Size now: " + rts.size()); System.out.println(""); System.out.println("Receive test in-order"); - rts = new RatchetTagSet(hkdf, null, (PublicKey) null, k1, k2, 0, 0, 10, 50); + rts = new RatchetTagSet(hkdf, null, (PublicKey) null, k1, k2, 0, 0, 0, 10, 50); System.out.println("Size now: " + rts.size()); List<RatchetSessionTag> tags = rts.getTags(); int j = 0; @@ -638,22 +630,22 @@ class RatchetTagSet implements TagSetHandle { for (RatchetSessionTag tag : tags) { SessionKey key = rts.consume(tag); if (key != null) - System.out.println(j++ + "\t" + Base64.encode(tag.getData()) + '\t' + Base64.encode(key.getData())); + System.out.println(j++ + "\t" + tag.toBase64() + '\t' + key.toBase64()); else - System.out.println(j++ + "\t" + Base64.encode(tag.getData()) + "\t NOT FOUND"); + System.out.println(j++ + "\t" + tag.toBase64() + "\t NOT FOUND"); } for (int i = 11; i <= 20; i++) { RatchetSessionTag tag = rts.getFirstTag(); SessionKey key = rts.consume(tag); if (key != null) - System.out.println(i + "\t" + Base64.encode(tag.getData()) + '\t' + Base64.encode(key.getData())); + System.out.println(i + "\t" + tag.toBase64() + '\t' + key.toBase64()); else - System.out.println(i + "\t" + Base64.encode(tag.getData()) + "\t NOT FOUND"); + System.out.println(i + "\t" + tag.toBase64() + "\t NOT FOUND"); } System.out.println("Size now: " + rts.size()); System.out.println(""); System.out.println("Receive test out of order"); - rts = new RatchetTagSet(hkdf, null, (PublicKey) null, k1, k2, 0, 0, 10, 50); + rts = new RatchetTagSet(hkdf, null, (PublicKey) null, k1, k2, 0, 0, 0, 10, 50); System.out.println("Size now: " + rts.size()); tags = rts.getTags(); List<RatchetSessionTag> origtags = new ArrayList<RatchetSessionTag>(tags);