forked from I2P_Developers/i2p.i2p
Ratchet: Prep for ratchet-layer acks (WIP)
This commit is contained in:
@ -32,7 +32,7 @@ public class LeaseSetKeys {
|
||||
* @since 0.9.44
|
||||
*/
|
||||
public static final Set<EncType> SET_ELG = Collections.unmodifiableSet(EnumSet.of(EncType.ELGAMAL_2048));
|
||||
private static final Set<EncType> SET_EC = Collections.unmodifiableSet(EnumSet.of(EncType.ECIES_X25519));
|
||||
public static final Set<EncType> SET_EC = Collections.unmodifiableSet(EnumSet.of(EncType.ECIES_X25519));
|
||||
private static final Set<EncType> SET_BOTH = Collections.unmodifiableSet(EnumSet.of(EncType.ELGAMAL_2048, EncType.ECIES_X25519));
|
||||
private static final Set<EncType> SET_NONE = Collections.unmodifiableSet(EnumSet.noneOf(EncType.class));
|
||||
|
||||
|
@ -606,14 +606,14 @@ class ClientConnectionRunner {
|
||||
if (hasElg) {
|
||||
TransientSessionKeyManager tskm = new TransientSessionKeyManager(_context, tags, thresh);
|
||||
if (hasEC) {
|
||||
RatchetSKM rskm = new RatchetSKM(_context);
|
||||
RatchetSKM rskm = new RatchetSKM(_context, dest);
|
||||
_sessionKeyManager = new MuxedSKM(tskm, rskm);
|
||||
} else {
|
||||
_sessionKeyManager = tskm;
|
||||
}
|
||||
} else {
|
||||
if (hasEC) {
|
||||
_sessionKeyManager = new RatchetSKM(_context);
|
||||
_sessionKeyManager = new RatchetSKM(_context, dest);
|
||||
} else {
|
||||
_log.error("No supported encryption types in i2cp.leaseSetEncType for " + dest.toBase32());
|
||||
return SessionStatusMessage.STATUS_INVALID;
|
||||
|
@ -19,15 +19,23 @@ import net.i2p.crypto.HKDF;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.Certificate;
|
||||
import net.i2p.data.DatabaseEntry;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.LeaseSet2;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.PublicKey;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.SessionTag;
|
||||
import net.i2p.data.i2np.DatabaseStoreMessage;
|
||||
import net.i2p.data.i2np.GarlicClove;
|
||||
import net.i2p.data.i2np.I2NPMessage;
|
||||
import static net.i2p.router.crypto.ratchet.RatchetPayload.*;
|
||||
import net.i2p.router.LeaseSetKeys;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.message.CloveSet;
|
||||
import net.i2p.util.Log;
|
||||
@ -395,13 +403,13 @@ public final class ECIESAEADEngine {
|
||||
return NO_CLOVES;
|
||||
}
|
||||
|
||||
byte[] bobPK = new byte[KEYLEN];
|
||||
state.getRemotePublicKey().getPublicKey(bobPK, 0);
|
||||
byte[] alicePK = new byte[KEYLEN];
|
||||
state.getRemotePublicKey().getPublicKey(alicePK, 0);
|
||||
if (_log.shouldDebug()) {
|
||||
_log.debug("NS decrypt success from PK " + Base64.encode(bobPK));
|
||||
_log.debug("NS decrypt success from PK " + Base64.encode(alicePK));
|
||||
_log.debug("State after decrypt new session: " + state);
|
||||
}
|
||||
if (Arrays.equals(bobPK, NULLPK)) {
|
||||
if (Arrays.equals(alicePK, NULLPK)) {
|
||||
// TODO
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Zero static key in IB NS");
|
||||
@ -434,8 +442,8 @@ public final class ECIESAEADEngine {
|
||||
}
|
||||
|
||||
// tell the SKM
|
||||
PublicKey bob = new PublicKey(EncType.ECIES_X25519, bobPK);
|
||||
keyManager.createSession(bob, state, null);
|
||||
PublicKey alice = new PublicKey(EncType.ECIES_X25519, alicePK);
|
||||
keyManager.createSession(alice, state, null);
|
||||
|
||||
if (pc.cloveSet.isEmpty()) {
|
||||
// this is legal
|
||||
@ -447,6 +455,8 @@ public final class ECIESAEADEngine {
|
||||
GarlicClove[] arr = new GarlicClove[num];
|
||||
// msg id and expiration not checked in GarlicMessageReceiver
|
||||
CloveSet rv = new CloveSet(pc.cloveSet.toArray(arr), Certificate.NULL_CERT, 0, pc.datetime);
|
||||
// TODO
|
||||
//setResponseTimer(alice, pc.cloveSet, keyManager);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -587,6 +597,8 @@ public final class ECIESAEADEngine {
|
||||
GarlicClove[] arr = new GarlicClove[num];
|
||||
// msg id and expiration not checked in GarlicMessageReceiver
|
||||
CloveSet rv = new CloveSet(pc.cloveSet.toArray(arr), Certificate.NULL_CERT, 0, pc.datetime);
|
||||
// TODO
|
||||
//setResponseTimer(bob, pc.cloveSet, keyManager);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -679,6 +691,7 @@ public final class ECIESAEADEngine {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//// end decrypt, start encrypt ////
|
||||
|
||||
|
||||
@ -1207,6 +1220,39 @@ public final class ECIESAEADEngine {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a timer for a ratchet-layer reply if the application does not respond.
|
||||
*
|
||||
* @since 0.9.46
|
||||
*/
|
||||
private void setResponseTimer(PublicKey from, List<GarlicClove> cloveSet, RatchetSKM skm) {
|
||||
for (GarlicClove clove : cloveSet) {
|
||||
I2NPMessage msg = clove.getData();
|
||||
if (msg.getType() != DatabaseStoreMessage.MESSAGE_TYPE)
|
||||
continue;
|
||||
DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
|
||||
DatabaseEntry entry = dsm.getEntry();
|
||||
if (entry.getType() != DatabaseEntry.KEY_TYPE_LS2)
|
||||
continue;
|
||||
LeaseSet2 ls2 = (LeaseSet2) entry;
|
||||
if (!ls2.isCurrent(Router.CLOCK_FUDGE_FACTOR))
|
||||
continue;
|
||||
PublicKey pk = ls2.getEncryptionKey(LeaseSetKeys.SET_EC);
|
||||
if (!from.equals(pk))
|
||||
continue;
|
||||
if (!ls2.verifySignature())
|
||||
continue;
|
||||
// OK, we have a valid place to send the reply
|
||||
Destination d = ls2.getDestination();
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Validated NS sender: " + d.toBase32());
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Unvalidated NS sender: " + from);
|
||||
}
|
||||
|
||||
|
||||
/****
|
||||
public static void main(String args[]) {
|
||||
|
@ -26,6 +26,7 @@ import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.crypto.TagSetHandle;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.PublicKey;
|
||||
import net.i2p.data.SessionKey;
|
||||
@ -52,6 +53,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
||||
private volatile boolean _alive;
|
||||
private final HKDF _hkdf;
|
||||
private final DecayingHashSet _replayFilter;
|
||||
private final Destination _destination;
|
||||
|
||||
/**
|
||||
* Let outbound session tags sit around for this long before expiring them.
|
||||
@ -81,10 +83,11 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
||||
* appropriate application context itself.
|
||||
*
|
||||
*/
|
||||
public RatchetSKM(RouterContext context) {
|
||||
public RatchetSKM(RouterContext context, Destination dest) {
|
||||
super(context);
|
||||
_log = context.logManager().getLog(RatchetSKM.class);
|
||||
_context = context;
|
||||
_destination = dest;
|
||||
_outboundSessions = new ConcurrentHashMap<PublicKey, OutboundSession>(64);
|
||||
_pendingOutboundSessions = new HashMap<PublicKey, List<OutboundSession>>(64);
|
||||
_inboundTagSets = new ConcurrentHashMap<RatchetSessionTag, RatchetTagSet>(128);
|
||||
@ -124,6 +127,12 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.46
|
||||
*/
|
||||
public Destination getDestination() {
|
||||
return _destination;
|
||||
}
|
||||
|
||||
/** RatchetTagSet */
|
||||
private Set<RatchetTagSet> getRatchetTagSets() {
|
||||
|
Reference in New Issue
Block a user