Router: Add KeyManager support for multiple leaseset private keys

This commit is contained in:
zzz
2019-10-23 12:11:17 +00:00
parent 0f7ebf2f71
commit 8484a22fc4
2 changed files with 119 additions and 6 deletions

View File

@ -15,6 +15,7 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -110,15 +111,29 @@ public class KeyManager {
public synchronized SigningPublicKey getSigningPublicKey() { return _signingPublicKey; }
/**
* client
* Client with a single key
*
* @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());
if (_log.shouldInfo())
_log.info("Registering keys for destination " + dest.toBase32());
LeaseSetKeys keys = new LeaseSetKeys(dest, leaseRevocationPrivateKey, endpointDecryptionKey);
_leaseSetKeys.put(dest.calculateHash(), keys);
}
/**
* Client with multiple keys
*
* @param leaseRevocationPrivateKey unused, may be null
* @since 0.9.44
*/
public void registerKeys(Destination dest, SigningPrivateKey leaseRevocationPrivateKey, List<PrivateKey> endpointDecryptionKeys) {
if (_log.shouldInfo())
_log.info("Registering keys for destination " + dest.toBase32());
LeaseSetKeys keys = new LeaseSetKeys(dest, leaseRevocationPrivateKey, endpointDecryptionKeys);
_leaseSetKeys.put(dest.calculateHash(), keys);
}
/**
* Read/Write the router keys from/to disk
@ -129,7 +144,7 @@ public class KeyManager {
/** client */
public LeaseSetKeys unregisterKeys(Destination dest) {
if (_log.shouldLog(Log.INFO))
if (_log.shouldInfo())
_log.info("Unregistering keys for destination " + dest.calculateHash().toBase64());
return _leaseSetKeys.remove(dest.calculateHash());
}

View File

@ -8,6 +8,12 @@ package net.i2p.router;
*
*/
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import net.i2p.crypto.EncType;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKey;
import net.i2p.data.SigningPrivateKey;
@ -19,15 +25,66 @@ import net.i2p.data.SigningPrivateKey;
public class LeaseSetKeys {
private final SigningPrivateKey _revocationKey;
private final PrivateKey _decryptionKey;
private final PrivateKey _decryptionKeyEC;
/**
* Unmodifiable, ElGamal only
* @since 0.9.44
*/
public static final Set<EncType> SET_ELG = Collections.unmodifiableSet(EnumSet.of(EncType.ELGAMAL_2048));
private static final Set<EncType> SET_EC = Collections.unmodifiableSet(EnumSet.of(EncType.ECIES_X25519));
private static final Set<EncType> SET_BOTH = Collections.unmodifiableSet(EnumSet.of(EncType.ELGAMAL_2048, EncType.ECIES_X25519));
private static final Set<EncType> SET_NONE = Collections.unmodifiableSet(EnumSet.noneOf(EncType.class));
/**
* Client with a single key
*
* @param dest unused
* @param revocationKey unused, may be null
* @param decryptionKey non-null
*/
public LeaseSetKeys(Destination dest, SigningPrivateKey revocationKey, PrivateKey decryptionKey) {
_revocationKey = revocationKey;
_decryptionKey = decryptionKey;
_revocationKey = revocationKey;
EncType type = decryptionKey.getType();
if (type == EncType.ELGAMAL_2048) {
_decryptionKey = decryptionKey;
_decryptionKeyEC = null;
} else if (type == EncType.ECIES_X25519) {
_decryptionKey = null;
_decryptionKeyEC = decryptionKey;
} else {
throw new IllegalArgumentException("Unknown type " + type);
}
}
/**
* Client with multiple keys
*
* @param dest unused
* @param revocationKey unused, may be null
* @param decryptionKeys non-null
* @since 0.9.44
*/
public LeaseSetKeys(Destination dest, SigningPrivateKey revocationKey, List<PrivateKey> decryptionKeys) {
_revocationKey = revocationKey;
PrivateKey elg = null;
PrivateKey ec = null;
for (PrivateKey pk : decryptionKeys) {
EncType type = pk.getType();
if (type == EncType.ELGAMAL_2048) {
if (elg != null)
throw new IllegalArgumentException("Multiple keys same type");
elg = pk;
} else if (type == EncType.ECIES_X25519) {
if (ec != null)
throw new IllegalArgumentException("Multiple keys same type");
ec = pk;
} else {
throw new IllegalArgumentException("Unknown type " + type);
}
}
_decryptionKey = elg;
_decryptionKeyEC = ec;
}
/**
@ -43,7 +100,48 @@ public class LeaseSetKeys {
* know on what router the destination is connected and as such can't encrypt
* to that router's normal public key.
*
* @return ElGamal key or null if the LS does not support ElGamal
*/
public PrivateKey getDecryptionKey() { return _decryptionKey; }
/**
* Decryption key which can open up garlic messages encrypted to the
* LeaseSet's public key. This is used because the general public does not
* know on what router the destination is connected and as such can't encrypt
* to that router's normal public key.
*
* @return key of the specified type or null if the LS does not support that type
* @since 0.9.44
*/
public PrivateKey getDecryptionKey(EncType type) {
if (type == EncType.ELGAMAL_2048)
return _decryptionKey;
if (type == EncType.ECIES_X25519)
return _decryptionKeyEC;
return null;
}
/**
* Do we support this type of encryption?
*
* @since 0.9.44
*/
public boolean isSupported(EncType type) {
if (type == EncType.ELGAMAL_2048)
return _decryptionKey != null;
if (type == EncType.ECIES_X25519)
return _decryptionKeyEC != null;
return false;
}
/**
* What types of encryption are supported?
*
* @since 0.9.44
*/
public Set<EncType> getSupportedEncryption() {
if (_decryptionKey != null)
return (_decryptionKeyEC != null) ? SET_BOTH : SET_ELG;
return (_decryptionKeyEC != null) ? SET_EC : SET_NONE;
}
}