diff --git a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java index d950da78e..9ddced828 100644 --- a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java +++ b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java @@ -25,6 +25,8 @@ import net.i2p.crypto.EncType; import net.i2p.crypto.KeyGenerator; import net.i2p.crypto.KeyPair; import net.i2p.crypto.SigType; +import net.i2p.data.Base64; +import net.i2p.data.BlindData; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; @@ -66,6 +68,10 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { public static final String PROP_LS_TYPE = "i2cp.leaseSetType"; private static final String PROP_LS_ENCTYPE = "i2cp.leaseSetEncType"; private static final String PROP_SECRET = "i2cp.leaseSetSecret"; + private static final String PROP_AUTH_TYPE = "i2cp.leaseSetAuthType"; + private static final String PROP_PRIV_KEY = "i2cp.leaseSetPrivKey"; + private static final String PROP_DH = "i2cp.leaseSetClient.dh."; + private static final String PROP_PSK = "i2cp.leaseSetClient.psk."; public RequestLeaseSetMessageHandler(I2PAppContext context) { this(context, RequestLeaseSetMessage.MESSAGE_TYPE); @@ -309,7 +315,77 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { } } try { - leaseSet.sign(session.getPrivateKey()); + if (isLS2 && _ls2Type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) { + EncryptedLeaseSet els2 = (EncryptedLeaseSet) leaseSet; + String at = opts.getProperty(PROP_AUTH_TYPE, "0"); + if (at.equals("1")) { + int authType = BlindData.AUTH_DH; + List clientKeys = new ArrayList(4); + String pfx = PROP_DH; + String p = opts.getProperty(PROP_PRIV_KEY); + if (p == null) { + _log.error("No " + PROP_PRIV_KEY + " for DH auth"); + } else { + byte[] b = Base64.decode(p); + try { + PrivateKey pk = new PrivateKey(EncType.ECIES_X25519, b); + clientKeys.add(pk.toPublic()); + } catch (IllegalArgumentException iae) { + _log.error("Bad priv key: " + p, iae); + } + } + int i = 0; + while ((p = opts.getProperty(pfx + i)) != null) { + int colon = p.indexOf(':'); + if (colon >= 0) + p = p.substring(colon + 1); + byte[] b = Base64.decode(p); + try { + PublicKey pk = new PublicKey(EncType.ECIES_X25519, b); + clientKeys.add(pk); + } catch (IllegalArgumentException iae) { + _log.error("Bad client key: " + p, iae); + } + i++; + } + els2.sign(session.getPrivateKey(), authType, clientKeys); + } else if (at.equals("2")) { + int authType = BlindData.AUTH_PSK; + List clientKeys = new ArrayList(4); + String pfx = PROP_PSK; + String p = opts.getProperty(PROP_PRIV_KEY); + if (p == null) { + _log.error("No " + PROP_PRIV_KEY + " for PSK auth"); + } else { + byte[] b = Base64.decode(p); + try { + PrivateKey pk = new PrivateKey(EncType.ECIES_X25519, b); + clientKeys.add(pk); + } catch (IllegalArgumentException iae) { + _log.error("Bad priv key: " + p, iae); + } + } + int i = 0; + while ((p = opts.getProperty(pfx + i)) != null) { + int colon = p.indexOf(':'); + if (colon >= 0) + p = p.substring(colon + 1); + byte[] b = Base64.decode(p); + try { + PrivateKey pk = new PrivateKey(EncType.ECIES_X25519, b); + clientKeys.add(pk); + } catch (IllegalArgumentException iae) { + _log.error("Bad client key: " + p, iae); + } + i++; + } + els2.sign(session.getPrivateKey(), authType, clientKeys); + } else { + els2.sign(session.getPrivateKey()); + } + } else { + leaseSet.sign(session.getPrivateKey()); + } SigningPrivateKey spk = li.getSigningPrivateKey(); if (isLS2) { // no revocation key in LS2 diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 7fc3ac557..f0f023783 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -559,6 +559,15 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi _runner.disconnectClient(re.toString()); return; } + // per-client auth + // we have to do this before verifySignature() + String pk = cfg.getOptions().getProperty("i2cp.leaseSetPrivKey"); + if (pk != null) { + byte[] priv = Base64.decode(pk); + PrivateKey privkey = new PrivateKey(EncType.ECIES_X25519, priv); + EncryptedLeaseSet encls = (EncryptedLeaseSet) ls; + encls.setClientPrivateKey(privkey); + } // we have to do this before checking encryption keys below if (!ls.verifySignature()) { if (_log.shouldError()) @@ -648,16 +657,6 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi EncryptedLeaseSet encls = (EncryptedLeaseSet) ls; encls.setSecret(secret); } - // per-client auth - String pk = cfg.getOptions().getProperty("i2cp.leaseSetPrivKey"); - if (pk != null) { - byte[] priv = Base64.decode(pk); - if (priv == null) - throw new IllegalArgumentException("bad privkey"); - PrivateKey privkey = new PrivateKey(EncType.ECIES_X25519, priv); - EncryptedLeaseSet encls = (EncryptedLeaseSet) ls; - encls.setClientPrivateKey(privkey); - } } if (_log.shouldDebug()) _log.debug("Publishing: " + ls);