forked from I2P_Developers/i2p.i2p
short build records
This commit is contained in:
@@ -57,7 +57,7 @@ import net.i2p.router.RouterContext;
|
||||
* bytes 16-527: ElGamal encrypted block (discarding zero bytes at elg[0] and elg[257])
|
||||
* </pre>
|
||||
*
|
||||
* New ECIES format, ref: proposal 152:
|
||||
* ECIES long record format, ref: proposal 152:
|
||||
*
|
||||
* Holds the unencrypted 464-byte tunnel request record,
|
||||
* with a constructor for ECIES decryption and a method for ECIES encryption.
|
||||
@@ -90,6 +90,36 @@ import net.i2p.router.RouterContext;
|
||||
* bytes 512-527: Poly1305 MAC
|
||||
* </pre>
|
||||
*
|
||||
* ECIES short record format, ref: proposal 157:
|
||||
*
|
||||
* Holds the unencrypted 172-byte tunnel request record,
|
||||
* with a constructor for ECIES decryption and a method for ECIES encryption.
|
||||
* Iterative AES encryption/decryption is done elsewhere.
|
||||
*
|
||||
* Cleartext:
|
||||
* <pre>
|
||||
* bytes 0-3: tunnel ID to receive messages as, nonzero
|
||||
* bytes 4-7: next tunnel ID, nonzero
|
||||
* bytes 8-39: next router identity hash
|
||||
* byte 40: flags
|
||||
* bytes 41-42: more flags, unused, set to 0 for compatibility
|
||||
* byte 43: layer enc. type
|
||||
* bytes 44-47: request time (in minutes since the epoch, rounded down)
|
||||
* bytes 48-51: request expiration (in seconds since creation)
|
||||
* bytes 52-55: next message ID
|
||||
* bytes 56-x: tunnel build options (Mapping)
|
||||
* bytes x-x: other data as implied by flags or options
|
||||
* bytes x-171: random padding
|
||||
* </pre>
|
||||
*
|
||||
* Encrypted:
|
||||
* <pre>
|
||||
* bytes 0-15: Hop's truncated identity hash
|
||||
* bytes 16-47: Sender's ephemeral X25519 public key
|
||||
* bytes 48-219: ChaCha20 encrypted BuildRequestRecord
|
||||
* bytes 220-235: Poly1305 MAC
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class BuildRequestRecord {
|
||||
private final byte[] _data;
|
||||
@@ -138,7 +168,7 @@ public class BuildRequestRecord {
|
||||
// 222
|
||||
private static final int LENGTH = OFF_SEND_MSG_ID + 4 + PADDING_SIZE;
|
||||
|
||||
// New ECIES format
|
||||
// ECIES long record format
|
||||
private static final int OFF_SEND_TUNNEL_EC = OFF_OUR_IDENT;
|
||||
private static final int OFF_SEND_IDENT_EC = OFF_SEND_TUNNEL_EC + 4;
|
||||
private static final int OFF_LAYER_KEY_EC = OFF_SEND_IDENT_EC + Hash.HASH_LENGTH;
|
||||
@@ -152,6 +182,16 @@ public class BuildRequestRecord {
|
||||
private static final int OFF_OPTIONS = OFF_SEND_MSG_ID_EC + 4;
|
||||
private static final int LENGTH_EC = 464;
|
||||
private static final int MAX_OPTIONS_LENGTH = LENGTH_EC - OFF_OPTIONS; // includes options length
|
||||
|
||||
// ECIES short record format
|
||||
private static final int OFF_FLAG_EC_SHORT = OFF_SEND_IDENT_EC + Hash.HASH_LENGTH;
|
||||
private static final int OFF_LAYER_ENC_TYPE = OFF_FLAG_EC_SHORT + 3;
|
||||
private static final int OFF_REQ_TIME_EC_SHORT = OFF_LAYER_ENC_TYPE + 1;
|
||||
private static final int OFF_EXPIRATION_SHORT = OFF_REQ_TIME_EC + 4;
|
||||
private static final int OFF_SEND_MSG_ID_EC_SHORT = OFF_EXPIRATION + 4;
|
||||
private static final int OFF_OPTIONS_SHORT = OFF_SEND_MSG_ID_EC_SHORT + 4;
|
||||
private static final int LENGTH_EC_SHORT = 172;
|
||||
private static final int MAX_OPTIONS_LENGTH_SHORT = LENGTH_EC_SHORT - OFF_OPTIONS_SHORT; // includes options length
|
||||
|
||||
private static final boolean TEST = false;
|
||||
private static KeyFactory TESTKF;
|
||||
@@ -225,7 +265,8 @@ public class BuildRequestRecord {
|
||||
*
|
||||
*/
|
||||
public boolean readIsInboundGateway() {
|
||||
int off = _isEC ? OFF_FLAG_EC : OFF_FLAG;
|
||||
int off = _isEC ? ( _data.length == LENGTH_EC_SHORT ? OFF_FLAG_EC_SHORT : OFF_FLAG_EC)
|
||||
: OFF_FLAG;
|
||||
return (_data[off] & FLAG_UNRESTRICTED_PREV) != 0;
|
||||
}
|
||||
|
||||
@@ -234,7 +275,8 @@ public class BuildRequestRecord {
|
||||
* fields refer to where the reply should be sent.
|
||||
*/
|
||||
public boolean readIsOutboundEndpoint() {
|
||||
int off = _isEC ? OFF_FLAG_EC : OFF_FLAG;
|
||||
int off = _isEC ? ( _data.length == LENGTH_EC_SHORT ? OFF_FLAG_EC_SHORT : OFF_FLAG_EC)
|
||||
: OFF_FLAG;
|
||||
return (_data[off] & FLAG_OUTBOUND_ENDPOINT) != 0;
|
||||
}
|
||||
|
||||
@@ -244,8 +286,10 @@ public class BuildRequestRecord {
|
||||
* This ignores leap seconds.
|
||||
*/
|
||||
public long readRequestTime() {
|
||||
if (_isEC)
|
||||
return DataHelper.fromLong(_data, OFF_REQ_TIME_EC, 4) * (60 * 1000L);
|
||||
if (_isEC) {
|
||||
int off = _data.length == LENGTH_EC_SHORT ? OFF_REQ_TIME_EC_SHORT : OFF_REQ_TIME_EC;
|
||||
return DataHelper.fromLong(_data, off, 4) * (60 * 1000L);
|
||||
}
|
||||
return DataHelper.fromLong(_data, OFF_REQ_TIME, 4) * (60 * 60 * 1000L);
|
||||
}
|
||||
|
||||
@@ -254,7 +298,8 @@ public class BuildRequestRecord {
|
||||
* this specifies the message ID with which the reply should be sent.
|
||||
*/
|
||||
public long readReplyMessageId() {
|
||||
int off = _isEC ? OFF_SEND_MSG_ID_EC : OFF_SEND_MSG_ID;
|
||||
int off = _isEC ? ( _data.length == LENGTH_EC_SHORT ? OFF_SEND_MSG_ID_EC_SHORT : OFF_SEND_MSG_ID_EC)
|
||||
: OFF_SEND_MSG_ID;
|
||||
return DataHelper.fromLong(_data, off, 4);
|
||||
}
|
||||
|
||||
@@ -265,7 +310,8 @@ public class BuildRequestRecord {
|
||||
public long readExpiration() {
|
||||
if (!_isEC)
|
||||
return DEFAULT_EXPIRATION_SECONDS * 1000L;
|
||||
return DataHelper.fromLong(_data, OFF_EXPIRATION, 4) * 1000L;
|
||||
int off = _data.length == LENGTH_EC_SHORT ? OFF_EXPIRATION_SHORT : OFF_EXPIRATION;
|
||||
return DataHelper.fromLong(_data, off, 4) * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,7 +322,11 @@ public class BuildRequestRecord {
|
||||
public Properties readOptions() {
|
||||
if (!_isEC)
|
||||
return null;
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(_data, OFF_OPTIONS, MAX_OPTIONS_LENGTH);
|
||||
ByteArrayInputStream in;
|
||||
if (_data.length == LENGTH_EC_SHORT)
|
||||
in = new ByteArrayInputStream(_data, OFF_OPTIONS_SHORT, MAX_OPTIONS_LENGTH_SHORT);
|
||||
else
|
||||
in = new ByteArrayInputStream(_data, OFF_OPTIONS, MAX_OPTIONS_LENGTH);
|
||||
try {
|
||||
return DataHelper.readProperties(in, null);
|
||||
} catch (DataFormatException dfe) {
|
||||
@@ -286,6 +336,17 @@ public class BuildRequestRecord {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ECIES short record only.
|
||||
* @return 0 for ElGamal or ECIES long record
|
||||
* @since 0.9.51
|
||||
*/
|
||||
public int readLayerEncryptionType() {
|
||||
if (_data.length == LENGTH_EC_SHORT)
|
||||
return _data[OFF_LAYER_ENC_TYPE] & 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the record to the specified peer. The result is formatted as: <pre>
|
||||
* bytes 0-15: truncated SHA-256 of the current hop's identity (the toPeer parameter)
|
||||
@@ -324,7 +385,8 @@ public class BuildRequestRecord {
|
||||
EncType type = toKey.getType();
|
||||
if (type != EncType.ECIES_X25519)
|
||||
throw new IllegalArgumentException();
|
||||
byte[] out = new byte[EncryptedBuildRecord.LENGTH];
|
||||
boolean isShort = _data.length == LENGTH_EC_SHORT;
|
||||
byte[] out = new byte[isShort ? ShortEncryptedBuildRecord.LENGTH : EncryptedBuildRecord.LENGTH];
|
||||
System.arraycopy(toPeer.getData(), 0, out, 0, PEER_SIZE);
|
||||
HandshakeState state = null;
|
||||
try {
|
||||
@@ -332,8 +394,8 @@ public class BuildRequestRecord {
|
||||
state = new HandshakeState(HandshakeState.PATTERN_ID_N, HandshakeState.INITIATOR, kf);
|
||||
state.getRemotePublicKey().setPublicKey(toKey.getData(), 0);
|
||||
state.start();
|
||||
state.writeMessage(out, PEER_SIZE, _data, 0, LENGTH_EC);
|
||||
EncryptedBuildRecord rv = new EncryptedBuildRecord(out);
|
||||
state.writeMessage(out, PEER_SIZE, _data, 0, _data.length);
|
||||
EncryptedBuildRecord rv = isShort ? new ShortEncryptedBuildRecord(out) : new EncryptedBuildRecord(out);
|
||||
_chachaReplyKey = new SessionKey(state.getChainingKey());
|
||||
_chachaReplyAD = new byte[32];
|
||||
System.arraycopy(state.getHandshakeHash(), 0, _chachaReplyAD, 0, 32);
|
||||
@@ -414,8 +476,10 @@ public class BuildRequestRecord {
|
||||
state.getLocalKeyPair().setKeys(ourKey.getData(), 0,
|
||||
ourKey.toPublic().getData(), 0);
|
||||
state.start();
|
||||
decrypted = new byte[LENGTH_EC];
|
||||
state.readMessage(encrypted, PEER_SIZE, EncryptedBuildRecord.LENGTH - PEER_SIZE,
|
||||
int len = encryptedRecord.length();
|
||||
boolean isShort = len == ShortEncryptedBuildRecord.LENGTH;
|
||||
decrypted = new byte[isShort ? LENGTH_EC_SHORT : LENGTH_EC];
|
||||
state.readMessage(encrypted, PEER_SIZE, len - PEER_SIZE,
|
||||
decrypted, 0);
|
||||
_chachaReplyKey = new SessionKey(state.getChainingKey());
|
||||
_chachaReplyAD = new byte[32];
|
||||
@@ -507,7 +571,7 @@ public class BuildRequestRecord {
|
||||
* Populate this instance with data. A new buffer is created to contain the data, with the
|
||||
* necessary randomized padding.
|
||||
*
|
||||
* ECIES only. ElGamal constructor above.
|
||||
* ECIES long record only. ElGamal constructor above.
|
||||
*
|
||||
* @param receiveTunnelId tunnel the current hop will receive messages on
|
||||
* @param nextTunnelId id for the next hop, or where we send the reply (if we are the outbound endpoint)
|
||||
@@ -559,6 +623,55 @@ public class BuildRequestRecord {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate this instance with data. A new buffer is created to contain the data, with the
|
||||
* necessary randomized padding.
|
||||
*
|
||||
* ECIES short record only. ElGamal constructor above.
|
||||
*
|
||||
* @param receiveTunnelId tunnel the current hop will receive messages on
|
||||
* @param nextTunnelId id for the next hop, or where we send the reply (if we are the outbound endpoint)
|
||||
* @param nextHop next hop's identity, or where we send the reply (if we are the outbound endpoint)
|
||||
* @param nextMsgId message ID to use when sending on to the next hop (or for the reply)
|
||||
* @param isInGateway are we the gateway of an inbound tunnel?
|
||||
* @param isOutEndpoint are we the endpoint of an outbound tunnel?
|
||||
* @param options 116 bytes max when serialized
|
||||
* @since 0.9.51
|
||||
* @throws IllegalArgumentException if options too long
|
||||
*/
|
||||
public BuildRequestRecord(I2PAppContext ctx, long receiveTunnelId, long nextTunnelId, Hash nextHop, long nextMsgId,
|
||||
boolean isInGateway, boolean isOutEndpoint, Properties options) {
|
||||
byte buf[] = new byte[LENGTH_EC_SHORT];
|
||||
_data = buf;
|
||||
_isEC = true;
|
||||
|
||||
DataHelper.toLong(buf, OFF_RECV_TUNNEL, 4, receiveTunnelId);
|
||||
DataHelper.toLong(buf, OFF_SEND_TUNNEL_EC, 4, nextTunnelId);
|
||||
System.arraycopy(nextHop.getData(), 0, buf, OFF_SEND_IDENT_EC, Hash.HASH_LENGTH);
|
||||
if (isInGateway)
|
||||
buf[OFF_FLAG_EC_SHORT] |= FLAG_UNRESTRICTED_PREV;
|
||||
else if (isOutEndpoint)
|
||||
buf[OFF_FLAG_EC_SHORT] |= FLAG_OUTBOUND_ENDPOINT;
|
||||
// 2 bytes unused flags = 0
|
||||
// 1 byte layer enc. type = 0
|
||||
long truncatedMinute = ctx.clock().now();
|
||||
// prevent hop identification at top of the minute
|
||||
truncatedMinute -= ctx.random().nextInt(2048);
|
||||
// this ignores leap seconds
|
||||
truncatedMinute /= (60*1000L);
|
||||
DataHelper.toLong(buf, OFF_REQ_TIME_EC_SHORT, 4, truncatedMinute);
|
||||
DataHelper.toLong(buf, OFF_EXPIRATION_SHORT, 4, DEFAULT_EXPIRATION_SECONDS);
|
||||
DataHelper.toLong(buf, OFF_SEND_MSG_ID_EC_SHORT, 4, nextMsgId);
|
||||
try {
|
||||
int off = DataHelper.toProperties(buf, OFF_OPTIONS_SHORT, options);
|
||||
int sz = LENGTH_EC_SHORT - off;
|
||||
if (sz > 0)
|
||||
ctx.random().nextBytes(buf, off, sz);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("options", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.24
|
||||
*/
|
||||
@@ -566,6 +679,8 @@ public class BuildRequestRecord {
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
buf.append(_isEC ? "ECIES" : "ElGamal");
|
||||
if (_data.length == LENGTH_EC_SHORT)
|
||||
buf.append(" short ");
|
||||
buf.append(" BRR ");
|
||||
boolean isIBGW = readIsInboundGateway();
|
||||
boolean isOBEP = readIsOutboundEndpoint();
|
||||
@@ -578,12 +693,14 @@ public class BuildRequestRecord {
|
||||
buf.append("part. in: ").append(readReceiveTunnelId())
|
||||
.append(" out: ").append(readNextTunnelId());
|
||||
}
|
||||
buf.append(" to: ").append(readNextIdentity())
|
||||
.append(" layer key: ").append(readLayerKey())
|
||||
.append(" IV key: ").append(readIVKey())
|
||||
.append(" reply key: ").append(readReplyKey())
|
||||
.append(" reply IV: ").append(Base64.encode(readReplyIV()))
|
||||
.append(" time: ").append(DataHelper.formatTime(readRequestTime()))
|
||||
buf.append(" to: ").append(readNextIdentity());
|
||||
if (_data.length != LENGTH_EC_SHORT) {
|
||||
buf.append(" layer key: ").append(readLayerKey())
|
||||
.append(" IV key: ").append(readIVKey())
|
||||
.append(" reply key: ").append(readReplyKey())
|
||||
.append(" reply IV: ").append(Base64.encode(readReplyIV()));
|
||||
}
|
||||
buf.append(" time: ").append(DataHelper.formatTime(readRequestTime()))
|
||||
.append(" reply msg id: ").append(readReplyMessageId())
|
||||
.append(" expires in: ").append(DataHelper.formatDuration(readExpiration()));
|
||||
if (_isEC) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class BuildResponseRecord {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new encrypted response.
|
||||
* Create a new encrypted response (long record).
|
||||
* ChaCha/Poly only for ECIES routers.
|
||||
*
|
||||
* @param status the response 0-255
|
||||
@@ -77,6 +77,38 @@ public class BuildResponseRecord {
|
||||
return new EncryptedBuildRecord(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new encrypted response (short record).
|
||||
* ChaCha/Poly only for ECIES routers.
|
||||
*
|
||||
* @param status the response 0-255
|
||||
* @param replyAD 32 bytes
|
||||
* @param options 116 bytes max when serialized
|
||||
* @return a 236-byte response record
|
||||
* @throws IllegalArgumentException if options too big or on encryption failure
|
||||
* @since 0.9.451
|
||||
*/
|
||||
public static ShortEncryptedBuildRecord createShort(I2PAppContext ctx, int status, SessionKey replyKey,
|
||||
byte replyAD[], Properties options) {
|
||||
byte rv[] = new byte[ShortTunnelBuildMessage.SHORT_RECORD_SIZE];
|
||||
int off;
|
||||
try {
|
||||
off = DataHelper.toProperties(rv, 0, options);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("options", e);
|
||||
}
|
||||
int sz = ShortTunnelBuildMessage.SHORT_RECORD_SIZE - off - 1;
|
||||
if (sz > 0)
|
||||
ctx.random().nextBytes(rv, off, sz);
|
||||
else if (sz < 0)
|
||||
throw new IllegalArgumentException("options");
|
||||
rv[ShortTunnelBuildMessage.SHORT_RECORD_SIZE - 17] = (byte) status;
|
||||
boolean ok = encryptAEADBlock(replyAD, rv, replyKey);
|
||||
if (!ok)
|
||||
throw new IllegalArgumentException("encrypt fail");
|
||||
return new ShortEncryptedBuildRecord(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts in place
|
||||
* @param ad non-null
|
||||
|
||||
@@ -11,6 +11,9 @@ import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.i2np.BuildRequestRecord;
|
||||
import net.i2p.data.i2np.EncryptedBuildRecord;
|
||||
import net.i2p.data.i2np.I2NPMessage;
|
||||
import net.i2p.data.i2np.InboundTunnelBuildMessage;
|
||||
import net.i2p.data.i2np.ShortEncryptedBuildRecord;
|
||||
import net.i2p.data.i2np.ShortTunnelBuildMessage;
|
||||
import net.i2p.data.i2np.TunnelBuildMessage;
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
@@ -32,15 +35,17 @@ public abstract class BuildMessageGenerator {
|
||||
public static void createRecord(int recordNum, int hop, TunnelBuildMessage msg,
|
||||
TunnelCreatorConfig cfg, Hash replyRouter,
|
||||
long replyTunnel, RouterContext ctx, PublicKey peerKey) {
|
||||
////// TODO check msg type for short (STBM or ITBM)
|
||||
int mtype = msg.getType();
|
||||
boolean isShort = mtype == InboundTunnelBuildMessage.MESSAGE_TYPE || mtype == ShortTunnelBuildMessage.MESSAGE_TYPE;
|
||||
EncryptedBuildRecord erec;
|
||||
if (peerKey != null) {
|
||||
boolean isEC = peerKey.getType() == EncType.ECIES_X25519;
|
||||
BuildRequestRecord req;
|
||||
if ( (!cfg.isInbound()) && (hop + 1 == cfg.getLength()) ) //outbound endpoint
|
||||
req = createUnencryptedRecord(ctx, cfg, hop, replyRouter, replyTunnel, isEC);
|
||||
//// TODO if we're the OBEP
|
||||
req = createUnencryptedRecord(ctx, cfg, hop, replyRouter, replyTunnel, isEC, isShort);
|
||||
else
|
||||
req = createUnencryptedRecord(ctx, cfg, hop, null, -1, isEC);
|
||||
req = createUnencryptedRecord(ctx, cfg, hop, null, -1, isEC, isShort);
|
||||
if (req == null)
|
||||
throw new IllegalArgumentException("hop bigger than config");
|
||||
Hash peer = cfg.getPeer(hop);
|
||||
@@ -51,26 +56,31 @@ public abstract class BuildMessageGenerator {
|
||||
erec = req.encryptRecord(ctx, peerKey, peer);
|
||||
}
|
||||
} else {
|
||||
byte encrypted[] = new byte[TunnelBuildMessage.RECORD_SIZE];
|
||||
int len = isShort ? ShortTunnelBuildMessage.SHORT_RECORD_SIZE : TunnelBuildMessage.RECORD_SIZE;
|
||||
byte encrypted[] = new byte[len];
|
||||
if (cfg.isInbound() && hop + 1 == cfg.getLength()) { // IBEP
|
||||
System.arraycopy(cfg.getPeer(hop).getData(), 0, encrypted, 0, BuildRequestRecord.PEER_SIZE);
|
||||
ctx.random().nextBytes(encrypted, BuildRequestRecord.PEER_SIZE, TunnelBuildMessage.RECORD_SIZE - BuildRequestRecord.PEER_SIZE);
|
||||
ctx.random().nextBytes(encrypted, BuildRequestRecord.PEER_SIZE, len - BuildRequestRecord.PEER_SIZE);
|
||||
byte[] h = new byte[Hash.HASH_LENGTH];
|
||||
ctx.sha().calculateHash(encrypted, 0, TunnelBuildMessage.RECORD_SIZE, h, 0);
|
||||
ctx.sha().calculateHash(encrypted, 0, len, h, 0);
|
||||
cfg.setBlankHash(new Hash(h));
|
||||
} else {
|
||||
ctx.random().nextBytes(encrypted);
|
||||
}
|
||||
erec = new EncryptedBuildRecord(encrypted);
|
||||
erec = isShort ? new ShortEncryptedBuildRecord(encrypted) : new EncryptedBuildRecord(encrypted);
|
||||
}
|
||||
msg.setRecord(recordNum, erec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if hop >= cfg.length
|
||||
*
|
||||
* @param isEC must be true if isShort is true
|
||||
* @param isShort short EC record
|
||||
*/
|
||||
private static BuildRequestRecord createUnencryptedRecord(I2PAppContext ctx, TunnelCreatorConfig cfg, int hop,
|
||||
Hash replyRouter, long replyTunnel, boolean isEC) {
|
||||
Hash replyRouter, long replyTunnel, boolean isEC,
|
||||
boolean isShort) {
|
||||
if (hop < cfg.getLength()) {
|
||||
// ok, now lets fill in some data
|
||||
HopConfig hopConfig = cfg.getConfig(hop);
|
||||
@@ -115,9 +125,15 @@ public abstract class BuildMessageGenerator {
|
||||
BuildRequestRecord rec;
|
||||
if (isEC) {
|
||||
// TODO pass properties from cfg
|
||||
rec = new BuildRequestRecord(ctx, recvTunnelId, nextTunnelId, nextPeer,
|
||||
nextMsgId, layerKey, ivKey, replyKey,
|
||||
iv, isInGW, isOutEnd, EmptyProperties.INSTANCE);
|
||||
if (isShort) {
|
||||
rec = new BuildRequestRecord(ctx, recvTunnelId, nextTunnelId, nextPeer,
|
||||
nextMsgId, layerKey, ivKey, replyKey,
|
||||
iv, isInGW, isOutEnd, EmptyProperties.INSTANCE);
|
||||
} else {
|
||||
rec = new BuildRequestRecord(ctx, recvTunnelId, nextTunnelId, nextPeer,
|
||||
nextMsgId,
|
||||
isInGW, isOutEnd, EmptyProperties.INSTANCE);
|
||||
}
|
||||
} else {
|
||||
rec = new BuildRequestRecord(ctx, recvTunnelId, peer, nextTunnelId, nextPeer,
|
||||
nextMsgId, layerKey, ivKey, replyKey,
|
||||
@@ -140,6 +156,8 @@ public abstract class BuildMessageGenerator {
|
||||
public static void layeredEncrypt(I2PAppContext ctx, TunnelBuildMessage msg,
|
||||
TunnelCreatorConfig cfg, List<Integer> order) {
|
||||
////// TODO check msg type for short (STBM or ITBM)
|
||||
int mtype = msg.getType();
|
||||
boolean isShort = mtype == InboundTunnelBuildMessage.MESSAGE_TYPE || mtype == ShortTunnelBuildMessage.MESSAGE_TYPE;
|
||||
// encrypt the records so that the right elements will be visible at the right time
|
||||
for (int i = 0; i < msg.getRecordCount(); i++) {
|
||||
EncryptedBuildRecord rec = msg.getRecord(i);
|
||||
|
||||
Reference in New Issue
Block a user