forked from I2P_Developers/i2p.i2p
Ratchet: Stub out ack and ack request blocks
This commit is contained in:
@ -26,6 +26,7 @@ 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;
|
||||||
|
import net.i2p.data.i2np.DeliveryInstructions;
|
||||||
import net.i2p.data.i2np.GarlicClove;
|
import net.i2p.data.i2np.GarlicClove;
|
||||||
import static net.i2p.router.crypto.ratchet.RatchetPayload.*;
|
import static net.i2p.router.crypto.ratchet.RatchetPayload.*;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
@ -554,13 +555,14 @@ public final class ECIESAEADEngine {
|
|||||||
*
|
*
|
||||||
* @param target public key to which the data should be encrypted.
|
* @param target public key to which the data should be encrypted.
|
||||||
* @param priv local private key to encrypt with, from the leaseset
|
* @param priv local private key to encrypt with, from the leaseset
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return encrypted data or null on failure
|
* @return encrypted data or null on failure
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public byte[] encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
public byte[] encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager, DeliveryInstructions replyDI) {
|
||||||
try {
|
try {
|
||||||
return x_encrypt(cloves, target, priv, keyManager);
|
return x_encrypt(cloves, target, priv, keyManager, replyDI);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_log.error("ECIES encrypt error", e);
|
_log.error("ECIES encrypt error", e);
|
||||||
return null;
|
return null;
|
||||||
@ -568,7 +570,7 @@ public final class ECIESAEADEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] x_encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
private byte[] x_encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager, DeliveryInstructions replyDI) {
|
||||||
if (target.getType() != EncType.ECIES_X25519)
|
if (target.getType() != EncType.ECIES_X25519)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (Arrays.equals(target.getData(), NULLPK)) {
|
if (Arrays.equals(target.getData(), NULLPK)) {
|
||||||
@ -581,7 +583,7 @@ public final class ECIESAEADEngine {
|
|||||||
if (re == null) {
|
if (re == null) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Encrypting as NS to " + target);
|
_log.debug("Encrypting as NS to " + target);
|
||||||
return encryptNewSession(cloves, target, priv, keyManager);
|
return encryptNewSession(cloves, target, priv, keyManager, replyDI);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeState state = re.key.getHandshakeState();
|
HandshakeState state = re.key.getHandshakeState();
|
||||||
@ -595,11 +597,11 @@ public final class ECIESAEADEngine {
|
|||||||
}
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Encrypting as NSR to " + target + " with tag " + re.tag.toBase64());
|
_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, replyDI);
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Encrypting as ES to " + target + " with key " + re.key + " and tag " + re.tag.toBase64());
|
_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, replyDI);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,10 +620,11 @@ public final class ECIESAEADEngine {
|
|||||||
* - 16 byte MAC
|
* - 16 byte MAC
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return encrypted data or null on failure
|
* @return encrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
private byte[] encryptNewSession(CloveSet cloves, PublicKey target, PrivateKey priv,
|
private byte[] encryptNewSession(CloveSet cloves, PublicKey target, PrivateKey priv,
|
||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager, DeliveryInstructions replyDI) {
|
||||||
HandshakeState state;
|
HandshakeState state;
|
||||||
try {
|
try {
|
||||||
state = new HandshakeState(HandshakeState.PATTERN_ID_IK, HandshakeState.INITIATOR, _edhThread);
|
state = new HandshakeState(HandshakeState.PATTERN_ID_IK, HandshakeState.INITIATOR, _edhThread);
|
||||||
@ -635,7 +638,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());
|
byte[] payload = createPayload(cloves, cloves.getExpiration(), replyDI);
|
||||||
|
|
||||||
byte[] enc = new byte[KEYLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
byte[] enc = new byte[KEYLEN + KEYLEN + MACLEN + payload.length + MACLEN];
|
||||||
try {
|
try {
|
||||||
@ -681,10 +684,12 @@ public final class ECIESAEADEngine {
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param state must have already been cloned
|
* @param state must have already been cloned
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return encrypted data or null on failure
|
* @return encrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
private byte[] encryptNewSessionReply(CloveSet cloves, PublicKey target, HandshakeState state,
|
private byte[] encryptNewSessionReply(CloveSet cloves, PublicKey target, HandshakeState state,
|
||||||
RatchetSessionTag currentTag, RatchetSKM keyManager) {
|
RatchetSessionTag currentTag, RatchetSKM keyManager,
|
||||||
|
DeliveryInstructions replyDI) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("State before encrypt new session reply: " + state);
|
_log.debug("State before encrypt new session reply: " + state);
|
||||||
byte[] tag = currentTag.getData();
|
byte[] tag = currentTag.getData();
|
||||||
@ -692,7 +697,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);
|
byte[] payload = createPayload(cloves, 0, replyDI);
|
||||||
|
|
||||||
// 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];
|
||||||
@ -752,12 +757,14 @@ public final class ECIESAEADEngine {
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param target unused, this is AEAD encrypt only using the session key and tag
|
* @param target unused, this is AEAD encrypt only using the session key and tag
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return encrypted data or null on failure
|
* @return encrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
private byte[] encryptExistingSession(CloveSet cloves, PublicKey target, SessionKeyAndNonce key,
|
private byte[] encryptExistingSession(CloveSet cloves, PublicKey target, SessionKeyAndNonce key,
|
||||||
RatchetSessionTag currentTag) {
|
RatchetSessionTag currentTag,
|
||||||
|
DeliveryInstructions replyDI) {
|
||||||
byte rawTag[] = currentTag.getData();
|
byte rawTag[] = currentTag.getData();
|
||||||
byte[] payload = createPayload(cloves, 0);
|
byte[] payload = createPayload(cloves, 0, replyDI);
|
||||||
byte encr[] = encryptAEADBlock(rawTag, payload, key, key.getNonce());
|
byte encr[] = encryptAEADBlock(rawTag, payload, key, key.getNonce());
|
||||||
System.arraycopy(rawTag, 0, encr, 0, TAGLEN);
|
System.arraycopy(rawTag, 0, encr, 0, TAGLEN);
|
||||||
return encr;
|
return encr;
|
||||||
@ -831,6 +838,16 @@ public final class ECIESAEADEngine {
|
|||||||
nextKey = next;
|
nextKey = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void gotAck(int id, int n) {
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("Got ACK block: " + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotAckRequest(int id, DeliveryInstructions di) {
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("Got ACK REQUEST block: " + di);
|
||||||
|
}
|
||||||
|
|
||||||
public void gotTermination(int reason, long count) {
|
public void gotTermination(int reason, long count) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Got TERMINATION block, reason: " + reason + " count: " + count);
|
_log.debug("Got TERMINATION block, reason: " + reason + " count: " + count);
|
||||||
@ -849,12 +866,15 @@ public final class ECIESAEADEngine {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param expiration if greater than zero, add a DateTime block
|
* @param expiration if greater than zero, add a DateTime block
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
*/
|
*/
|
||||||
private byte[] createPayload(CloveSet cloves, long expiration) {
|
private byte[] createPayload(CloveSet cloves, long expiration, DeliveryInstructions replyDI) {
|
||||||
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 (replyDI != null)
|
||||||
|
numblocks++;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
List<Block> blocks = new ArrayList<Block>(numblocks);
|
List<Block> blocks = new ArrayList<Block>(numblocks);
|
||||||
if (expiration > 0) {
|
if (expiration > 0) {
|
||||||
@ -868,6 +888,12 @@ public final class ECIESAEADEngine {
|
|||||||
blocks.add(block);
|
blocks.add(block);
|
||||||
len += block.getTotalLength();
|
len += block.getTotalLength();
|
||||||
}
|
}
|
||||||
|
if (replyDI != null) {
|
||||||
|
// put after the cloves so recipient has any LS garlic
|
||||||
|
Block block = new AckRequestBlock(0, replyDI);
|
||||||
|
blocks.add(block);
|
||||||
|
len += block.getTotalLength();
|
||||||
|
}
|
||||||
int padlen = 1 + _context.random().nextInt(MAXPAD);
|
int padlen = 1 + _context.random().nextInt(MAXPAD);
|
||||||
// random data
|
// random data
|
||||||
//Block block = new PaddingBlock(_context, padlen);
|
//Block block = new PaddingBlock(_context, padlen);
|
||||||
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.data.i2np.DeliveryInstructions;
|
||||||
import net.i2p.data.i2np.GarlicClove;
|
import net.i2p.data.i2np.GarlicClove;
|
||||||
import net.i2p.data.i2np.GarlicMessage;
|
import net.i2p.data.i2np.GarlicMessage;
|
||||||
import net.i2p.data.i2np.I2NPMessage;
|
import net.i2p.data.i2np.I2NPMessage;
|
||||||
@ -61,6 +62,16 @@ class RatchetPayload {
|
|||||||
*/
|
*/
|
||||||
public void gotNextKey(NextSessionKey nextKey);
|
public void gotNextKey(NextSessionKey nextKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public void gotAck(int id, int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public void gotAckRequest(int id, DeliveryInstructions di);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For stats.
|
* For stats.
|
||||||
* @param paddingLength the number of padding bytes, not including the 3-byte block header
|
* @param paddingLength the number of padding bytes, not including the 3-byte block header
|
||||||
@ -123,6 +134,7 @@ class RatchetPayload {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BLOCK_NEXTKEY:
|
case BLOCK_NEXTKEY:
|
||||||
|
{
|
||||||
if (len != 34)
|
if (len != 34)
|
||||||
throw new IOException("Bad length for NEXTKEY: " + len);
|
throw new IOException("Bad length for NEXTKEY: " + len);
|
||||||
int id = (int) DataHelper.fromLong(payload, i, 2);
|
int id = (int) DataHelper.fromLong(payload, i, 2);
|
||||||
@ -130,6 +142,30 @@ class RatchetPayload {
|
|||||||
System.arraycopy(payload, i + 2, data, 0, 32);
|
System.arraycopy(payload, i + 2, data, 0, 32);
|
||||||
NextSessionKey nsk = new NextSessionKey(data, id);
|
NextSessionKey nsk = new NextSessionKey(data, id);
|
||||||
cb.gotNextKey(nsk);
|
cb.gotNextKey(nsk);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLOCK_ACKKEY:
|
||||||
|
{
|
||||||
|
if (len < 4 || (len % 4) != 0)
|
||||||
|
throw new IOException("Bad length for REPLYDI: " + len);
|
||||||
|
for (int j = i; j < i + len; j += 4) {
|
||||||
|
int id = (int) DataHelper.fromLong(payload, j, 2);
|
||||||
|
int n = (int) DataHelper.fromLong(payload, j + 2, 2);
|
||||||
|
cb.gotAck(id, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLOCK_REPLYDI:
|
||||||
|
{
|
||||||
|
if (len < 6)
|
||||||
|
throw new IOException("Bad length for REPLYDI: " + len);
|
||||||
|
int id = (int) DataHelper.fromLong(payload, i, 4);
|
||||||
|
DeliveryInstructions di = new DeliveryInstructions();
|
||||||
|
di.readBytes(payload, i + 5);
|
||||||
|
cb.gotAckRequest(id, di);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLOCK_TERMINATION:
|
case BLOCK_TERMINATION:
|
||||||
@ -318,6 +354,53 @@ class RatchetPayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public static class AckBlock extends Block {
|
||||||
|
private final byte[] data;
|
||||||
|
|
||||||
|
public AckBlock(int keyID, int n) {
|
||||||
|
super(BLOCK_ACKKEY);
|
||||||
|
data = new byte[4];
|
||||||
|
DataHelper.toLong(data, 0, 2, keyID);
|
||||||
|
DataHelper.toLong(data, 2, 2, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDataLength() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int writeData(byte[] tgt, int off) {
|
||||||
|
System.arraycopy(data, 0, tgt, off, data.length);
|
||||||
|
return off + data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public static class AckRequestBlock extends Block {
|
||||||
|
private final byte[] data;
|
||||||
|
|
||||||
|
public AckRequestBlock(int sessionID, DeliveryInstructions di) {
|
||||||
|
super(BLOCK_REPLYDI);
|
||||||
|
data = new byte[5 + di.getSize()];
|
||||||
|
DataHelper.toLong(data, 0, 4, sessionID);
|
||||||
|
// flag is zero
|
||||||
|
di.writeBytes(data, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDataLength() {
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int writeData(byte[] tgt, int off) {
|
||||||
|
System.arraycopy(data, 0, tgt, off, data.length);
|
||||||
|
return off + data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class TerminationBlock extends Block {
|
public static class TerminationBlock extends Block {
|
||||||
private final byte rsn;
|
private final byte rsn;
|
||||||
private final long rcvd;
|
private final long rcvd;
|
||||||
|
@ -24,6 +24,7 @@ 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;
|
||||||
|
import net.i2p.data.i2np.DeliveryInstructions;
|
||||||
import net.i2p.data.i2np.GarlicClove;
|
import net.i2p.data.i2np.GarlicClove;
|
||||||
import net.i2p.data.i2np.GarlicMessage;
|
import net.i2p.data.i2np.GarlicMessage;
|
||||||
import net.i2p.data.i2np.I2NPMessage;
|
import net.i2p.data.i2np.I2NPMessage;
|
||||||
@ -251,12 +252,14 @@ public class GarlicMessageBuilder {
|
|||||||
* @param config how/what to wrap
|
* @param config how/what to wrap
|
||||||
* @param target public key of the location being garlic routed to (may be null if we
|
* @param target public key of the location being garlic routed to (may be null if we
|
||||||
* know the encryptKey and encryptTag)
|
* know the encryptKey and encryptTag)
|
||||||
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return null if expired or on other errors
|
* @return null if expired or on other errors
|
||||||
* @throws IllegalArgumentException on error
|
* @throws IllegalArgumentException on error
|
||||||
* @since 0.9.44
|
* @since 0.9.44
|
||||||
*/
|
*/
|
||||||
static GarlicMessage buildECIESMessage(RouterContext ctx, GarlicConfig config,
|
static GarlicMessage buildECIESMessage(RouterContext ctx, GarlicConfig config,
|
||||||
PublicKey target, Hash from, SessionKeyManager skm) {
|
PublicKey target, Hash from, SessionKeyManager skm,
|
||||||
|
DeliveryInstructions replyDI) {
|
||||||
PublicKey key = config.getRecipientPublicKey();
|
PublicKey key = config.getRecipientPublicKey();
|
||||||
if (key.getType() != EncType.ECIES_X25519)
|
if (key.getType() != EncType.ECIES_X25519)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
@ -286,7 +289,7 @@ public class GarlicMessageBuilder {
|
|||||||
log.warn("No SKM for " + from.toBase32());
|
log.warn("No SKM for " + from.toBase32());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
byte encData[] = ctx.eciesEngine().encrypt(cloveSet, target, priv, rskm);
|
byte encData[] = ctx.eciesEngine().encrypt(cloveSet, target, priv, rskm, replyDI);
|
||||||
if (encData == null) {
|
if (encData == null) {
|
||||||
if (log.shouldWarn())
|
if (log.shouldWarn())
|
||||||
log.warn("Encrypt fail for " + from.toBase32());
|
log.warn("Encrypt fail for " + from.toBase32());
|
||||||
@ -438,6 +441,11 @@ public class GarlicMessageBuilder {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a single clove
|
||||||
|
*
|
||||||
|
* @since 0.9.44
|
||||||
|
*/
|
||||||
private static GarlicClove buildECIESClove(RouterContext ctx, PayloadGarlicConfig config) {
|
private static GarlicClove buildECIESClove(RouterContext ctx, PayloadGarlicConfig config) {
|
||||||
GarlicClove clove = new GarlicClove(ctx);
|
GarlicClove clove = new GarlicClove(ctx);
|
||||||
clove.setData(config.getPayload());
|
clove.setData(config.getPayload());
|
||||||
|
@ -118,13 +118,36 @@ class OutboundClientMessageJobHelper {
|
|||||||
SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(from);
|
SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(from);
|
||||||
if (skm == null)
|
if (skm == null)
|
||||||
return null;
|
return null;
|
||||||
|
boolean isECIES = recipientPK.getType() == EncType.ECIES_X25519;
|
||||||
|
// force ack off if ECIES
|
||||||
|
boolean ackInGarlic = isECIES ? false : requireAck;
|
||||||
GarlicConfig config = createGarlicConfig(ctx, replyToken, expiration, recipientPK, dataClove,
|
GarlicConfig config = createGarlicConfig(ctx, replyToken, expiration, recipientPK, dataClove,
|
||||||
from, dest, replyTunnel, requireAck, bundledReplyLeaseSet, skm);
|
from, dest, replyTunnel, ackInGarlic, bundledReplyLeaseSet, skm);
|
||||||
if (config == null)
|
if (config == null)
|
||||||
return null;
|
return null;
|
||||||
GarlicMessage msg;
|
GarlicMessage msg;
|
||||||
if (recipientPK.getType() == EncType.ECIES_X25519) {
|
if (isECIES) {
|
||||||
msg = GarlicMessageBuilder.buildECIESMessage(ctx, config, recipientPK, from, skm);
|
DeliveryInstructions di;
|
||||||
|
if (requireAck) {
|
||||||
|
// setup reply DI
|
||||||
|
di = new DeliveryInstructions();
|
||||||
|
if (bundledReplyLeaseSet != null) {
|
||||||
|
di.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_DESTINATION);
|
||||||
|
di.setDestination(from);
|
||||||
|
} else if (replyTunnel != null) {
|
||||||
|
di.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
|
||||||
|
TunnelId replyToTunnelId = replyTunnel.getReceiveTunnelId(0);
|
||||||
|
Hash replyToTunnelRouter = replyTunnel.getPeer(0);
|
||||||
|
di.setRouter(replyToTunnelRouter);
|
||||||
|
di.setTunnelId(replyToTunnelId);
|
||||||
|
} else {
|
||||||
|
// shouldn't happen
|
||||||
|
di = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
di = null;
|
||||||
|
}
|
||||||
|
msg = GarlicMessageBuilder.buildECIESMessage(ctx, config, recipientPK, from, skm, di);
|
||||||
} else {
|
} else {
|
||||||
// no use sending tags unless we have a reply token set up already
|
// no use sending tags unless we have a reply token set up already
|
||||||
int tagsToSend = replyToken >= 0 ? (tagsToSendOverride > 0 ? tagsToSendOverride : skm.getTagsToSend()) : 0;
|
int tagsToSend = replyToken >= 0 ? (tagsToSendOverride > 0 ? tagsToSendOverride : skm.getTagsToSend()) : 0;
|
||||||
|
Reference in New Issue
Block a user