- Verify crypto key pair in LS
 - Verfiy same dest as before in LS
Router: Don't try to use an unavailable sig type for the router,
   even if it's the default
RouterInfo: Work around unsupported raw signatures for
   RI Ed25519 sig type
This commit is contained in:
zzz
2014-08-26 19:14:51 +00:00
parent 51f9d6d421
commit ed4fe56e7e
6 changed files with 56 additions and 14 deletions

View File

@ -188,8 +188,7 @@ public class EditBean extends IndexBean {
/** @since 0.9.12 */ /** @since 0.9.12 */
public boolean isSigTypeAvailable(int code) { public boolean isSigTypeAvailable(int code) {
SigType type = SigType.getByCode(code); return SigType.isAvailable(code);
return type != null && type.isAvailable();
} }
/** @since 0.8.9 */ /** @since 0.8.9 */

View File

@ -50,6 +50,7 @@ public class PrivateKey extends SimpleDataStructure {
/** derives a new PublicKey object derived from the secret contents /** derives a new PublicKey object derived from the secret contents
* of this PrivateKey * of this PrivateKey
* @return a PublicKey object * @return a PublicKey object
* @throws IllegalArgumentException on bad key
*/ */
public PublicKey toPublic() { public PublicKey toPublic() {
return KeyGenerator.getPublicKey(this); return KeyGenerator.getPublicKey(this);

View File

@ -30,6 +30,7 @@ import net.i2p.crypto.DSAEngine;
import net.i2p.crypto.SHA1; import net.i2p.crypto.SHA1;
import net.i2p.crypto.SHA1Hash; import net.i2p.crypto.SHA1Hash;
import net.i2p.crypto.SHA256Generator; import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SigType;
import net.i2p.data.DatabaseEntry; import net.i2p.data.DatabaseEntry;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
@ -532,10 +533,17 @@ public class RouterInfo extends DatabaseEntry {
InputStream din; InputStream din;
MessageDigest digest; MessageDigest digest;
if (verifySig) { if (verifySig) {
digest = _identity.getSigningPublicKey().getType().getDigestInstance(); SigType type = _identity.getSigningPublicKey().getType();
// TODO any better way? if (type != SigType.EdDSA_SHA512_Ed25519) {
digest.update(_identity.toByteArray()); // This won't work for EdDSA
din = new DigestInputStream(in, digest); digest = _identity.getSigningPublicKey().getType().getDigestInstance();
// TODO any better way?
digest.update(_identity.toByteArray());
din = new DigestInputStream(in, digest);
} else {
digest = null;
din = in;
}
} else { } else {
digest = null; digest = null;
din = in; din = in;
@ -569,10 +577,16 @@ public class RouterInfo extends DatabaseEntry {
_signature.readBytes(in); _signature.readBytes(in);
if (verifySig) { if (verifySig) {
SimpleDataStructure hash = _identity.getSigningPublicKey().getType().getHashInstance(); SigType type = _identity.getSigningPublicKey().getType();
hash.setData(digest.digest()); if (type != SigType.EdDSA_SHA512_Ed25519) {
_isValid = DSAEngine.getInstance().verifySignature(_signature, hash, _identity.getSigningPublicKey()); // This won't work for EdDSA
_validated = true; SimpleDataStructure hash = _identity.getSigningPublicKey().getType().getHashInstance();
hash.setData(digest.digest());
_isValid = DSAEngine.getInstance().verifySignature(_signature, hash, _identity.getSigningPublicKey());
_validated = true;
} else {
doValidate();
}
if (!_isValid) { if (!_isValid) {
throw new DataFormatException("Bad sig"); throw new DataFormatException("Bad sig");
} }

View File

@ -40,7 +40,7 @@ public class LeaseSetKeys {
/** /**
* Key with which a LeaseSet can be revoked (by republishing it with no Leases) * Key with which a LeaseSet can be revoked (by republishing it with no Leases)
* *
* @deprecated unused * Deprecated, unused
*/ */
public SigningPrivateKey getRevocationKey() { return _revocationKey; } public SigningPrivateKey getRevocationKey() { return _revocationKey; }

View File

@ -12,6 +12,7 @@ import java.util.Properties;
import net.i2p.CoreVersion; import net.i2p.CoreVersion;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.data.Destination;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.Payload; import net.i2p.data.Payload;
import net.i2p.data.i2cp.BandwidthLimitsMessage; 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.SessionStatusMessage;
import net.i2p.data.i2cp.SetDateMessage; import net.i2p.data.i2cp.SetDateMessage;
import net.i2p.router.ClientTunnelSettings; import net.i2p.router.ClientTunnelSettings;
import net.i2p.router.LeaseSetKeys;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.PasswordManager; import net.i2p.util.PasswordManager;
@ -367,8 +369,31 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
_runner.disconnectClient("Invalid CreateLeaseSetMessage"); _runner.disconnectClient("Invalid CreateLeaseSetMessage");
return; return;
} }
Destination dest = _runner.getConfig().getDestination();
_context.keyManager().registerKeys(message.getLeaseSet().getDestination(), message.getSigningPrivateKey(), message.getPrivateKey()); 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 { try {
_context.netDb().publish(message.getLeaseSet()); _context.netDb().publish(message.getLeaseSet());
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {

View File

@ -170,9 +170,12 @@ public class CreateRouterInfoJob extends JobImpl {
String sstype = ctx.getProperty(PROP_ROUTER_SIGTYPE); String sstype = ctx.getProperty(PROP_ROUTER_SIGTYPE);
if (sstype != null) { if (sstype != null) {
SigType ntype = SigType.parseSigType(sstype); SigType ntype = SigType.parseSigType(sstype);
if (ntype != null && ntype.isAvailable()) if (ntype != null)
cstype = ntype; cstype = ntype;
} }
// fallback?
if (cstype != SigType.DSA_SHA1 && !cstype.isAvailable())
cstype = SigType.DSA_SHA1;
return cstype; return cstype;
} }