Router: MessageWrapper.wrap() and GMB support for ECIES (prop. #156 WIP)

NetDB parts still TODO
Remove PK param from GMB.buildECIESMessage(), already in config
This commit is contained in:
zzz
2020-10-15 11:50:11 +00:00
parent b2f060795c
commit e54950e02e
5 changed files with 86 additions and 15 deletions

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 6;
public final static long BUILD = 7;
/** for example "-test" */
public final static String EXTRA = "";

View File

@ -275,16 +275,14 @@ public class GarlicMessageBuilder {
* Called by OCMJH only.
*
* @param ctx scope
* @param config how/what to wrap
* @param target public key of the location being garlic routed to (may be null if we
* know the encryptKey and encryptTag)
* @param config how/what to wrap, must have key set with setRecipientPublicKey()
* @param callback may be null
* @return null if expired or on other errors
* @throws IllegalArgumentException on error
* @since 0.9.44
*/
static GarlicMessage buildECIESMessage(RouterContext ctx, GarlicConfig config,
PublicKey target, Hash from, Destination to, SessionKeyManager skm,
Hash from, Destination to, SessionKeyManager skm,
ReplyCallback callback) {
PublicKey key = config.getRecipientPublicKey();
if (key.getType() != EncType.ECIES_X25519)
@ -315,7 +313,7 @@ public class GarlicMessageBuilder {
log.warn("No SKM for " + from.toBase32());
return null;
}
byte encData[] = ctx.eciesEngine().encrypt(cloveSet, target, to, priv, rskm, callback);
byte encData[] = ctx.eciesEngine().encrypt(cloveSet, key, to, priv, rskm, callback);
if (encData == null) {
if (log.shouldWarn())
log.warn("Encrypt fail for " + from.toBase32());
@ -334,6 +332,42 @@ public class GarlicMessageBuilder {
return msg;
}
/**
* Encrypt from an anonymous source.
* ECIES_X25519 only.
* Called by MessageWrapper only.
*
* @param ctx scope
* @param config how/what to wrap, must have key set with setRecipientPublicKey()
* @throws IllegalArgumentException on error
* @since 0.9.48
*/
public static GarlicMessage buildECIESMessage(RouterContext ctx, GarlicConfig config) {
PublicKey key = config.getRecipientPublicKey();
if (key.getType() != EncType.ECIES_X25519)
throw new IllegalArgumentException();
Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
GarlicMessage msg = new GarlicMessage(ctx);
CloveSet cloveSet = buildECIESCloveSet(ctx, config);
byte encData[] = ctx.eciesEngine().encrypt(cloveSet, key);
if (encData == null) {
if (log.shouldWarn())
log.warn("Encrypt fail for " + config);
return null;
}
msg.setData(encData);
msg.setMessageExpiration(config.getExpiration());
long timeFromNow = config.getExpiration() - ctx.clock().now();
if (timeFromNow < 1*1000) {
if (log.shouldDebug())
log.debug("Building a message expiring in " + timeFromNow + "ms: " + config, new Exception("created by"));
return null;
}
if (log.shouldDebug())
log.debug("Built ECIES CloveSet (" + config.getCloveCount() + " cloves) in " + msg);
return msg;
}
/****
private static void noteWrap(RouterContext ctx, GarlicMessage wrapper, GarlicConfig contained) {
for (int i = 0; i < contained.getCloveCount(); i++) {

View File

@ -131,7 +131,7 @@ class OutboundClientMessageJobHelper {
return null;
GarlicMessage msg;
if (isECIES) {
msg = GarlicMessageBuilder.buildECIESMessage(ctx, config, recipientPK, from, dest, skm, callback);
msg = GarlicMessageBuilder.buildECIESMessage(ctx, config, from, dest, skm, callback);
} else {
// no use sending tags unless we have a reply token set up already
int tagsToSend = replyToken >= 0 ? (tagsToSendOverride > 0 ? tagsToSendOverride : skm.getTagsToSend()) : 0;
@ -146,6 +146,8 @@ class OutboundClientMessageJobHelper {
* Make the top-level config, with a data clove, an optional ack clove, and
* an optional leaseset clove.
*
* The returned GarlicConfig will have the recipientPublicKey set.
*
* @param dataClove may be null for ECIES-layer ack
* @param replyTunnel non-null if requireAck is true or bundledReplyLeaseSet is non-null
* @param requireAck if true, bundle replyToken in an ack clove

View File

@ -125,16 +125,13 @@ public class MessageWrapper {
/**
* Garlic wrap a message from nobody, destined for a router,
* to hide the contents from the OBEP.
* Forces ElGamal.
* Forces full asymmetric encryption.
*
* @param to must be ELGAMAL_2048 EncType
* @param to must be ELGAMAL_2048 or ECIES_X25519 EncType
* @return null on encrypt failure
* @since 0.9.5
*/
static GarlicMessage wrap(RouterContext ctx, I2NPMessage m, RouterInfo to) {
PublicKey key = to.getIdentity().getPublicKey();
if (key.getType() != EncType.ELGAMAL_2048)
return null;
PayloadGarlicConfig payload = new PayloadGarlicConfig(Certificate.NULL_CERT,
ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE),
@ -142,9 +139,19 @@ public class MessageWrapper {
DeliveryInstructions.LOCAL, m);
payload.setRecipient(to);
SessionKey sentKey = ctx.keyGenerator().generateSessionKey();
GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, payload, null,
key, sentKey, null);
PublicKey key = to.getIdentity().getPublicKey();
EncType type = key.getType();
GarlicMessage msg;
if (type == EncType.ELGAMAL_2048) {
SessionKey sentKey = ctx.keyGenerator().generateSessionKey();
msg = GarlicMessageBuilder.buildMessage(ctx, payload, null, key, sentKey, null);
} else if (type == EncType.ECIES_X25519) {
payload.setRecipientPublicKey(key);
msg = GarlicMessageBuilder.buildECIESMessage(ctx, payload);
} else {
// unsupported
msg = null;
}
return msg;
}