From 7d11fb269ef4940fada96ff9d6311273870ae50b Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 3 Feb 2019 12:59:53 +0000 Subject: [PATCH] I2CP: Remove revocation private key from CreateLeaseset2 message Use correct key to sign SessionConfig with offline keys LeaseSetKeys cleanups --- .../i2p/client/impl/I2CPMessageProducer.java | 3 +- .../impl/RequestLeaseSetMessageHandler.java | 16 ++++++---- .../i2p/data/i2cp/CreateLeaseSet2Message.java | 30 +++++++++++-------- .../i2p/data/i2cp/CreateLeaseSetMessage.java | 2 +- .../src/net/i2p/data/i2cp/SessionConfig.java | 5 +++- .../java/src/net/i2p/router/KeyManager.java | 5 +++- .../java/src/net/i2p/router/LeaseSetKeys.java | 11 ++----- .../client/ClientMessageEventListener.java | 10 +++++-- .../i2p/router/client/LeaseRequestState.java | 1 - 9 files changed, 48 insertions(+), 35 deletions(-) diff --git a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java index 4448122d0..f49f08086 100644 --- a/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java +++ b/core/java/src/net/i2p/client/impl/I2CPMessageProducer.java @@ -362,6 +362,7 @@ class I2CPMessageProducer { * This method is misnamed, it does not create the LeaseSet, * the caller does that. * + * @param signingPriv ignored for LS2 */ public void createLeaseSet(I2PSessionImpl session, LeaseSet leaseSet, SigningPrivateKey signingPriv, List privs) throws I2PSessionException { @@ -370,6 +371,7 @@ class I2CPMessageProducer { if (type == DatabaseEntry.KEY_TYPE_LEASESET) { msg = new CreateLeaseSetMessage(); msg.setPrivateKey(privs.get(0)); + msg.setSigningPrivateKey(signingPriv); } else { CreateLeaseSet2Message msg2 = new CreateLeaseSet2Message(); for (PrivateKey priv : privs) { @@ -378,7 +380,6 @@ class I2CPMessageProducer { msg = msg2; } msg.setLeaseSet(leaseSet); - msg.setSigningPrivateKey(signingPriv); SessionId sid = session.getSessionId(); if (sid == null) { _log.error(session.toString() + " create LS w/o session", new Exception()); diff --git a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java index f0b9d9e3b..259e6d08d 100644 --- a/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java +++ b/core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java @@ -304,16 +304,20 @@ class RequestLeaseSetMessageHandler extends HandlerImpl { } try { leaseSet.sign(session.getPrivateKey()); - // Workaround for unparsable serialized signing private key for revocation - // Send him a dummy DSA_SHA1 private key since it's unused anyway - // See CreateLeaseSetMessage.doReadMessage() - // For LS1 only SigningPrivateKey spk = li.getSigningPrivateKey(); - if (!_context.isRouterContext() && spk.getType() != SigType.DSA_SHA1 && - !(leaseSet instanceof LeaseSet2)) { + if (isLS2) { + // no revocation key in LS2 + spk = null; + } else if (!_context.isRouterContext() && spk.getType() != SigType.DSA_SHA1) { + // Workaround for unparsable serialized signing private key for revocation + // Send him a dummy DSA_SHA1 private key since it's unused anyway + // See CreateLeaseSetMessage.doReadMessage() + // For LS1 only byte[] dummy = new byte[SigningPrivateKey.KEYSIZE_BYTES]; _context.random().nextBytes(dummy); spk = new SigningPrivateKey(dummy); + if (_log.shouldDebug()) + _log.debug("Generated random dummy SPK " + spk); } session.getProducer().createLeaseSet(session, leaseSet, spk, li.getPrivateKeys()); session.setLeaseSet(leaseSet); diff --git a/core/java/src/net/i2p/data/i2cp/CreateLeaseSet2Message.java b/core/java/src/net/i2p/data/i2cp/CreateLeaseSet2Message.java index 0149b06bc..04d00d8cb 100644 --- a/core/java/src/net/i2p/data/i2cp/CreateLeaseSet2Message.java +++ b/core/java/src/net/i2p/data/i2cp/CreateLeaseSet2Message.java @@ -18,20 +18,21 @@ import net.i2p.data.LeaseSet2; import net.i2p.data.MetaLeaseSet; import net.i2p.data.PrivateKey; import net.i2p.data.PublicKey; -import net.i2p.data.SigningPrivateKey; /** * Like CreateLeaseSetMessage, but supports both old * and new LeaseSet types, including LS2, Meta, and Encrypted. + * Revocation keys are not present. + * Multiple public/private encryption keys are possible. * * For LS2: * Same as CreateLeaseSetMessage, but has a netdb type before - * the LeaseSet. SigningPrivateKey and PrivateKey(s) are + * the LeaseSet. PrivateKeys are * serialized after the LeaseSet, not before, so we can * infer the types from the LeaseSet. * * For Meta LS: - * SigningPrivateKey and PrivateKey are not present. + * PrivateKeys are not present. * * For Encrypted LS: * TODO @@ -105,8 +106,6 @@ public class CreateLeaseSet2Message extends CreateLeaseSetMessage { SigType stype = _leaseSet.getSignature().getType(); if (stype == null) throw new I2CPMessageException("Unsupported sig type"); - _signingPrivateKey = new SigningPrivateKey(stype); - _signingPrivateKey.readBytes(in); if (type == DatabaseEntry.KEY_TYPE_LS2 || type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) { LeaseSet2 ls2 = (LeaseSet2) _leaseSet; @@ -140,20 +139,22 @@ public class CreateLeaseSet2Message extends CreateLeaseSetMessage { protected byte[] doWriteMessage() throws I2CPMessageException, IOException { int type = _leaseSet.getType(); if (_sessionId == null || _leaseSet == null || - (type != DatabaseEntry.KEY_TYPE_META_LS2 && (_signingPrivateKey == null || _privateKey == null))) + (type != DatabaseEntry.KEY_TYPE_META_LS2 && _privateKey == null)) throw new I2CPMessageException("Unable to write out the message as there is not enough data"); int size = 4 // sessionId + 1 // type - + _leaseSet.size() - + _signingPrivateKey.length() - + _privateKey.length(); + + _leaseSet.size(); + if (type != DatabaseEntry.KEY_TYPE_META_LS2) { + for (PrivateKey pk : getPrivateKeys()) { + size += pk.length(); + } + } ByteArrayOutputStream os = new ByteArrayOutputStream(size); try { _sessionId.writeBytes(os); os.write(_leaseSet.getType()); _leaseSet.writeBytes(os); if (type != DatabaseEntry.KEY_TYPE_META_LS2) { - _signingPrivateKey.writeBytes(os); for (PrivateKey pk : getPrivateKeys()) { pk.writeBytes(os); } @@ -173,9 +174,12 @@ public class CreateLeaseSet2Message extends CreateLeaseSetMessage { public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[CreateLeaseSet2Message: "); - buf.append("\n\tLeaseSet: ").append(getLeaseSet()); - buf.append("\n\tSigningPrivateKey: ").append(getSigningPrivateKey()); - buf.append("\n\tPrivateKey: ").append(getPrivateKey()); + buf.append("\n\tLeaseSet: ").append(_leaseSet); + if (_leaseSet.getType() != DatabaseEntry.KEY_TYPE_META_LS2) { + for (PrivateKey pk : getPrivateKeys()) { + buf.append("\n\tPrivateKey: ").append(pk); + } + } buf.append("\n\tSessionId: ").append(getSessionId()); buf.append("]"); return buf.toString(); diff --git a/core/java/src/net/i2p/data/i2cp/CreateLeaseSetMessage.java b/core/java/src/net/i2p/data/i2cp/CreateLeaseSetMessage.java index 277e9cd91..d7e8048cf 100644 --- a/core/java/src/net/i2p/data/i2cp/CreateLeaseSetMessage.java +++ b/core/java/src/net/i2p/data/i2cp/CreateLeaseSetMessage.java @@ -28,7 +28,7 @@ public class CreateLeaseSetMessage extends I2CPMessageImpl { public final static int MESSAGE_TYPE = 4; protected SessionId _sessionId; protected LeaseSet _leaseSet; - protected SigningPrivateKey _signingPrivateKey; + private SigningPrivateKey _signingPrivateKey; protected PrivateKey _privateKey; public CreateLeaseSetMessage() { diff --git a/core/java/src/net/i2p/data/i2cp/SessionConfig.java b/core/java/src/net/i2p/data/i2cp/SessionConfig.java index 932b2f1cf..69072e9eb 100644 --- a/core/java/src/net/i2p/data/i2cp/SessionConfig.java +++ b/core/java/src/net/i2p/data/i2cp/SessionConfig.java @@ -346,7 +346,10 @@ public class SessionConfig extends DataStructureImpl { _destination = Destination.create(rawConfig); _options = DataHelper.readProperties(rawConfig); _creationDate = DataHelper.readDate(rawConfig); - _signature = new Signature(_destination.getSigningPublicKey().getType()); + SigningPublicKey spk = getTransientSigningPublicKey(); + if (spk == null) + spk = _destination.getSigningPublicKey(); + _signature = new Signature(spk.getType()); _signature.readBytes(rawConfig); } diff --git a/router/java/src/net/i2p/router/KeyManager.java b/router/java/src/net/i2p/router/KeyManager.java index cda22114f..b3d968786 100644 --- a/router/java/src/net/i2p/router/KeyManager.java +++ b/router/java/src/net/i2p/router/KeyManager.java @@ -109,7 +109,10 @@ public class KeyManager { */ public synchronized SigningPublicKey getSigningPublicKey() { return _signingPublicKey; } - /** client */ + /** + * client + * @param leaseRevocationPrivateKey unused, may be null + */ public void registerKeys(Destination dest, SigningPrivateKey leaseRevocationPrivateKey, PrivateKey endpointDecryptionKey) { if (_log.shouldLog(Log.INFO)) _log.info("Registering keys for destination " + dest.calculateHash().toBase64()); diff --git a/router/java/src/net/i2p/router/LeaseSetKeys.java b/router/java/src/net/i2p/router/LeaseSetKeys.java index 849e54f47..75556d817 100644 --- a/router/java/src/net/i2p/router/LeaseSetKeys.java +++ b/router/java/src/net/i2p/router/LeaseSetKeys.java @@ -8,20 +8,13 @@ package net.i2p.router; * */ -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import net.i2p.data.DataFormatException; -import net.i2p.data.DataHelper; -import net.i2p.data.DataStructureImpl; import net.i2p.data.Destination; import net.i2p.data.PrivateKey; import net.i2p.data.SigningPrivateKey; /** * Wrap up the keys given to the router when a destination connects to it. - * Used only by KeyManager. + * Used by KeyManager, ClientMessageEventListener, GarlicMessageReceiver. */ public class LeaseSetKeys { private final SigningPrivateKey _revocationKey; @@ -29,7 +22,7 @@ public class LeaseSetKeys { /** * @param dest unused - * @param revocationKey unused + * @param revocationKey unused, may be null * @param decryptionKey non-null */ public LeaseSetKeys(Destination dest, SigningPrivateKey revocationKey, PrivateKey decryptionKey) { diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 19783123d..28d927921 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -508,8 +508,14 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi return; } int type = ls.getType(); - if (type != DatabaseEntry.KEY_TYPE_META_LS2 && - (message.getPrivateKey() == null || message.getSigningPrivateKey() == null)) { + if (type != DatabaseEntry.KEY_TYPE_META_LS2 && message.getPrivateKey() == null) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Null private keys: " + message); + _runner.disconnectClient("Invalid CreateLeaseSetMessage - null private keys"); + return; + } + if (type == DatabaseEntry.KEY_TYPE_LEASESET && message.getSigningPrivateKey() == null) { + // revocation keys only in LS1 if (_log.shouldLog(Log.ERROR)) _log.error("Null private keys: " + message); _runner.disconnectClient("Invalid CreateLeaseSetMessage - null private keys"); diff --git a/router/java/src/net/i2p/router/client/LeaseRequestState.java b/router/java/src/net/i2p/router/client/LeaseRequestState.java index 2fb6b9760..a6c597edc 100644 --- a/router/java/src/net/i2p/router/client/LeaseRequestState.java +++ b/router/java/src/net/i2p/router/client/LeaseRequestState.java @@ -10,7 +10,6 @@ package net.i2p.router.client; import net.i2p.data.LeaseSet; import net.i2p.data.PrivateKey; -import net.i2p.data.SigningPrivateKey; import net.i2p.router.Job; /**