diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java index 0597db5f19..b49f51a07f 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java @@ -188,8 +188,7 @@ public class EditBean extends IndexBean { /** @since 0.9.12 */ public boolean isSigTypeAvailable(int code) { - SigType type = SigType.getByCode(code); - return type != null && type.isAvailable(); + return SigType.isAvailable(code); } /** @since 0.8.9 */ diff --git a/core/java/src/net/i2p/data/PrivateKey.java b/core/java/src/net/i2p/data/PrivateKey.java index f10248189e..163edcc3f5 100644 --- a/core/java/src/net/i2p/data/PrivateKey.java +++ b/core/java/src/net/i2p/data/PrivateKey.java @@ -50,6 +50,7 @@ public class PrivateKey extends SimpleDataStructure { /** derives a new PublicKey object derived from the secret contents * of this PrivateKey * @return a PublicKey object + * @throws IllegalArgumentException on bad key */ public PublicKey toPublic() { return KeyGenerator.getPublicKey(this); diff --git a/router/java/src/net/i2p/data/router/RouterInfo.java b/router/java/src/net/i2p/data/router/RouterInfo.java index 71a1157fab..390b013ec5 100644 --- a/router/java/src/net/i2p/data/router/RouterInfo.java +++ b/router/java/src/net/i2p/data/router/RouterInfo.java @@ -30,6 +30,7 @@ import net.i2p.crypto.DSAEngine; import net.i2p.crypto.SHA1; import net.i2p.crypto.SHA1Hash; import net.i2p.crypto.SHA256Generator; +import net.i2p.crypto.SigType; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; @@ -532,10 +533,17 @@ public class RouterInfo extends DatabaseEntry { InputStream din; MessageDigest digest; if (verifySig) { - digest = _identity.getSigningPublicKey().getType().getDigestInstance(); - // TODO any better way? - digest.update(_identity.toByteArray()); - din = new DigestInputStream(in, digest); + SigType type = _identity.getSigningPublicKey().getType(); + if (type != SigType.EdDSA_SHA512_Ed25519) { + // This won't work for EdDSA + digest = _identity.getSigningPublicKey().getType().getDigestInstance(); + // TODO any better way? + digest.update(_identity.toByteArray()); + din = new DigestInputStream(in, digest); + } else { + digest = null; + din = in; + } } else { digest = null; din = in; @@ -569,10 +577,16 @@ public class RouterInfo extends DatabaseEntry { _signature.readBytes(in); if (verifySig) { - SimpleDataStructure hash = _identity.getSigningPublicKey().getType().getHashInstance(); - hash.setData(digest.digest()); - _isValid = DSAEngine.getInstance().verifySignature(_signature, hash, _identity.getSigningPublicKey()); - _validated = true; + SigType type = _identity.getSigningPublicKey().getType(); + if (type != SigType.EdDSA_SHA512_Ed25519) { + // This won't work for EdDSA + SimpleDataStructure hash = _identity.getSigningPublicKey().getType().getHashInstance(); + hash.setData(digest.digest()); + _isValid = DSAEngine.getInstance().verifySignature(_signature, hash, _identity.getSigningPublicKey()); + _validated = true; + } else { + doValidate(); + } if (!_isValid) { throw new DataFormatException("Bad sig"); } diff --git a/router/java/src/net/i2p/router/LeaseSetKeys.java b/router/java/src/net/i2p/router/LeaseSetKeys.java index abfc566df9..849e54f47f 100644 --- a/router/java/src/net/i2p/router/LeaseSetKeys.java +++ b/router/java/src/net/i2p/router/LeaseSetKeys.java @@ -40,7 +40,7 @@ public class LeaseSetKeys { /** * Key with which a LeaseSet can be revoked (by republishing it with no Leases) * - * @deprecated unused + * Deprecated, unused */ public SigningPrivateKey getRevocationKey() { return _revocationKey; } diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index cdcc0008cf..74e9102cbd 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -12,6 +12,7 @@ import java.util.Properties; import net.i2p.CoreVersion; import net.i2p.crypto.SigType; +import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.Payload; import net.i2p.data.i2cp.BandwidthLimitsMessage; @@ -37,6 +38,7 @@ import net.i2p.data.i2cp.SessionId; import net.i2p.data.i2cp.SessionStatusMessage; import net.i2p.data.i2cp.SetDateMessage; import net.i2p.router.ClientTunnelSettings; +import net.i2p.router.LeaseSetKeys; import net.i2p.router.RouterContext; import net.i2p.util.Log; import net.i2p.util.PasswordManager; @@ -367,8 +369,31 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi _runner.disconnectClient("Invalid CreateLeaseSetMessage"); return; } - - _context.keyManager().registerKeys(message.getLeaseSet().getDestination(), message.getSigningPrivateKey(), message.getPrivateKey()); + Destination dest = _runner.getConfig().getDestination(); + Destination ndest = message.getLeaseSet().getDestination(); + if (!dest.equals(ndest)) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Different destination in LS"); + _runner.disconnectClient("Different destination in LS"); + return; + } + LeaseSetKeys keys = _context.keyManager().getKeys(dest); + if (keys == null || + !message.getPrivateKey().equals(keys.getDecryptionKey())) { + // Verify and register crypto keys if new or if changed + // Private crypto key should never change + if (!message.getPrivateKey().toPublic().equals(dest.getPublicKey())) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Private/public crypto key mismatch in LS"); + _runner.disconnectClient("Private/public crypto key mismatch in LS"); + return; + } + // just register new SPK, don't verify, unused + _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); + } else if (!message.getSigningPrivateKey().equals(keys.getRevocationKey())) { + // just register new SPK, don't verify, unused + _context.keyManager().registerKeys(dest, message.getSigningPrivateKey(), message.getPrivateKey()); + } try { _context.netDb().publish(message.getLeaseSet()); } catch (IllegalArgumentException iae) { diff --git a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java index a343939f98..83f2c7a7ef 100644 --- a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java +++ b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java @@ -170,9 +170,12 @@ public class CreateRouterInfoJob extends JobImpl { String sstype = ctx.getProperty(PROP_ROUTER_SIGTYPE); if (sstype != null) { SigType ntype = SigType.parseSigType(sstype); - if (ntype != null && ntype.isAvailable()) + if (ntype != null) cstype = ntype; } + // fallback? + if (cstype != SigType.DSA_SHA1 && !cstype.isAvailable()) + cstype = SigType.DSA_SHA1; return cstype; }