forked from I2P_Developers/i2p.i2p
Router: Add KeyManager support for multiple leaseset private keys
This commit is contained in:
@ -15,6 +15,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -110,15 +111,29 @@ public class KeyManager {
|
|||||||
public synchronized SigningPublicKey getSigningPublicKey() { return _signingPublicKey; }
|
public synchronized SigningPublicKey getSigningPublicKey() { return _signingPublicKey; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* client
|
* Client with a single key
|
||||||
|
*
|
||||||
* @param leaseRevocationPrivateKey unused, may be null
|
* @param leaseRevocationPrivateKey unused, may be null
|
||||||
*/
|
*/
|
||||||
public void registerKeys(Destination dest, SigningPrivateKey leaseRevocationPrivateKey, PrivateKey endpointDecryptionKey) {
|
public void registerKeys(Destination dest, SigningPrivateKey leaseRevocationPrivateKey, PrivateKey endpointDecryptionKey) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldInfo())
|
||||||
_log.info("Registering keys for destination " + dest.calculateHash().toBase64());
|
_log.info("Registering keys for destination " + dest.toBase32());
|
||||||
LeaseSetKeys keys = new LeaseSetKeys(dest, leaseRevocationPrivateKey, endpointDecryptionKey);
|
LeaseSetKeys keys = new LeaseSetKeys(dest, leaseRevocationPrivateKey, endpointDecryptionKey);
|
||||||
_leaseSetKeys.put(dest.calculateHash(), keys);
|
_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
|
* Read/Write the router keys from/to disk
|
||||||
@ -129,7 +144,7 @@ public class KeyManager {
|
|||||||
|
|
||||||
/** client */
|
/** client */
|
||||||
public LeaseSetKeys unregisterKeys(Destination dest) {
|
public LeaseSetKeys unregisterKeys(Destination dest) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldInfo())
|
||||||
_log.info("Unregistering keys for destination " + dest.calculateHash().toBase64());
|
_log.info("Unregistering keys for destination " + dest.calculateHash().toBase64());
|
||||||
return _leaseSetKeys.remove(dest.calculateHash());
|
return _leaseSetKeys.remove(dest.calculateHash());
|
||||||
}
|
}
|
||||||
|
@ -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.Destination;
|
||||||
import net.i2p.data.PrivateKey;
|
import net.i2p.data.PrivateKey;
|
||||||
import net.i2p.data.SigningPrivateKey;
|
import net.i2p.data.SigningPrivateKey;
|
||||||
@ -19,15 +25,66 @@ import net.i2p.data.SigningPrivateKey;
|
|||||||
public class LeaseSetKeys {
|
public class LeaseSetKeys {
|
||||||
private final SigningPrivateKey _revocationKey;
|
private final SigningPrivateKey _revocationKey;
|
||||||
private final PrivateKey _decryptionKey;
|
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 dest unused
|
||||||
* @param revocationKey unused, may be null
|
* @param revocationKey unused, may be null
|
||||||
* @param decryptionKey non-null
|
* @param decryptionKey non-null
|
||||||
*/
|
*/
|
||||||
public LeaseSetKeys(Destination dest, SigningPrivateKey revocationKey, PrivateKey decryptionKey) {
|
public LeaseSetKeys(Destination dest, SigningPrivateKey revocationKey, PrivateKey decryptionKey) {
|
||||||
_revocationKey = revocationKey;
|
_revocationKey = revocationKey;
|
||||||
_decryptionKey = decryptionKey;
|
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
|
* know on what router the destination is connected and as such can't encrypt
|
||||||
* to that router's normal public key.
|
* to that router's normal public key.
|
||||||
*
|
*
|
||||||
|
* @return ElGamal key or null if the LS does not support ElGamal
|
||||||
*/
|
*/
|
||||||
public PrivateKey getDecryptionKey() { return _decryptionKey; }
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user