forked from I2P_Developers/i2p.i2p
Data: Add support for LS2 multiple encryption keys (proposal 123)
This commit is contained in:
@ -4,6 +4,10 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
@ -35,9 +39,12 @@ public class LeaseSet2 extends LeaseSet {
|
||||
protected Properties _options;
|
||||
// only used for unknown types; else use _encryptionKey.getType()
|
||||
private int _encType;
|
||||
// only used if more than one key, otherwise null
|
||||
private List<PublicKey> _encryptionKeys;
|
||||
|
||||
private static final int FLAG_OFFLINE_KEYS = 1;
|
||||
private static final int FLAG_UNPUBLISHED = 2;
|
||||
private static final int MAX_KEYS = 8;
|
||||
|
||||
public LeaseSet2() {
|
||||
super();
|
||||
@ -59,6 +66,36 @@ public class LeaseSet2 extends LeaseSet {
|
||||
return _options.getProperty(opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an encryption key.
|
||||
*/
|
||||
public void addEncryptionKey(PublicKey key) {
|
||||
if (_encryptionKey == null) {
|
||||
setEncryptionKey(key);
|
||||
} else {
|
||||
if (_encryptionKeys == null) {
|
||||
_encryptionKeys = new ArrayList<PublicKey>(4);
|
||||
_encryptionKeys.add(_encryptionKey);
|
||||
} else {
|
||||
if (_encryptionKeys.size() >= MAX_KEYS)
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
_encryptionKeys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns all the keys. getEncryptionKey() returns the first one.
|
||||
* @return not a copy, do not modify, null if none
|
||||
*/
|
||||
public List<PublicKey> getEncryptionKeys() {
|
||||
if (_encryptionKeys != null)
|
||||
return _encryptionKeys;
|
||||
if (_encryptionKey != null)
|
||||
return Collections.singletonList(_encryptionKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a set of options or statistics that the router can expose.
|
||||
* Makes a copy.
|
||||
@ -193,18 +230,27 @@ public class LeaseSet2 extends LeaseSet {
|
||||
readHeader(in);
|
||||
// LS2 part
|
||||
_options = DataHelper.readProperties(in);
|
||||
_encType = (int) DataHelper.readLong(in, 2);
|
||||
int encLen = (int) DataHelper.readLong(in, 2);
|
||||
// TODO
|
||||
if (_encType == 0) {
|
||||
_encryptionKey = PublicKey.create(in);
|
||||
} else {
|
||||
EncType type = EncType.getByCode(_encType);
|
||||
// type will be null if unknown
|
||||
byte[] encKey = new byte[encLen];
|
||||
DataHelper.read(in, encKey);
|
||||
// this will throw IAE if type is non-null and length is wrong
|
||||
_encryptionKey = new PublicKey(type, encKey);
|
||||
int numKeys = in.read();
|
||||
if (numKeys <= 0 || numKeys > MAX_KEYS)
|
||||
throw new DataFormatException("Bad key count: " + numKeys);
|
||||
if (numKeys > 1)
|
||||
_encryptionKeys = new ArrayList<PublicKey>(numKeys);
|
||||
for (int i = 0; i < numKeys; i++) {
|
||||
_encType = (int) DataHelper.readLong(in, 2);
|
||||
int encLen = (int) DataHelper.readLong(in, 2);
|
||||
// TODO
|
||||
if (_encType == 0) {
|
||||
_encryptionKey = PublicKey.create(in);
|
||||
} else {
|
||||
EncType type = EncType.getByCode(_encType);
|
||||
// type will be null if unknown
|
||||
byte[] encKey = new byte[encLen];
|
||||
DataHelper.read(in, encKey);
|
||||
// this will throw IAE if type is non-null and length is wrong
|
||||
_encryptionKey = new PublicKey(type, encKey);
|
||||
}
|
||||
if (numKeys > 1)
|
||||
_encryptionKeys.add(_encryptionKey);
|
||||
}
|
||||
int numLeases = in.read();
|
||||
if (numLeases > MAX_LEASES)
|
||||
@ -246,14 +292,18 @@ public class LeaseSet2 extends LeaseSet {
|
||||
} else {
|
||||
DataHelper.writeLong(out, 2, 0);
|
||||
}
|
||||
EncType type = _encryptionKey.getType();
|
||||
if (type != null) {
|
||||
DataHelper.writeLong(out, 2, type.getCode());
|
||||
} else {
|
||||
DataHelper.writeLong(out, 2, _encType);
|
||||
List<PublicKey> keys = getEncryptionKeys();
|
||||
out.write((byte) keys.size());
|
||||
for (PublicKey key : keys) {
|
||||
EncType type = key.getType();
|
||||
if (type != null) {
|
||||
DataHelper.writeLong(out, 2, type.getCode());
|
||||
} else {
|
||||
DataHelper.writeLong(out, 2, _encType);
|
||||
}
|
||||
DataHelper.writeLong(out, 2, key.length());
|
||||
key.writeBytes(out);
|
||||
}
|
||||
DataHelper.writeLong(out, 2, _encryptionKey.length());
|
||||
_encryptionKey.writeBytes(out);
|
||||
out.write((byte) _leases.size());
|
||||
for (Lease lease : _leases) {
|
||||
lease.writeBytes(out);
|
||||
@ -433,13 +483,25 @@ public class LeaseSet2 extends LeaseSet {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append("[LeaseSet2: ");
|
||||
buf.append("\n\tDestination: ").append(_destination);
|
||||
buf.append("\n\tEncryptionKey: ").append(_encryptionKey);
|
||||
List<PublicKey> keys = getEncryptionKeys();
|
||||
int sz = keys.size();
|
||||
buf.append("\n\tEncryption Keys: ").append(sz);
|
||||
for (int i = 0; i < sz; i++) {
|
||||
buf.append("\n\tEncryptionKey ").append(i).append(": ").append(keys.get(i));
|
||||
}
|
||||
if (isOffline()) {
|
||||
buf.append("\n\tTransient Key: ").append(_transientSigningPublicKey);
|
||||
buf.append("\n\tTransient Expires: ").append(new java.util.Date(_transientExpires));
|
||||
buf.append("\n\tOffline Signature: ").append(_offlineSignature);
|
||||
}
|
||||
buf.append("\n\tOptions: ").append((_options != null) ? _options.size() : 0);
|
||||
if (_options != null && !_options.isEmpty()) {
|
||||
for (Map.Entry<Object, Object> e : _options.entrySet()) {
|
||||
String key = (String) e.getKey();
|
||||
String val = (String) e.getValue();
|
||||
buf.append("\n\t\t[").append(key).append("] = [").append(val).append("]");
|
||||
}
|
||||
}
|
||||
buf.append("\n\tSignature: ").append(_signature);
|
||||
buf.append("\n\tPublished: ").append(new java.util.Date(_published));
|
||||
buf.append("\n\tExpires: ").append(new java.util.Date(_expires));
|
||||
@ -465,10 +527,10 @@ public class LeaseSet2 extends LeaseSet {
|
||||
PrivateKeyFile pkf = new PrivateKeyFile(f);
|
||||
pkf.createIfAbsent(SigType.EdDSA_SHA512_Ed25519);
|
||||
System.out.println("Online test");
|
||||
java.io.File f2 = new java.io.File("online-leaseset.dat");
|
||||
java.io.File f2 = new java.io.File("online-ls2.dat");
|
||||
test(pkf, f2, false);
|
||||
System.out.println("Offline test");
|
||||
f2 = new java.io.File("offline-leaseset.dat");
|
||||
f2 = new java.io.File("offline-ls2.dat");
|
||||
test(pkf, f2, true);
|
||||
}
|
||||
|
||||
@ -494,10 +556,13 @@ public class LeaseSet2 extends LeaseSet {
|
||||
ls2.setDestination(pkf.getDestination());
|
||||
SimpleDataStructure encKeys[] = net.i2p.crypto.KeyGenerator.getInstance().generatePKIKeys();
|
||||
PublicKey pubKey = (PublicKey) encKeys[0];
|
||||
ls2.setEncryptionKey(pubKey);
|
||||
ls2.addEncryptionKey(pubKey);
|
||||
net.i2p.crypto.KeyPair encKeys2 = net.i2p.crypto.KeyGenerator.getInstance().generatePKIKeys(net.i2p.crypto.EncType.ECIES_X25519);
|
||||
pubKey = encKeys2.getPublic();
|
||||
ls2.addEncryptionKey(pubKey);
|
||||
SigningPrivateKey spk = pkf.getSigningPrivKey();
|
||||
if (offline) {
|
||||
now += 100000;
|
||||
now += 365*24*60*60*1000L;
|
||||
SimpleDataStructure transKeys[] = net.i2p.crypto.KeyGenerator.getInstance().generateSigningKeys(SigType.EdDSA_SHA512_Ed25519);
|
||||
SigningPublicKey transientPub = (SigningPublicKey) transKeys[0];
|
||||
SigningPrivateKey transientPriv = (SigningPrivateKey) transKeys[1];
|
||||
|
Reference in New Issue
Block a user