I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 9307cc8a authored by zzz's avatar zzz
Browse files

Ratchet: Add support for database lookup replies (proposal 154)

parent 6dd0b23c
No related branches found
No related tags found
No related merge requests found
...@@ -15,13 +15,15 @@ import java.util.List; ...@@ -15,13 +15,15 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.crypto.EncType;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.router.RouterInfo; 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;
import net.i2p.data.TunnelId; import net.i2p.data.TunnelId;
//import net.i2p.util.Log; import net.i2p.data.router.RouterInfo;
import net.i2p.router.crypto.ratchet.RatchetSessionTag;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
...@@ -31,7 +33,6 @@ import net.i2p.util.VersionComparator; ...@@ -31,7 +33,6 @@ import net.i2p.util.VersionComparator;
* @author jrandom * @author jrandom
*/ */
public class DatabaseLookupMessage extends FastI2NPMessageImpl { public class DatabaseLookupMessage extends FastI2NPMessageImpl {
//private final static Log _log = new Log(DatabaseLookupMessage.class);
public final static int MESSAGE_TYPE = 2; public final static int MESSAGE_TYPE = 2;
private Hash _key; private Hash _key;
private Hash _fromHash; private Hash _fromHash;
...@@ -40,6 +41,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -40,6 +41,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
private List<Hash> _dontIncludePeers; private List<Hash> _dontIncludePeers;
private SessionKey _replyKey; private SessionKey _replyKey;
private SessionTag _replyTag; private SessionTag _replyTag;
private RatchetSessionTag _ratchetReplyTag;
private PublicKey _ratchetPubKey;
private Type _type; private Type _type;
//private static volatile long _currentLookupPeriod = 0; //private static volatile long _currentLookupPeriod = 0;
...@@ -60,6 +63,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -60,6 +63,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
private static final byte FLAG_TYPE_LS = 0x04; private static final byte FLAG_TYPE_LS = 0x04;
private static final byte FLAG_TYPE_RI = 0x08; private static final byte FLAG_TYPE_RI = 0x08;
private static final byte FLAG_TYPE_EXPL = 0x0c; private static final byte FLAG_TYPE_EXPL = 0x0c;
// 0.9.46 or higher
private static final byte FLAG_RATCHET = 0x10;
/** @since 0.9.16 */ /** @since 0.9.16 */
public enum Type { public enum Type {
...@@ -80,6 +85,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -80,6 +85,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
* the receiver rejecting the whole message as invalid. * the receiver rejecting the whole message as invalid.
*/ */
private static final String MIN_ENCRYPTION_VERSION = "0.9.7"; private static final String MIN_ENCRYPTION_VERSION = "0.9.7";
private static final String MIN_RATCHET_VERSION = "0.9.46";
public DatabaseLookupMessage(I2PAppContext context) { public DatabaseLookupMessage(I2PAppContext context) {
this(context, false); this(context, false);
...@@ -219,7 +225,21 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -219,7 +225,21 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
} }
/** /**
* The included session key or null if unset * Does this router support ratchet replies?
*
* @param to null OK
* @since 0.9.46
*/
public static boolean supportsRatchetReplies(RouterInfo to) {
if (to == null)
return false;
String v = to.getVersion();
return VersionComparator.comp(v, MIN_RATCHET_VERSION) >= 0;
}
/**
* The included session key or null if unset.
* If non-null, either getReplyTag() or getRatchetReplyTag() is non-null.
* *
* @since 0.9.7 * @since 0.9.7
*/ */
...@@ -241,12 +261,57 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -241,12 +261,57 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
* @since 0.9.7 * @since 0.9.7
*/ */
public void setReplySession(SessionKey encryptKey, SessionTag encryptTag) { public void setReplySession(SessionKey encryptKey, SessionTag encryptTag) {
if (_replyKey != null || _replyTag != null) if (_replyKey != null || _replyTag != null ||
_ratchetReplyTag != null || _ratchetPubKey != null)
throw new IllegalStateException(); throw new IllegalStateException();
_replyKey = encryptKey; _replyKey = encryptKey;
_replyTag = encryptTag; _replyTag = encryptTag;
} }
/**
* The included session tag or null if unset
*
* @since 0.9.46
*/
public RatchetSessionTag getRatchetReplyTag() { return _ratchetReplyTag; }
/**
* Ratchet
*
* @throws IllegalStateException if key or tag previously set, to protect saved checksum
* @param encryptKey non-null
* @param encryptTag non-null
* @since 0.9.46
*/
public void setReplySession(SessionKey encryptKey, RatchetSessionTag encryptTag) {
if (_replyKey != null || _replyTag != null ||
_ratchetReplyTag != null || _ratchetPubKey != null)
throw new IllegalStateException();
_replyKey = encryptKey;
_ratchetReplyTag = encryptTag;
}
/**
* The included session key or null if unset.
* Preliminary, not fully supported, see proposal 154.
*
* @since 0.9.46
*/
public PublicKey getRatchetPublicKey() { return _ratchetPubKey; }
/**
* Ratchet.
* 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
* @since 0.9.46
*/
public void setReplySession(PublicKey pubKey) {
_ratchetPubKey = pubKey;
}
/** /**
* Set of peers that a lookup reply should NOT include. * Set of peers that a lookup reply should NOT include.
* WARNING - returns a copy. * WARNING - returns a copy.
...@@ -329,6 +394,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -329,6 +394,7 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
// TODO store the whole flag byte // TODO store the whole flag byte
boolean tunnelSpecified = (data[curIndex] & FLAG_TUNNEL) != 0; boolean tunnelSpecified = (data[curIndex] & FLAG_TUNNEL) != 0;
boolean replyKeySpecified = (data[curIndex] & FLAG_ENCRYPT) != 0; boolean replyKeySpecified = (data[curIndex] & FLAG_ENCRYPT) != 0;
boolean ratchetSpecified = (data[curIndex] & FLAG_RATCHET) != 0;
switch (data[curIndex] & FLAG_TYPE_MASK) { switch (data[curIndex] & FLAG_TYPE_MASK) {
case FLAG_TYPE_LS: case FLAG_TYPE_LS:
_type = Type.LS; _type = Type.LS;
...@@ -365,20 +431,31 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -365,20 +431,31 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
peers.add(p); peers.add(p);
} }
_dontIncludePeers = peers; _dontIncludePeers = peers;
if (replyKeySpecified) { if (replyKeySpecified || ratchetSpecified) {
// all 3 flavors are 32 bytes
byte[] rk = new byte[SessionKey.KEYSIZE_BYTES]; byte[] rk = new byte[SessionKey.KEYSIZE_BYTES];
System.arraycopy(data, curIndex, rk, 0, SessionKey.KEYSIZE_BYTES); System.arraycopy(data, curIndex, rk, 0, SessionKey.KEYSIZE_BYTES);
_replyKey = new SessionKey(rk); if (replyKeySpecified && ratchetSpecified)
_ratchetPubKey = new PublicKey(EncType.ECIES_X25519, rk);
else
_replyKey = new SessionKey(rk);
curIndex += SessionKey.KEYSIZE_BYTES; curIndex += SessionKey.KEYSIZE_BYTES;
// number of tags, assume always 1 for now if (!(replyKeySpecified && ratchetSpecified)) {
curIndex++; // number of tags, assume always 1 for now
byte[] rt = new byte[SessionTag.BYTE_LENGTH]; curIndex++;
System.arraycopy(data, curIndex, rt, 0, SessionTag.BYTE_LENGTH); if (replyKeySpecified) {
_replyTag = new SessionTag(rt); byte[] rt = new byte[SessionTag.BYTE_LENGTH];
System.arraycopy(data, curIndex, rt, 0, SessionTag.BYTE_LENGTH);
_replyTag = new SessionTag(rt);
} else {
byte[] rt = new byte[RatchetSessionTag.LENGTH];
System.arraycopy(data, curIndex, rt, 0, RatchetSessionTag.LENGTH);
_ratchetReplyTag = new RatchetSessionTag(rt);
}
}
} }
} }
protected int calculateWrittenLength() { protected int calculateWrittenLength() {
int totalLength = 0; int totalLength = 0;
totalLength += Hash.HASH_LENGTH*2; // key+fromHash totalLength += Hash.HASH_LENGTH*2; // key+fromHash
...@@ -388,9 +465,17 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -388,9 +465,17 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
totalLength += 2; // numPeers totalLength += 2; // numPeers
if (_dontIncludePeers != null) if (_dontIncludePeers != null)
totalLength += Hash.HASH_LENGTH * _dontIncludePeers.size(); totalLength += Hash.HASH_LENGTH * _dontIncludePeers.size();
if (_replyKey != null) if (_replyKey != null) {
// number of tags, assume always 1 for now // number of tags, assume always 1 for now
totalLength += SessionKey.KEYSIZE_BYTES + 1 + SessionTag.BYTE_LENGTH; totalLength += SessionKey.KEYSIZE_BYTES + 1;
if (_ratchetReplyTag != null)
totalLength += RatchetSessionTag.LENGTH;
else
totalLength += SessionTag.BYTE_LENGTH;
} else if (_ratchetPubKey != null) {
totalLength += 32;
// no tags
}
return totalLength; return totalLength;
} }
...@@ -404,8 +489,12 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -404,8 +489,12 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
curIndex += Hash.HASH_LENGTH; curIndex += Hash.HASH_LENGTH;
// Generate the flag byte // Generate the flag byte
byte flag; byte flag;
if (_replyKey != null) if (_replyTag != null)
flag = FLAG_ENCRYPT; flag = FLAG_ENCRYPT;
else if (_ratchetReplyTag != null)
flag = FLAG_RATCHET;
else if (_ratchetPubKey != null)
flag = FLAG_RATCHET | FLAG_ENCRYPT;
else else
flag = 0; flag = 0;
switch (_type) { switch (_type) {
...@@ -450,8 +539,17 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -450,8 +539,17 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
curIndex += SessionKey.KEYSIZE_BYTES; curIndex += SessionKey.KEYSIZE_BYTES;
// number of tags, always 1 for now // number of tags, always 1 for now
out[curIndex++] = 1; out[curIndex++] = 1;
System.arraycopy(_replyTag.getData(), 0, out, curIndex, SessionTag.BYTE_LENGTH); if (_replyTag != null) {
curIndex += SessionTag.BYTE_LENGTH; System.arraycopy(_replyTag.getData(), 0, out, curIndex, SessionTag.BYTE_LENGTH);
curIndex += SessionTag.BYTE_LENGTH;
} else {
System.arraycopy(_ratchetReplyTag.getData(), 0, out, curIndex, RatchetSessionTag.LENGTH);
curIndex += RatchetSessionTag.LENGTH;
}
} else if (_ratchetPubKey != null) {
System.arraycopy(_ratchetPubKey.getData(), 0, out, curIndex, _ratchetPubKey.length());
curIndex += _ratchetPubKey.length();
// no tags
} }
return curIndex; return curIndex;
} }
...@@ -499,6 +597,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl { ...@@ -499,6 +597,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
buf.append("\n\tReply Key: ").append(_replyKey); buf.append("\n\tReply Key: ").append(_replyKey);
if (_replyTag != null) if (_replyTag != null)
buf.append("\n\tReply Tag: ").append(_replyTag); buf.append("\n\tReply Tag: ").append(_replyTag);
else if (_ratchetReplyTag != null)
buf.append("\n\tRatchetReply Tag: ").append(_ratchetReplyTag);
if (_dontIncludePeers != null) { if (_dontIncludePeers != null) {
buf.append("\n\tDon't Include Peers: "); buf.append("\n\tDon't Include Peers: ");
buf.append(_dontIncludePeers.size()); buf.append(_dontIncludePeers.size());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment