forked from I2P_Developers/i2p.i2p
Ratchet: Next Key WIP
This commit is contained in:
@ -510,6 +510,11 @@ public final class ECIESAEADEngine {
|
|||||||
if (_log.shouldWarn())
|
if (_log.shouldWarn())
|
||||||
_log.warn("No garlic block in ES payload");
|
_log.warn("No garlic block in ES payload");
|
||||||
}
|
}
|
||||||
|
if (pc.nextKeys != null) {
|
||||||
|
for (NextSessionKey nextKey : pc.nextKeys) {
|
||||||
|
keyManager.nextKeyReceived(remote, nextKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (pc.ackRequested) {
|
if (pc.ackRequested) {
|
||||||
keyManager.ackRequested(remote, key.getID(), nonce);
|
keyManager.ackRequested(remote, key.getID(), nonce);
|
||||||
}
|
}
|
||||||
@ -667,7 +672,7 @@ public final class ECIESAEADEngine {
|
|||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("State before encrypt new session: " + state);
|
_log.debug("State before encrypt new session: " + state);
|
||||||
|
|
||||||
byte[] payload = createPayload(cloves, cloves.getExpiration(), false, null, null);
|
byte[] payload = createPayload(cloves, cloves.getExpiration());
|
||||||
|
|
||||||
byte[] enc = new byte[KEYLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
byte[] enc = new byte[KEYLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
||||||
try {
|
try {
|
||||||
@ -726,7 +731,7 @@ public final class ECIESAEADEngine {
|
|||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("State after mixhash tag before encrypt new session reply: " + state);
|
_log.debug("State after mixhash tag before encrypt new session reply: " + state);
|
||||||
|
|
||||||
byte[] payload = createPayload(cloves, 0, false, null, null);
|
byte[] payload = createPayload(cloves, 0);
|
||||||
|
|
||||||
// part 1 - tag and empty payload
|
// part 1 - tag and empty payload
|
||||||
byte[] enc = new byte[TAGLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
byte[] enc = new byte[TAGLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
||||||
@ -793,7 +798,7 @@ public final class ECIESAEADEngine {
|
|||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager) {
|
||||||
boolean ackreq = callback != null || ACKREQ_IN_ES;
|
boolean ackreq = callback != null || ACKREQ_IN_ES;
|
||||||
byte rawTag[] = re.tag.getData();
|
byte rawTag[] = re.tag.getData();
|
||||||
byte[] payload = createPayload(cloves, 0, ackreq, re.nextKey, re.acksToSend);
|
byte[] payload = createPayload(cloves, 0, ackreq, re.nextForwardKey, re.nextReverseKey, re.acksToSend);
|
||||||
SessionKeyAndNonce key = re.key;
|
SessionKeyAndNonce key = re.key;
|
||||||
int nonce = key.getNonce();
|
int nonce = key.getNonce();
|
||||||
byte encr[] = encryptAEADBlock(rawTag, payload, key, nonce);
|
byte encr[] = encryptAEADBlock(rawTag, payload, key, nonce);
|
||||||
@ -823,7 +828,7 @@ public final class ECIESAEADEngine {
|
|||||||
*/
|
*/
|
||||||
public byte[] encrypt(CloveSet cloves, SessionKey key, RatchetSessionTag tag) {
|
public byte[] encrypt(CloveSet cloves, SessionKey key, RatchetSessionTag tag) {
|
||||||
byte rawTag[] = tag.getData();
|
byte rawTag[] = tag.getData();
|
||||||
byte[] payload = createPayload(cloves, 0, false, null, null);
|
byte[] payload = createPayload(cloves, 0);
|
||||||
byte encr[] = encryptAEADBlock(rawTag, payload, key, 0);
|
byte encr[] = encryptAEADBlock(rawTag, payload, key, 0);
|
||||||
System.arraycopy(rawTag, 0, encr, 0, TAGLEN);
|
System.arraycopy(rawTag, 0, encr, 0, TAGLEN);
|
||||||
return encr;
|
return encr;
|
||||||
@ -857,7 +862,7 @@ public final class ECIESAEADEngine {
|
|||||||
return enc;
|
return enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final PrivateKey doDH(PrivateKey privkey, PublicKey pubkey) {
|
static final PrivateKey doDH(PrivateKey privkey, PublicKey pubkey) {
|
||||||
byte[] dh = new byte[KEYLEN];
|
byte[] dh = new byte[KEYLEN];
|
||||||
Curve25519.eval(dh, 0, privkey.getData(), pubkey.getData());
|
Curve25519.eval(dh, 0, privkey.getData(), pubkey.getData());
|
||||||
return new PrivateKey(EncType.ECIES_X25519, dh);
|
return new PrivateKey(EncType.ECIES_X25519, dh);
|
||||||
@ -868,11 +873,13 @@ public final class ECIESAEADEngine {
|
|||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private class PLCallback implements RatchetPayload.PayloadCallback {
|
private class PLCallback implements RatchetPayload.PayloadCallback {
|
||||||
|
/** non null, may be empty */
|
||||||
public final List<GarlicClove> cloveSet = new ArrayList<GarlicClove>(3);
|
public final List<GarlicClove> cloveSet = new ArrayList<GarlicClove>(3);
|
||||||
private final RatchetSKM skm;
|
private final RatchetSKM skm;
|
||||||
private final PublicKey remote;
|
private final PublicKey remote;
|
||||||
public long datetime;
|
public long datetime;
|
||||||
public NextSessionKey nextKey;
|
/** null or non-empty */
|
||||||
|
public List<NextSessionKey> nextKeys;
|
||||||
public boolean ackRequested;
|
public boolean ackRequested;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -920,7 +927,11 @@ public final class ECIESAEADEngine {
|
|||||||
public void gotNextKey(NextSessionKey next) {
|
public void gotNextKey(NextSessionKey next) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Got NEXTKEY block: " + next);
|
_log.debug("Got NEXTKEY block: " + next);
|
||||||
nextKey = next;
|
// could have both a forward and reverse.
|
||||||
|
// shouldn't have two forwards or two reverses
|
||||||
|
if (nextKeys == null)
|
||||||
|
nextKeys = new ArrayList<NextSessionKey>(2);
|
||||||
|
nextKeys.add(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gotAck(int id, int n) {
|
public void gotAck(int id, int n) {
|
||||||
@ -954,21 +965,33 @@ public final class ECIESAEADEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param expiration if greater than zero, add a DateTime block
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
private byte[] createPayload(CloveSet cloves, long expiration) {
|
||||||
|
return createPayload(cloves, expiration, false, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param expiration if greater than zero, add a DateTime block
|
* @param expiration if greater than zero, add a DateTime block
|
||||||
* @param ackreq to request an ack, must be false for NS/NSR
|
* @param ackreq to request an ack, must be false for NS/NSR
|
||||||
|
* @param nextKey1 may be null
|
||||||
|
* @param nextKey2 may be null
|
||||||
* @param acksTOSend may be null
|
* @param acksTOSend may be null
|
||||||
*/
|
*/
|
||||||
private byte[] createPayload(CloveSet cloves, long expiration,
|
private byte[] createPayload(CloveSet cloves, long expiration,
|
||||||
boolean ackreq, NextSessionKey nextKey,
|
boolean ackreq, NextSessionKey nextKey1,
|
||||||
List<Integer> acksToSend) {
|
NextSessionKey nextKey2, List<Integer> acksToSend) {
|
||||||
int count = cloves.getCloveCount();
|
int count = cloves.getCloveCount();
|
||||||
int numblocks = count + 1;
|
int numblocks = count + 1;
|
||||||
if (expiration > 0)
|
if (expiration > 0)
|
||||||
numblocks++;
|
numblocks++;
|
||||||
if (ackreq)
|
if (ackreq)
|
||||||
numblocks++;
|
numblocks++;
|
||||||
if (nextKey != null)
|
if (nextKey1 != null)
|
||||||
|
numblocks++;
|
||||||
|
if (nextKey2 != null)
|
||||||
numblocks++;
|
numblocks++;
|
||||||
if (acksToSend != null)
|
if (acksToSend != null)
|
||||||
numblocks++;
|
numblocks++;
|
||||||
@ -979,8 +1002,13 @@ public final class ECIESAEADEngine {
|
|||||||
blocks.add(block);
|
blocks.add(block);
|
||||||
len += block.getTotalLength();
|
len += block.getTotalLength();
|
||||||
}
|
}
|
||||||
if (nextKey != null) {
|
if (nextKey1 != null) {
|
||||||
Block block = new NextKeyBlock(nextKey);
|
Block block = new NextKeyBlock(nextKey1);
|
||||||
|
blocks.add(block);
|
||||||
|
len += block.getTotalLength();
|
||||||
|
}
|
||||||
|
if (nextKey2 != null) {
|
||||||
|
Block block = new NextKeyBlock(nextKey2);
|
||||||
blocks.add(block);
|
blocks.add(block);
|
||||||
len += block.getTotalLength();
|
len += block.getTotalLength();
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ class NextSessionKey extends PublicKey {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder buf = new StringBuilder(64);
|
StringBuilder buf = new StringBuilder(64);
|
||||||
buf.append("[NextSessionKey: ");
|
buf.append("[NextSessionKey: ");
|
||||||
buf.append(toBase64());
|
buf.append(super.toString());
|
||||||
buf.append(" ID: ").append(_id);
|
buf.append(" ID: ").append(_id);
|
||||||
buf.append(" reverse? ").append(_isReverse);
|
buf.append(" reverse? ").append(_isReverse);
|
||||||
buf.append(" request? ").append(_isRequest);
|
buf.append(" request? ").append(_isRequest);
|
||||||
|
@ -6,7 +6,7 @@ import net.i2p.data.SessionKey;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple object with outbound tag, key, and nonce,
|
* Simple object with outbound tag, key, and nonce,
|
||||||
* and an optional next key.
|
* and an optional next keys.
|
||||||
* The object returned from SKM.consumeNextAvailableTag() to the engine encrypt.
|
* The object returned from SKM.consumeNextAvailableTag() to the engine encrypt.
|
||||||
*
|
*
|
||||||
* @since 0.9.44
|
* @since 0.9.44
|
||||||
@ -16,21 +16,23 @@ class RatchetEntry {
|
|||||||
public final SessionKeyAndNonce key;
|
public final SessionKeyAndNonce key;
|
||||||
public final int keyID;
|
public final int keyID;
|
||||||
public final int pn;
|
public final int pn;
|
||||||
public final NextSessionKey nextKey;
|
public final NextSessionKey nextForwardKey;
|
||||||
|
public final NextSessionKey nextReverseKey;
|
||||||
public final List<Integer> acksToSend;
|
public final List<Integer> acksToSend;
|
||||||
|
|
||||||
/** outbound - calculated key */
|
/** outbound - calculated key */
|
||||||
public RatchetEntry(RatchetSessionTag tag, SessionKeyAndNonce key, int keyID, int pn) {
|
public RatchetEntry(RatchetSessionTag tag, SessionKeyAndNonce key, int keyID, int pn) {
|
||||||
this(tag, key, keyID, pn, null, null);
|
this(tag, key, keyID, pn, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RatchetEntry(RatchetSessionTag tag, SessionKeyAndNonce key, int keyID, int pn,
|
public RatchetEntry(RatchetSessionTag tag, SessionKeyAndNonce key, int keyID, int pn,
|
||||||
NextSessionKey nextKey, List<Integer> acksToSend) {
|
NextSessionKey nextFwdKey, NextSessionKey nextRevKey, List<Integer> acksToSend) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.keyID = keyID;
|
this.keyID = keyID;
|
||||||
this.pn = pn;
|
this.pn = pn;
|
||||||
this.nextKey = nextKey;
|
this.nextForwardKey = nextFwdKey;
|
||||||
|
this.nextReverseKey = nextRevKey;
|
||||||
this.acksToSend = acksToSend;
|
this.acksToSend = acksToSend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,12 @@ import com.southernstorm.noise.protocol.HandshakeState;
|
|||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.EncType;
|
import net.i2p.crypto.EncType;
|
||||||
import net.i2p.crypto.HKDF;
|
import net.i2p.crypto.HKDF;
|
||||||
|
import net.i2p.crypto.KeyPair;
|
||||||
import net.i2p.crypto.SessionKeyManager;
|
import net.i2p.crypto.SessionKeyManager;
|
||||||
import net.i2p.crypto.TagSetHandle;
|
import net.i2p.crypto.TagSetHandle;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.data.PrivateKey;
|
||||||
import net.i2p.data.PublicKey;
|
import net.i2p.data.PublicKey;
|
||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
import net.i2p.data.SessionTag;
|
import net.i2p.data.SessionTag;
|
||||||
@ -241,8 +243,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
_log.info("Session " + state.hashCode() + " update as Bob. Alice: " + toString(target));
|
_log.info("Session " + state.hashCode() + " update as Bob. Alice: " + toString(target));
|
||||||
OutboundSession sess = getSession(target);
|
OutboundSession sess = getSession(target);
|
||||||
if (sess == null) {
|
if (sess == null) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldWarn())
|
||||||
_log.debug("Update Bob session but no session found for " + target);
|
_log.warn("Update Bob session but no session found for " + target);
|
||||||
// TODO can we recover?
|
// TODO can we recover?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -304,6 +306,19 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public void nextKeyReceived(PublicKey target, NextSessionKey key) {
|
||||||
|
OutboundSession sess = getSession(target);
|
||||||
|
if (sess == null) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got NextKey but no session found for " + target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sess.nextKeyReceived(key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws UnsupportedOperationException always
|
* @throws UnsupportedOperationException always
|
||||||
*/
|
*/
|
||||||
@ -793,7 +808,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
for (RatchetTagSet ts : sets) {
|
for (RatchetTagSet ts : sets) {
|
||||||
int size = ts.size();
|
int size = ts.size();
|
||||||
total += size;
|
total += size;
|
||||||
buf.append("<li><b>ID: ").append(ts.getID());
|
buf.append("<li><b>ID: ").append(ts.getID())
|
||||||
|
.append(" / ").append(ts.getDebugID());
|
||||||
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
long expires = ts.getExpiration() - now;
|
long expires = ts.getExpiration() - now;
|
||||||
@ -835,6 +851,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
for (RatchetTagSet ts : sets) {
|
for (RatchetTagSet ts : sets) {
|
||||||
int size = ts.remaining();
|
int size = ts.remaining();
|
||||||
buf.append("<li><b>ID: ").append(ts.getID())
|
buf.append("<li><b>ID: ").append(ts.getID())
|
||||||
|
.append(" / ").append(ts.getDebugID())
|
||||||
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
long expires = ts.getExpiration() - now;
|
long expires = ts.getExpiration() - now;
|
||||||
@ -914,6 +931,14 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
*/
|
*/
|
||||||
private int _consecutiveFailures;
|
private int _consecutiveFailures;
|
||||||
|
|
||||||
|
// next key
|
||||||
|
private int _myOBKeyID = -1;
|
||||||
|
private int _hisOBKeyID = -1;
|
||||||
|
private int _currentOBTagSetID;
|
||||||
|
private int _myIBKeyID = -1;
|
||||||
|
private int _hisIBKeyID = -1;
|
||||||
|
private int _currentIBTagSetID;
|
||||||
|
|
||||||
private static final int MAX_FAILS = 2;
|
private static final int MAX_FAILS = 2;
|
||||||
private static final int MAX_SEND_ACKS = 8;
|
private static final int MAX_SEND_ACKS = 8;
|
||||||
private static final int DEBUG_OB_NSR = 0x10001;
|
private static final int DEBUG_OB_NSR = 0x10001;
|
||||||
@ -1024,6 +1049,76 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
//state.destroy();
|
//state.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public void nextKeyReceived(NextSessionKey key) {
|
||||||
|
boolean isReverse = key.isReverse();
|
||||||
|
boolean isRequest = key.isRequest();
|
||||||
|
boolean hasKey = key.getData() != null;
|
||||||
|
int id = key.getID();
|
||||||
|
synchronized (_tagSets) {
|
||||||
|
if (isReverse) {
|
||||||
|
// this is about my outbound tag set,
|
||||||
|
// and is an ack of new key sent
|
||||||
|
if (_hisIBKeyID != id) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got new key id, ratchet OB " + id);
|
||||||
|
if (_hisIBKeyID != id + 1) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got bad new key id OB? " + id);
|
||||||
|
}
|
||||||
|
if (hasKey) {
|
||||||
|
KeyPair nextKeys = _context.keyGenerator().generatePKIKeys(EncType.ECIES_X25519);
|
||||||
|
PublicKey pub = nextKeys.getPublic();
|
||||||
|
PrivateKey priv = nextKeys.getPrivate();
|
||||||
|
PrivateKey sharedSecret = ECIESAEADEngine.doDH(priv, key);
|
||||||
|
// create new OB TS
|
||||||
|
// find current OB TS, and delete it
|
||||||
|
} else {
|
||||||
|
// TODO get it from above
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got nextkey w/o key but we don't have it " + id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got dup new key id for OB " + id);
|
||||||
|
}
|
||||||
|
if (isRequest) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("invalid req+rev in nextkey");
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// this is about my inbound tag set
|
||||||
|
if (_hisOBKeyID != id) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got new key id, ratchet IB " + id);
|
||||||
|
if (_hisOBKeyID != id + 1) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got bad new key id IB? " + id);
|
||||||
|
}
|
||||||
|
if (!hasKey) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got nextkey w/o key but we don't have it " + id);
|
||||||
|
}
|
||||||
|
// find current OB TS, tell him to send ack
|
||||||
|
// create new IB TS
|
||||||
|
} else {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Got dup new key id for IB " + id);
|
||||||
|
// find current OB TS, tell him to send ack if nec.
|
||||||
|
// create new IB TS if nec.
|
||||||
|
}
|
||||||
|
if (!isRequest) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("invalid fwd w/o req in nextkey");
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First tag was received for this inbound (ES) tagset.
|
* First tag was received for this inbound (ES) tagset.
|
||||||
* Find the corresponding outbound (ES) tagset in _unackedTagSets,
|
* Find the corresponding outbound (ES) tagset in _unackedTagSets,
|
||||||
@ -1190,7 +1285,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
set.setDate(now);
|
set.setDate(now);
|
||||||
SessionKeyAndNonce skn = set.consumeNextKey();
|
SessionKeyAndNonce skn = set.consumeNextKey();
|
||||||
// TODO PN
|
// TODO PN
|
||||||
return new RatchetEntry(tag, skn, set.getID(), 0, set.getNextKey(), getAcksToSend());
|
// TODO reverse next key
|
||||||
|
return new RatchetEntry(tag, skn, set.getID(), 0, set.getNextKey(), null, getAcksToSend());
|
||||||
} else if (_log.shouldInfo()) {
|
} else if (_log.shouldInfo()) {
|
||||||
_log.info("Removing empty " + set);
|
_log.info("Removing empty " + set);
|
||||||
}
|
}
|
||||||
|
@ -263,6 +263,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
* @since 0.9.46
|
* @since 0.9.46
|
||||||
*/
|
*/
|
||||||
public synchronized long getExpiration() {
|
public synchronized long getExpiration() {
|
||||||
|
// TODO return shorter if not acked?
|
||||||
return _date + _timeout;
|
return _date + _timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,8 +300,9 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next Key if applicable
|
* Next Forward Key if applicable (we're running low).
|
||||||
* null if remaining is sufficient
|
* Null if remaining is sufficient.
|
||||||
|
* Once non-null, will be constant for the remaining life of the tagset.
|
||||||
*
|
*
|
||||||
* @return key or null
|
* @return key or null
|
||||||
* @since 0.9.46
|
* @since 0.9.46
|
||||||
@ -308,8 +310,6 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
public NextSessionKey getNextKey() {
|
public NextSessionKey getNextKey() {
|
||||||
if (remaining() > LOW)
|
if (remaining() > LOW)
|
||||||
return null;
|
return null;
|
||||||
if (_nextKeyAcked) // maybe not needed, keep sending until unused
|
|
||||||
return null;
|
|
||||||
if (_nextKeys == null) {
|
if (_nextKeys == null) {
|
||||||
_nextKeys = I2PAppContext.getGlobalContext().keyGenerator().generatePKIKeys(EncType.ECIES_X25519);
|
_nextKeys = I2PAppContext.getGlobalContext().keyGenerator().generatePKIKeys(EncType.ECIES_X25519);
|
||||||
boolean isIB = _sessionTags != null;
|
boolean isIB = _sessionTags != null;
|
||||||
@ -319,6 +319,18 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
return _nextKey;
|
return _nextKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Next Forward KeyPair if applicable (we're running low).
|
||||||
|
* Null if remaining is sufficient.
|
||||||
|
* Once non-null, will be constant for the remaining life of the tagset.
|
||||||
|
*
|
||||||
|
* @return keys or null
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public KeyPair getNextKeys() {
|
||||||
|
return _nextKeys;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tags still available
|
* tags still available
|
||||||
* inbound only
|
* inbound only
|
||||||
@ -502,11 +514,21 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public boolean getAcked() { return _acked; }
|
public boolean getAcked() { return _acked; }
|
||||||
|
|
||||||
/** the Key ID */
|
/**
|
||||||
|
* The TagSet ID, starting at 0.
|
||||||
|
* After that = 1 + my key id + his key id
|
||||||
|
*/
|
||||||
public int getID() {
|
public int getID() {
|
||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique ID for debugging only
|
||||||
|
*/
|
||||||
|
public int getDebugID() {
|
||||||
|
return _tagSetID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String toString() {
|
public synchronized String toString() {
|
||||||
StringBuilder buf = new StringBuilder(256);
|
StringBuilder buf = new StringBuilder(256);
|
||||||
|
Reference in New Issue
Block a user