forked from I2P_Developers/i2p.i2p
Data: More work on Encrypted LS2 (proposal 123)
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
package net.i2p.data;
|
package net.i2p.data;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -54,6 +55,38 @@ public class EncryptedLeaseSet extends LeaseSet2 {
|
|||||||
return _decryptedLS2 != null ? _decryptedLS2.getLease(index) : null;
|
return _decryptedLS2 != null ? _decryptedLS2.getLease(index) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to set the blinded key
|
||||||
|
*
|
||||||
|
* @param dest non-null, must be EdDSA_SHA512_Ed25519
|
||||||
|
* @throws IllegalStateException if already signed
|
||||||
|
* @throws IllegalArgumentException if not EdDSA
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDestination(Destination dest) {
|
||||||
|
super.setDestination(dest);
|
||||||
|
SigningPublicKey spk = dest.getSigningPublicKey();
|
||||||
|
if (spk.getType() != SigType.EdDSA_SHA512_Ed25519)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
// TODO generate blinded key
|
||||||
|
_signingKey = blind(spk, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SigningPublicKey blind(SigningPublicKey spk, SigningPrivateKey priv) {
|
||||||
|
// TODO generate blinded key
|
||||||
|
return spk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to return the blinded key so super.verifySignature() will work.
|
||||||
|
*
|
||||||
|
* @return SPK or null
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected SigningPublicKey getSigningPublicKey() {
|
||||||
|
return _signingKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This does NOT validate the signature
|
* This does NOT validate the signature
|
||||||
*
|
*
|
||||||
@ -88,6 +121,10 @@ public class EncryptedLeaseSet extends LeaseSet2 {
|
|||||||
// LS2 header
|
// LS2 header
|
||||||
writeHeader(out);
|
writeHeader(out);
|
||||||
// Encrypted LS2 part
|
// Encrypted LS2 part
|
||||||
|
if (_encryptedData == null) {
|
||||||
|
// TODO
|
||||||
|
encrypt(null);
|
||||||
|
}
|
||||||
DataHelper.writeLong(out, 2, _encryptedData.length);
|
DataHelper.writeLong(out, 2, _encryptedData.length);
|
||||||
out.write(_encryptedData);
|
out.write(_encryptedData);
|
||||||
}
|
}
|
||||||
@ -170,10 +207,13 @@ public class EncryptedLeaseSet extends LeaseSet2 {
|
|||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
int rv = _signingKey.length()
|
int rv = _signingKey.length()
|
||||||
+ 12
|
+ 12;
|
||||||
+ _encryptedData.length;
|
if (_encryptedData != null)
|
||||||
|
rv += _encryptedData.length;
|
||||||
|
else
|
||||||
|
rv += 99; // TODO
|
||||||
if (isOffline())
|
if (isOffline())
|
||||||
rv += 2 + _transientSigningPublicKey.length() + _offlineSignature.length();
|
rv += 6 + _transientSigningPublicKey.length() + _offlineSignature.length();
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +238,37 @@ public class EncryptedLeaseSet extends LeaseSet2 {
|
|||||||
return __calculatedHash;
|
return __calculatedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt / decrypt TODO
|
/**
|
||||||
|
* Throws IllegalStateException if not initialized.
|
||||||
|
*
|
||||||
|
* @param key ignored, to be fixed
|
||||||
|
* @throws IllegalStateException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void encrypt(SessionKey key) {
|
||||||
|
if (_encryptedData != null)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
// Middle layer - flag
|
||||||
|
baos.write(0);
|
||||||
|
// Inner layer - type - data covered by sig
|
||||||
|
baos.write(KEY_TYPE_LS2);
|
||||||
|
super.writeHeader(baos);
|
||||||
|
writeBody(baos);
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
throw new IllegalStateException("Error encrypting LS2", dfe);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new IllegalStateException("Error encrypting LS2", ioe);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO sign and add signature
|
||||||
|
// TODO encrypt - TESTING ONLY
|
||||||
|
_encryptedData = baos.toByteArray();
|
||||||
|
for (int i = 0; i < _encryptedData.length; i++) {
|
||||||
|
_encryptedData[i] ^= 0x5a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object object) {
|
public boolean equals(Object object) {
|
||||||
@ -234,4 +304,77 @@ public class EncryptedLeaseSet extends LeaseSet2 {
|
|||||||
buf.append("]");
|
buf.append("]");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
if (args.length != 1) {
|
||||||
|
System.out.println("Usage: LeaseSet2 privatekeyfile.dat");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
java.io.File f = new java.io.File(args[0]);
|
||||||
|
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-encls2.dat");
|
||||||
|
test(pkf, f2, false);
|
||||||
|
System.out.println("Offline test");
|
||||||
|
f2 = new java.io.File("offline-encls2.dat");
|
||||||
|
test(pkf, f2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void test(PrivateKeyFile pkf, java.io.File outfile, boolean offline) throws Exception {
|
||||||
|
net.i2p.util.RandomSource rand = net.i2p.util.RandomSource.getInstance();
|
||||||
|
long now = System.currentTimeMillis() + 5*60*1000;
|
||||||
|
EncryptedLeaseSet ls2 = new EncryptedLeaseSet();
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
Lease2 l2 = new Lease2();
|
||||||
|
now += 10000;
|
||||||
|
l2.setEndDate(new java.util.Date(now));
|
||||||
|
byte[] gw = new byte[32];
|
||||||
|
rand.nextBytes(gw);
|
||||||
|
l2.setGateway(new Hash(gw));
|
||||||
|
TunnelId id = new TunnelId(1 + rand.nextLong(TunnelId.MAX_ID_VALUE));
|
||||||
|
l2.setTunnelId(id);
|
||||||
|
ls2.addLease(l2);
|
||||||
|
}
|
||||||
|
java.util.Properties opts = new java.util.Properties();
|
||||||
|
opts.setProperty("foof", "bar");
|
||||||
|
ls2.setOptions(opts);
|
||||||
|
ls2.setDestination(pkf.getDestination());
|
||||||
|
SimpleDataStructure encKeys[] = net.i2p.crypto.KeyGenerator.getInstance().generatePKIKeys();
|
||||||
|
PublicKey pubKey = (PublicKey) encKeys[0];
|
||||||
|
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 += 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];
|
||||||
|
Signature sig = offlineSign(now, transientPub, spk);
|
||||||
|
ls2.setOfflineSignature(now, transientPub, sig);
|
||||||
|
ls2.sign(transientPriv);
|
||||||
|
} else {
|
||||||
|
ls2.sign(spk);
|
||||||
|
}
|
||||||
|
System.out.println("Created: " + ls2);
|
||||||
|
if (!ls2.verifySignature())
|
||||||
|
System.out.println("Verify FAILED");
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ls2.writeBytes(out);
|
||||||
|
java.io.OutputStream out2 = new java.io.FileOutputStream(outfile);
|
||||||
|
ls2.writeBytes(out2);
|
||||||
|
out2.close();
|
||||||
|
java.io.ByteArrayInputStream in = new java.io.ByteArrayInputStream(out.toByteArray());
|
||||||
|
System.out.println("Size calculated: " + (ls2.size() + ls2.getSignature().length()));
|
||||||
|
System.out.println("Size to read in: " + in.available());
|
||||||
|
EncryptedLeaseSet ls3 = new EncryptedLeaseSet();
|
||||||
|
ls3.readBytes(in);
|
||||||
|
System.out.println("Read back: " + ls3);
|
||||||
|
if (!ls3.verifySignature())
|
||||||
|
System.out.println("Verify FAILED");
|
||||||
|
}
|
||||||
|
****/
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ public class LeaseSet2 extends LeaseSet {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
byte[] data = baos.toByteArray();
|
byte[] data = baos.toByteArray();
|
||||||
return ctx.dsa().verifySignature(_offlineSignature, data, 0, data.length, _destination.getSigningPublicKey());
|
return ctx.dsa().verifySignature(_offlineSignature, data, 0, data.length, getSigningPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -288,6 +288,13 @@ public class LeaseSet2 extends LeaseSet {
|
|||||||
// LS2 header
|
// LS2 header
|
||||||
writeHeader(out);
|
writeHeader(out);
|
||||||
// LS2 part
|
// LS2 part
|
||||||
|
writeBody(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Without sig. This does NOT validate the signature
|
||||||
|
*/
|
||||||
|
protected void writeBody(OutputStream out) throws DataFormatException, IOException {
|
||||||
if (_options != null && !_options.isEmpty()) {
|
if (_options != null && !_options.isEmpty()) {
|
||||||
DataHelper.writeProperties(out, _options);
|
DataHelper.writeProperties(out, _options);
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user