forked from I2P_Developers/i2p.i2p
Ratchet: Bob transition to ES
Store PK in RTS New RST constructor Log tweaks (lots)
This commit is contained in:
@ -161,11 +161,11 @@ public final class ECIESAEADEngine {
|
|||||||
HandshakeState state = key.getHandshakeState();
|
HandshakeState state = key.getHandshakeState();
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
if (shouldDebug)
|
if (shouldDebug)
|
||||||
_log.debug("Decrypting ES with tag: " + st + ": key: " + key.toBase64() + ": " + data.length + " bytes");
|
_log.debug("Decrypting ES with tag: " + st.toBase64() + ": key: " + key.toBase64() + ": " + data.length + " bytes");
|
||||||
decrypted = decryptExistingSession(tag, data, key, targetPrivateKey);
|
decrypted = decryptExistingSession(tag, data, key, targetPrivateKey);
|
||||||
} else if (data.length >= MIN_NSR_SIZE) {
|
} else if (data.length >= MIN_NSR_SIZE) {
|
||||||
if (shouldDebug)
|
if (shouldDebug)
|
||||||
_log.debug("Decrypting NSR with tag: " + st + ": key: " + key.toBase64() + ": " + data.length + " bytes");
|
_log.debug("Decrypting NSR with tag: " + st.toBase64() + ": key: " + key.toBase64() + ": " + data.length + " bytes");
|
||||||
decrypted = decryptNewSessionReply(tag, data, state, keyManager);
|
decrypted = decryptNewSessionReply(tag, data, state, keyManager);
|
||||||
} else {
|
} else {
|
||||||
decrypted = null;
|
decrypted = null;
|
||||||
@ -562,11 +562,11 @@ public final class ECIESAEADEngine {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Encrypting as NSR to " + target + " with tag " + re.tag);
|
_log.debug("Encrypting as NSR to " + target + " with tag " + re.tag.toBase64());
|
||||||
return encryptNewSessionReply(cloves, target, state, re.tag, keyManager);
|
return encryptNewSessionReply(cloves, target, state, re.tag, keyManager);
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Encrypting as ES to " + target + " with key " + re.key + " and tag " + re.tag);
|
_log.debug("Encrypting as ES to " + target + " with key " + re.key + " and tag " + re.tag.toBase64());
|
||||||
byte rv[] = encryptExistingSession(cloves, target, re.key, re.tag);
|
byte rv[] = encryptExistingSession(cloves, target, re.key, re.tag);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -722,7 +722,7 @@ public final class ECIESAEADEngine {
|
|||||||
/**
|
/**
|
||||||
* No ad
|
* No ad
|
||||||
*/
|
*/
|
||||||
final byte[] encryptAEADBlock(byte data[], SessionKey key, long n) {
|
private final byte[] encryptAEADBlock(byte data[], SessionKey key, long n) {
|
||||||
return encryptAEADBlock(null, data, key, n);
|
return encryptAEADBlock(null, data, key, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +176,7 @@ public class MuxedSKM extends SessionKeyManager {
|
|||||||
public SessionKey consumeTag(SessionTag tag) {
|
public SessionKey consumeTag(SessionTag tag) {
|
||||||
SessionKey rv = _elg.consumeTag(tag);
|
SessionKey rv = _elg.consumeTag(tag);
|
||||||
if (rv == null) {
|
if (rv == null) {
|
||||||
byte[] stag = new byte[8];
|
long stag = RatchetPayload.fromLong8(tag.getData(), 0);
|
||||||
System.arraycopy(tag.getData(), 0, stag, 0, 8);
|
|
||||||
RatchetSessionTag rstag = new RatchetSessionTag(stag);
|
RatchetSessionTag rstag = new RatchetSessionTag(stag);
|
||||||
rv = _ec.consumeTag(rstag);
|
rv = _ec.consumeTag(rstag);
|
||||||
}
|
}
|
||||||
|
@ -178,9 +178,9 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
boolean rv = addSession(sess);
|
boolean rv = addSession(sess);
|
||||||
if (_log.shouldInfo()) {
|
if (_log.shouldInfo()) {
|
||||||
if (rv)
|
if (rv)
|
||||||
_log.info("New OB session as Bob. Alice: " + toString(target));
|
_log.info("New OB session " + state.hashCode() + " as Bob. Alice: " + toString(target));
|
||||||
else
|
else
|
||||||
_log.info("Dup OB session as Bob. Alice: " + toString(target));
|
_log.info("Dup OB session " + state.hashCode() + " as Bob. Alice: " + toString(target));
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
} else {
|
} else {
|
||||||
@ -191,14 +191,14 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (pending != null) {
|
if (pending != null) {
|
||||||
pending.add(sess);
|
pending.add(sess);
|
||||||
if (_log.shouldInfo())
|
if (_log.shouldInfo())
|
||||||
_log.info("Another new OB session as Alice, total now: " + pending.size() +
|
_log.info("Another new OB session " + state.hashCode() + " as Alice, total now: " + pending.size() +
|
||||||
". Bob: " + toString(target));
|
". Bob: " + toString(target));
|
||||||
} else {
|
} else {
|
||||||
pending = new ArrayList<OutboundSession>(4);
|
pending = new ArrayList<OutboundSession>(4);
|
||||||
pending.add(sess);
|
pending.add(sess);
|
||||||
_pendingOutboundSessions.put(target, pending);
|
_pendingOutboundSessions.put(target, pending);
|
||||||
if (_log.shouldInfo())
|
if (_log.shouldInfo())
|
||||||
_log.info("First new OB session as Alice. Bob: " + toString(target));
|
_log.info("First new OB session " + state.hashCode() + " as Alice. Bob: " + toString(target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -220,23 +220,25 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
boolean isInbound = state.getRole() == HandshakeState.RESPONDER;
|
boolean isInbound = state.getRole() == HandshakeState.RESPONDER;
|
||||||
if (isInbound) {
|
if (isInbound) {
|
||||||
// we are Bob, NSR sent
|
// we are Bob, NSR sent
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_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.shouldDebug())
|
||||||
_log.debug("Update session but no session found for " + target);
|
_log.debug("Update Bob session but no session found for " + target);
|
||||||
// TODO can we recover?
|
// TODO can we recover?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sess.updateSession(state);
|
sess.updateSession(state);
|
||||||
if (_log.shouldInfo())
|
|
||||||
_log.info("Session update as Bob. Alice: " + toString(target));
|
|
||||||
} else {
|
} else {
|
||||||
// we are Alice, NSR received
|
// we are Alice, NSR received
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("Session " + oldState.hashCode() + " to " + state.hashCode() + " update as Alice. Bob: " + toString(target));
|
||||||
synchronized (_pendingOutboundSessions) {
|
synchronized (_pendingOutboundSessions) {
|
||||||
List<OutboundSession> pending = _pendingOutboundSessions.get(target);
|
List<OutboundSession> pending = _pendingOutboundSessions.get(target);
|
||||||
if (pending == null) {
|
if (pending == null) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Update session but no sessions found for " + target);
|
_log.debug("Update Alice session but no pending sessions for " + target);
|
||||||
// TODO can we recover?
|
// TODO can we recover?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -250,7 +252,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
boolean ok = addSession(sess);
|
boolean ok = addSession(sess);
|
||||||
if (_log.shouldDebug()) {
|
if (_log.shouldDebug()) {
|
||||||
if (ok)
|
if (ok)
|
||||||
_log.debug("Update session from NSR to ES for " + target);
|
_log.debug("Update Alice session from NSR to ES for " + target);
|
||||||
else
|
else
|
||||||
_log.debug("Session already updated from NSR to ES for " + target);
|
_log.debug("Session already updated from NSR to ES for " + target);
|
||||||
}
|
}
|
||||||
@ -266,16 +268,15 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_pendingOutboundSessions.remove(target);
|
if (found) {
|
||||||
if (!found) {
|
_pendingOutboundSessions.remove(target);
|
||||||
|
} else {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Update session but no session found (out of " + pending.size() + ") for " + target);
|
_log.debug("Update Alice session but no session found (out of " + pending.size() + ") for " + target);
|
||||||
// TODO can we recover?
|
// TODO can we recover?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_log.shouldInfo())
|
|
||||||
_log.info("Session update as Alice. Bob: " + toString(target));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -520,8 +521,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
SessionKeyAndNonce key;
|
SessionKeyAndNonce key;
|
||||||
tagSet = _inboundTagSets.remove(tag);
|
tagSet = _inboundTagSets.remove(tag);
|
||||||
if (tagSet == null) {
|
if (tagSet == null) {
|
||||||
if (_log.shouldDebug())
|
//if (_log.shouldDebug())
|
||||||
_log.debug("IB tag not found: " + tag.toBase64());
|
// _log.debug("IB tag not found: " + tag.toBase64());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean firstInbound;
|
boolean firstInbound;
|
||||||
@ -535,14 +536,22 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
HandshakeState state = tagSet.getHandshakeState();
|
HandshakeState state = tagSet.getHandshakeState();
|
||||||
if (firstInbound) {
|
if (firstInbound) {
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
// TODO
|
// TODO this should really be after decrypt...
|
||||||
|
PublicKey pk = tagSet.getRemoteKey();
|
||||||
|
OutboundSession sess = getSession(pk);
|
||||||
|
if (sess != null) {
|
||||||
|
sess.firstTagConsumed(tagSet);
|
||||||
|
} else {
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("First tag consumed but session is gone");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug()) {
|
if (_log.shouldDebug()) {
|
||||||
if (state != null)
|
if (state != null)
|
||||||
_log.debug("IB NSR Tag consumed: " + tag + " from: " + tagSet);
|
_log.debug("IB NSR Tag consumed: " + tag.toBase64() + " from: " + tagSet);
|
||||||
else
|
else
|
||||||
_log.debug("IB ES Tag consumed: " + tag + " from: " + tagSet);
|
_log.debug("IB ES Tag consumed: " + tag.toBase64() + " from: " + tagSet);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldWarn())
|
if (_log.shouldWarn())
|
||||||
@ -838,12 +847,21 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
RatchetTagSet tagset = new RatchetTagSet(_hkdf, RatchetSKM.this, state,
|
RatchetTagSet tagset = new RatchetTagSet(_hkdf, RatchetSKM.this, state,
|
||||||
rk, tk,
|
rk, tk,
|
||||||
_established, _rcvTagSetID.getAndIncrement(), 5, 5);
|
_established, _rcvTagSetID.getAndIncrement(), 5, 5);
|
||||||
|
// store the IB tagset as OB so we can lookup the state
|
||||||
|
// TODO just store the state
|
||||||
_unackedTagSets.add(tagset);
|
_unackedTagSets.add(tagset);
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("New IB Session, rk = " + rk + " tk = " + tk + " 1st tagset: " + tagset);
|
_log.debug("New IB Session, rk = " + rk + " tk = " + tk + " 1st tagset: " + tagset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inbound or outbound. Checks state.getRole() to determine.
|
||||||
|
* For outbound (NSR rcvd by Alice), sets session to transition to ES mode outbound.
|
||||||
|
* For inbound (NSR sent by Bob), sets up inbound ES tagset.
|
||||||
|
*
|
||||||
|
* @param state current state
|
||||||
|
*/
|
||||||
void updateSession(HandshakeState state) {
|
void updateSession(HandshakeState state) {
|
||||||
byte[] ck = state.getChainingKey();
|
byte[] ck = state.getChainingKey();
|
||||||
byte[] k_ab = new byte[32];
|
byte[] k_ab = new byte[32];
|
||||||
@ -855,7 +873,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (isInbound) {
|
if (isInbound) {
|
||||||
// We are Bob
|
// We are Bob
|
||||||
// This is an OUTBOUND NSR, we make an INBOUND tagset for ES
|
// This is an OUTBOUND NSR, we make an INBOUND tagset for ES
|
||||||
RatchetTagSet tagset_ab = new RatchetTagSet(_hkdf, RatchetSKM.this, rk, new SessionKey(k_ab),
|
RatchetTagSet tagset_ab = new RatchetTagSet(_hkdf, RatchetSKM.this, _target, rk, new SessionKey(k_ab),
|
||||||
now, _rcvTagSetID.getAndIncrement(), 5, 5);
|
now, _rcvTagSetID.getAndIncrement(), 5, 5);
|
||||||
// and a pending outbound one
|
// and a pending outbound one
|
||||||
RatchetTagSet tagset_ba = new RatchetTagSet(_hkdf, rk, new SessionKey(k_ba),
|
RatchetTagSet tagset_ba = new RatchetTagSet(_hkdf, rk, new SessionKey(k_ba),
|
||||||
@ -873,7 +891,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
RatchetTagSet tagset_ab = new RatchetTagSet(_hkdf, rk, new SessionKey(k_ab),
|
RatchetTagSet tagset_ab = new RatchetTagSet(_hkdf, rk, new SessionKey(k_ab),
|
||||||
now, _sentTagSetID.getAndIncrement());
|
now, _sentTagSetID.getAndIncrement());
|
||||||
// and an inbound one
|
// and an inbound one
|
||||||
RatchetTagSet tagset_ba = new RatchetTagSet(_hkdf, RatchetSKM.this, rk, new SessionKey(k_ba),
|
RatchetTagSet tagset_ba = new RatchetTagSet(_hkdf, RatchetSKM.this, _target, rk, new SessionKey(k_ba),
|
||||||
now, _rcvTagSetID.getAndIncrement(), 5, 5);
|
now, _rcvTagSetID.getAndIncrement(), 5, 5);
|
||||||
if (_log.shouldDebug()) {
|
if (_log.shouldDebug()) {
|
||||||
_log.debug("Update OB Session, rk = " + rk + " tk = " + Base64.encode(k_ab) + " ES tagset: " + tagset_ab);
|
_log.debug("Update OB Session, rk = " + rk + " tk = " + Base64.encode(k_ab) + " ES tagset: " + tagset_ab);
|
||||||
@ -888,9 +906,37 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of RatchetTagSet objects
|
* First tag was received for this inbound (ES) tagset.
|
||||||
|
* Find the corresponding outbound (ES) tagset in _unackedTagSets,
|
||||||
|
* move it to _tagSets, and remove all others.
|
||||||
|
*
|
||||||
|
* @param set the inbound tagset
|
||||||
|
*/
|
||||||
|
void firstTagConsumed(RatchetTagSet set) {
|
||||||
|
SessionKey sk = set.getAssociatedKey();
|
||||||
|
synchronized (_tagSets) {
|
||||||
|
for (RatchetTagSet obSet : _unackedTagSets) {
|
||||||
|
if (obSet.getAssociatedKey().equals(sk)) {
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("First tag received from IB ES " + set +
|
||||||
|
", promoting OB ES " + obSet);
|
||||||
|
_unackedTagSets.clear();
|
||||||
|
_tagSets.clear();
|
||||||
|
_tagSets.add(obSet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("First tag received from IB ES " + set +
|
||||||
|
" but no corresponding OB ES set found, unacked size: " + _unackedTagSets.size() +
|
||||||
|
" acked size: " + _tagSets.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* This is used only by renderStatusHTML().
|
* This is used only by renderStatusHTML().
|
||||||
* It includes both acked and unacked RatchetTagSets.
|
* It includes both acked and unacked RatchetTagSets.
|
||||||
|
* @return list of RatchetTagSet objects
|
||||||
*/
|
*/
|
||||||
List<RatchetTagSet> getTagSets() {
|
List<RatchetTagSet> getTagSets() {
|
||||||
List<RatchetTagSet> rv;
|
List<RatchetTagSet> rv;
|
||||||
|
@ -15,6 +15,10 @@ public class RatchetSessionTag {
|
|||||||
|
|
||||||
private final long _data;
|
private final long _data;
|
||||||
|
|
||||||
|
public RatchetSessionTag(long val) {
|
||||||
|
_data = val;
|
||||||
|
}
|
||||||
|
|
||||||
public RatchetSessionTag(byte val[]) {
|
public RatchetSessionTag(byte val[]) {
|
||||||
if (val.length != LENGTH)
|
if (val.length != LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
@ -7,13 +7,16 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.southernstorm.noise.protocol.DHState;
|
||||||
import com.southernstorm.noise.protocol.HandshakeState;
|
import com.southernstorm.noise.protocol.HandshakeState;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.crypto.EncType;
|
||||||
import net.i2p.crypto.HKDF;
|
import net.i2p.crypto.HKDF;
|
||||||
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.PublicKey;
|
||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@ -32,6 +35,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
class RatchetTagSet implements TagSetHandle {
|
class RatchetTagSet implements TagSetHandle {
|
||||||
private final SessionTagListener _lsnr;
|
private final SessionTagListener _lsnr;
|
||||||
|
private final PublicKey _remoteKey;
|
||||||
private final SessionKey _key;
|
private final SessionKey _key;
|
||||||
private final HandshakeState _state;
|
private final HandshakeState _state;
|
||||||
// We use object for tags because we must do indexOfValueByValue()
|
// We use object for tags because we must do indexOfValueByValue()
|
||||||
@ -69,7 +73,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, HandshakeState state, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id) {
|
long date, int id) {
|
||||||
this(hkdf, null, state, rootKey, data, date, id, false, 0, 0);
|
this(hkdf, null, state, null, rootKey, data, date, id, false, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +83,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id) {
|
long date, int id) {
|
||||||
this(hkdf, null, null, rootKey, data, date, id, false, 0, 0);
|
this(hkdf, null, null, null, rootKey, data, date, id, false, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +93,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
this(hkdf, lsnr, state, rootKey, data, date, id, true, minSize, maxSize);
|
this(hkdf, lsnr, state, null, rootKey, data, date, id, true, minSize, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,19 +101,22 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*
|
*
|
||||||
* @param date For inbound: creation time
|
* @param date For inbound: creation time
|
||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr,
|
||||||
|
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
this(hkdf, lsnr, null, rootKey, data, date, id, true, minSize, maxSize);
|
this(hkdf, lsnr, null, remoteKey, rootKey, data, date, id, true, minSize, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param date For inbound and outbound: creation time
|
* @param date For inbound and outbound: creation time
|
||||||
*/
|
*/
|
||||||
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state,
|
||||||
|
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, boolean isInbound, int minSize, int maxSize) {
|
long date, int id, boolean isInbound, int minSize, int maxSize) {
|
||||||
_lsnr = lsnr;
|
_lsnr = lsnr;
|
||||||
_state = state;
|
_state = state;
|
||||||
|
_remoteKey = remoteKey;
|
||||||
_key = rootKey;
|
_key = rootKey;
|
||||||
_created = date;
|
_created = date;
|
||||||
_date = date;
|
_date = date;
|
||||||
@ -149,7 +156,24 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier for the session..
|
* The far-end's public key.
|
||||||
|
* Valid for NSR and inbound ES tagsets.
|
||||||
|
* Returns null for outbound ES tagsets.
|
||||||
|
*/
|
||||||
|
public PublicKey getRemoteKey() {
|
||||||
|
if (_state != null) {
|
||||||
|
DHState kp = _state.getRemotePublicKey();
|
||||||
|
if (kp != null) {
|
||||||
|
byte[] rv = new byte[32];
|
||||||
|
kp.getPublicKey(rv, 0);
|
||||||
|
return new PublicKey(EncType.ECIES_X25519, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _remoteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier for the session.
|
||||||
* Not used for cryptographic operations after setup.
|
* Not used for cryptographic operations after setup.
|
||||||
*/
|
*/
|
||||||
public SessionKey getAssociatedKey() {
|
public SessionKey getAssociatedKey() {
|
||||||
@ -386,21 +410,28 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder buf = new StringBuilder(256);
|
StringBuilder buf = new StringBuilder(256);
|
||||||
|
if (_sessionTags != null)
|
||||||
|
buf.append("Inbound ");
|
||||||
|
else
|
||||||
|
buf.append("Outbound ");
|
||||||
if (_state != null)
|
if (_state != null)
|
||||||
buf.append("NSR ");
|
buf.append("NSR ").append(_state.hashCode()).append(' ');
|
||||||
else
|
else
|
||||||
buf.append("ES ");
|
buf.append("ES ");
|
||||||
buf.append("TagSet #").append(_id)
|
buf.append("TagSet #").append(_id)
|
||||||
.append(" created: ").append(DataHelper.formatTime(_created))
|
.append("\nCreated: ").append(DataHelper.formatTime(_created))
|
||||||
.append(" last use: ").append(DataHelper.formatTime(_date));
|
.append("\nLast use: ").append(DataHelper.formatTime(_date));
|
||||||
|
PublicKey pk = getRemoteKey();
|
||||||
|
if (pk != null)
|
||||||
|
buf.append("\nRemote Public Key: ").append(pk.toBase64());
|
||||||
|
buf.append("\nRoot Symmetr. Key: ").append(_key.toBase64());
|
||||||
int sz = size();
|
int sz = size();
|
||||||
buf.append(" Size: ").append(sz)
|
buf.append("\nSize: ").append(sz)
|
||||||
.append(" Orig: ").append(_originalSize)
|
.append(" Orig: ").append(_originalSize)
|
||||||
.append(" Max: ").append(_maxSize)
|
.append(" Max: ").append(_maxSize)
|
||||||
.append(" Remaining: ").append(remaining());
|
.append(" Remaining: ").append(remaining());
|
||||||
buf.append(" Acked? ").append(_acked);
|
buf.append(" Acked? ").append(_acked);
|
||||||
if (_sessionTags != null) {
|
if (_sessionTags != null) {
|
||||||
buf.append(" Inbound");
|
|
||||||
for (int i = 0; i < sz; i++) {
|
for (int i = 0; i < sz; i++) {
|
||||||
int n = _sessionTags.keyAt(i);
|
int n = _sessionTags.keyAt(i);
|
||||||
RatchetSessionTag tag = _sessionTags.valueAt(i);
|
RatchetSessionTag tag = _sessionTags.valueAt(i);
|
||||||
@ -413,8 +444,6 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
buf.append("\tdeferred");
|
buf.append("\tdeferred");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
buf.append(" Outbound");
|
|
||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user