From 273902f6164dae02bbd2e89ce47d65b2dca7338e Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 2 Sep 2020 13:26:10 +0000 Subject: [PATCH] SSU: Randomize intro key --- router/java/src/net/i2p/router/Router.java | 1 + .../router/transport/udp/UDPTransport.java | 27 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index e1984d8172..62ac1ec85b 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -1267,6 +1267,7 @@ public class Router implements RouterClock.ClockShiftListener { synchronized(_configFileLock) { removeConfigSetting(UDPTransport.PROP_INTERNAL_PORT); removeConfigSetting(UDPTransport.PROP_EXTERNAL_PORT); + removeConfigSetting(UDPTransport.PROP_INTRO_KEY); removeConfigSetting(NTCPTransport.PROP_I2NP_NTCP_PORT); removeConfigSetting(NTCPTransport.PROP_NTCP2_SP); removeConfigSetting(NTCPTransport.PROP_NTCP2_IV); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index abc40021bf..37617a8761 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -20,8 +20,10 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import net.i2p.CoreVersion; import net.i2p.crypto.HMACGenerator; import net.i2p.crypto.SigType; +import net.i2p.data.Base64; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataHelper; import net.i2p.data.Hash; @@ -180,6 +182,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority /** override the "large" (max) MTU, default is PeerState.LARGE_MTU */ private static final String PROP_DEFAULT_MTU = "i2np.udp.mtu"; private static final String PROP_ADVANCED = "routerconsole.advanced"; + /** @since 0.9.48 */ + public static final String PROP_INTRO_KEY = "i2np.udp.introKey"; private static final String CAP_TESTING = Character.toString(UDPAddress.CAPACITY_TESTING); private static final String CAP_TESTING_INTRO = CAP_TESTING + UDPAddress.CAPACITY_INTRODUCER; @@ -207,6 +211,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority /** minimum peers volunteering to be introducers if we need that */ private static final int MIN_INTRODUCER_POOL = 5; static final long INTRODUCER_EXPIRATION_MARGIN = 20*60*1000L; + private static final long MIN_DOWNTIME_TO_REKEY = 30*24*60*60*1000L; private static final int[] BID_VALUES = { 15, 20, 50, 65, 80, 95, 100, 115, TransportBid.TRANSIENT_FAIL }; private static final int FAST_PREFERRED_BID = 0; @@ -382,8 +387,26 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority UDPPacket.clearCache(); if (_log.shouldLog(Log.WARN)) _log.warn("Starting SSU transport listening"); - _introKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]); - System.arraycopy(_context.routerHash().getData(), 0, _introKey.getData(), 0, SessionKey.KEYSIZE_BYTES); + byte[] ikey = new byte[SessionKey.KEYSIZE_BYTES]; + _introKey = new SessionKey(ikey); + if (VersionComparator.comp(CoreVersion.VERSION, "0.9.48") >= 0) { + String sikey = _context.getProperty(PROP_INTRO_KEY); + if (sikey != null && + _context.getEstimatedDowntime() < MIN_DOWNTIME_TO_REKEY) { + byte[] saved = Base64.decode(sikey); + if (saved != null && saved.length == SessionKey.KEYSIZE_BYTES) { + System.arraycopy(saved, 0, ikey, 0, SessionKey.KEYSIZE_BYTES); + } else { + _context.random().nextBytes(ikey); + _context.router().saveConfig(PROP_INTRO_KEY, Base64.encode(ikey)); + } + } else { + _context.random().nextBytes(ikey); + _context.router().saveConfig(PROP_INTRO_KEY, Base64.encode(ikey)); + } + } else { + System.arraycopy(_context.routerHash().getData(), 0, ikey, 0, SessionKey.KEYSIZE_BYTES); + } // bind host // This is not exposed in the UI and in practice is always null. -- GitLab