Ratchet: TagSet cleanups

Tag.toBase64() optimization
Javadoc fixes
This commit is contained in:
zzz
2020-04-08 13:16:15 +00:00
parent 1752291ffd
commit 3fa15824ee
4 changed files with 70 additions and 52 deletions

View File

@ -304,8 +304,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
* Preliminary, not fully supported, see proposal 154. * Preliminary, not fully supported, see proposal 154.
* *
* @throws IllegalStateException if key or tag previously set, to protect saved checksum * @throws IllegalStateException if key or tag previously set, to protect saved checksum
* @param encryptKey non-null * @param pubKey non-null
* @param encryptTag non-null
* @since 0.9.46 * @since 0.9.46
*/ */
public void setReplySession(PublicKey pubKey) { public void setReplySession(PublicKey pubKey) {

View File

@ -67,7 +67,6 @@ class RatchetPayload {
public void gotAck(int id, int n); public void gotAck(int id, int n);
/** /**
* @param di may be null
* @since 0.9.46 * @since 0.9.46
*/ */
public void gotAckRequest(); public void gotAckRequest();

View File

@ -1,11 +1,9 @@
package net.i2p.router.crypto.ratchet; package net.i2p.router.crypto.ratchet;
import java.util.Arrays;
import net.i2p.data.Base64; 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 * Does not extend SessionTag or DataStructure to save space
* *
* @since 0.9.44 * @since 0.9.44
@ -25,18 +23,38 @@ public class RatchetSessionTag {
_data = RatchetPayload.fromLong8(val, 0); _data = RatchetPayload.fromLong8(val, 0);
} }
/**
* @return data as a byte array
*/
public byte[] getData() { public byte[] getData() {
byte[] rv = new byte[LENGTH]; byte[] rv = new byte[LENGTH];
RatchetPayload.toLong8(rv, 0, _data); RatchetPayload.toLong8(rv, 0, _data);
return rv; return rv;
} }
/**
* @return data as a long value
* @since 0.9.46
*/
public long getLong() {
return _data;
}
public int length() { public int length() {
return LENGTH; return LENGTH;
} }
/** 12 chars */
public String toBase64() { 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 @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder(64); StringBuilder buf = new StringBuilder(33);
buf.append("[RatchetSessionTag: "); buf.append("[RatchetSessionTag: ");
buf.append(toBase64()); buf.append(toBase64());
buf.append(']'); buf.append(']');
return buf.toString(); 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()));
}
****/
} }

View File

@ -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. * Not used for cryptographic operations after setup.
*/ */
public SessionKey getAssociatedKey() { public SessionKey getAssociatedKey() {
@ -285,11 +287,6 @@ class RatchetTagSet implements TagSetHandle {
return _created + Math.min(_timeout, RatchetSKM.SESSION_PENDING_DURATION_MS); return _created + Math.min(_timeout, RatchetSKM.SESSION_PENDING_DURATION_MS);
} }
/** for debugging */
public int getOriginalSize() {
return _originalSize;
}
/** /**
* unused tags generated * unused tags generated
* @return 0 for outbound * @return 0 for outbound
@ -365,22 +362,6 @@ class RatchetTagSet implements TagSetHandle {
return new SessionKey(_nextRootKey); 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 * first tag still available, or null
* inbound only * inbound only
@ -407,8 +388,8 @@ class RatchetTagSet implements TagSetHandle {
if (idx < 0) { if (idx < 0) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class); Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class);
if (log.shouldWarn()) if (log.shouldWarn())
log.warn("Tag not found " + Base64.encode(tag.getData()) + log.warn("Tag not found " + tag.toBase64() +
" Remaining tags: " + getTags(), new Exception()); " in:\n" + toString(), new Exception());
return null; return null;
} }
_acked = true; _acked = true;
@ -443,7 +424,7 @@ class RatchetTagSet implements TagSetHandle {
// dup or some other error // dup or some other error
Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class); Log log = I2PAppContext.getGlobalContext().logManager().getLog(RatchetTagSet.class);
if (log.shouldWarn()) 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()); " tagnum = " + tagnum + " lastkey = " + _lastKey, new Exception());
return null; return null;
} }
@ -540,14 +521,9 @@ class RatchetTagSet implements TagSetHandle {
return new SessionKeyAndNonce(key, _id, _lastKey, _remoteKey); 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 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; } public boolean getAcked() { return _acked; }
@ -584,11 +560,11 @@ class RatchetTagSet implements TagSetHandle {
PublicKey pk = getRemoteKey(); PublicKey pk = getRemoteKey();
if (pk != null) if (pk != null)
buf.append("\nRemote Public Key: ").append(pk.toBase64()); 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) if (_tagsetKey != null)
buf.append("\nTagset Key: ").append(_tagsetKey.toBase64()); buf.append("\nTagset Key: ").append(_tagsetKey.toBase64());
if (_nextKey != null) if (_nextKey != null)
buf.append("\nNext Key: ").append(_nextKey); buf.append("\nNext Key: ").append(_nextKey);
int sz = size(); int sz = size();
buf.append("\nSize: ").append(sz) buf.append("\nSize: ").append(sz)
.append(" Orig: ").append(_originalSize) .append(" Orig: ").append(_originalSize)
@ -601,36 +577,52 @@ class RatchetTagSet implements TagSetHandle {
RatchetSessionTag tag = _sessionTags.valueAt(i); RatchetSessionTag tag = _sessionTags.valueAt(i);
if (tag == null) if (tag == null)
continue; continue;
buf.append("\n " + n + '\t' + Base64.encode(tag.getData())); buf.append("\n ").append(n).append('\t').append(tag.toBase64());
if (_sessionKeys != null) { if (_sessionKeys != null) {
byte[] key = _sessionKeys.get(n); byte[] key = _sessionKeys.get(n);
if (key != null) if (key != null)
buf.append('\t' + Base64.encode(key)); buf.append('\t').append(Base64.encode(key));
else else
buf.append("\tdeferred"); buf.append("\tTBD");
} }
} }
} }
return buf.toString(); 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) { public static void main(String[] args) {
SessionKey k1 = new SessionKey(new byte[32]); SessionKey k1 = new SessionKey(new byte[32]);
SessionKey k2 = new SessionKey(new byte[32]); SessionKey k2 = new SessionKey(new byte[32]);
System.out.println("Send test"); System.out.println("Send test");
HKDF hkdf = new HKDF(I2PAppContext.getGlobalContext()); 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"); System.out.println("TAGNUM\tTAG\t\tKEY");
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
RatchetSessionTag tag = rts.consumeNext(); RatchetSessionTag tag = rts.consumeNext();
SessionKey key = rts.consumeNextKey(); 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("Size now: " + rts.size());
System.out.println(""); System.out.println("");
System.out.println("Receive test in-order"); 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()); System.out.println("Size now: " + rts.size());
List<RatchetSessionTag> tags = rts.getTags(); List<RatchetSessionTag> tags = rts.getTags();
int j = 0; int j = 0;
@ -638,22 +630,22 @@ class RatchetTagSet implements TagSetHandle {
for (RatchetSessionTag tag : tags) { for (RatchetSessionTag tag : tags) {
SessionKey key = rts.consume(tag); SessionKey key = rts.consume(tag);
if (key != null) 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 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++) { for (int i = 11; i <= 20; i++) {
RatchetSessionTag tag = rts.getFirstTag(); RatchetSessionTag tag = rts.getFirstTag();
SessionKey key = rts.consume(tag); SessionKey key = rts.consume(tag);
if (key != null) 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 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("Size now: " + rts.size());
System.out.println(""); System.out.println("");
System.out.println("Receive test out of order"); 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()); System.out.println("Size now: " + rts.size());
tags = rts.getTags(); tags = rts.getTags();
List<RatchetSessionTag> origtags = new ArrayList<RatchetSessionTag>(tags); List<RatchetSessionTag> origtags = new ArrayList<RatchetSessionTag>(tags);