i2ptunnel: New CLI BlindingInfo test

I2CP: Fix BlindingInfo serialization
This commit is contained in:
zzz
2019-09-17 17:30:42 +00:00
parent 0d325d5a28
commit f9a2193e2f
2 changed files with 118 additions and 2 deletions

View File

@ -66,10 +66,14 @@ import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException; import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSimpleClient; import net.i2p.client.I2PSimpleClient;
import net.i2p.client.naming.NamingService; import net.i2p.client.naming.NamingService;
import net.i2p.crypto.Blinding;
import net.i2p.crypto.EncType;
import net.i2p.data.Base64; import net.i2p.data.Base64;
import net.i2p.data.BlindData;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.PrivateKey;
import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel; import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel; import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
import net.i2p.i2ptunnel.streamr.StreamrConsumer; import net.i2p.i2ptunnel.streamr.StreamrConsumer;
@ -448,6 +452,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
runOwnDest(args, l); runOwnDest(args, l);
} else if (cmdname.equals("auth")) { } else if (cmdname.equals("auth")) {
runAuth(args, l); runAuth(args, l);
} else if (cmdname.equals("blinding")) {
runBlinding(args, l);
} else { } else {
l.log("Unknown command [" + cmdname + "]"); l.log("Unknown command [" + cmdname + "]");
} }
@ -464,6 +470,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
l.log("Command list:\n" + l.log("Command list:\n" +
// alphabetical please... // alphabetical please...
" auth <username> <password>\n" + " auth <username> <password>\n" +
" blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p\n" +
" client <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]\n" + " client <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]\n" +
" clientoptions [-acx] [key=value ]*\n" + " clientoptions [-acx] [key=value ]*\n" +
" close [forced|destroy] <jobnumber>|all\n" + " close [forced|destroy] <jobnumber>|all\n" +
@ -1694,6 +1701,110 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
} }
} }
/**
* Send a BlindingInfo message, just for testing
* @since 0.9.43
*/
private void runBlinding(String[] argv, Logging l) {
// blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH; -p for PSK; expires in days
Getopt g = new Getopt("blinding", argv, "dpk:s:e:");
boolean error = false;
boolean dh = false;
boolean psk = false;
String key = null;
String pw = null;
long expires = 0;
int c;
while ((c = g.getopt()) != -1) {
switch (c) {
case 'd':
dh = true;
break;
case 'p':
psk = true;
break;
case 'k':
key = g.getOptarg();
break;
case 's':
pw = g.getOptarg();
break;
case 'e':
expires = Long.parseLong(g.getOptarg());
break;
case '?':
case ':':
default:
error = true;
}
}
int remaining = argv.length - g.getOptind();
if (error || remaining != 1 || (dh && psk) || ((dh || psk) && key == null)) {
System.out.println("Usage: blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH; -p for PSK; expires in days");
return;
}
String name = argv[g.getOptind()];
BlindData bd;
try {
int auth = BlindData.AUTH_NONE;
PrivateKey pk = null;
if (key != null) {
byte[] data = Base64.decode(key);
if (data == null || data.length != 32) {
System.out.println("Invalid private key");
return;
}
pk = new PrivateKey(EncType.ECIES_X25519, data);
auth = dh ? BlindData.AUTH_DH : BlindData.AUTH_PSK;
}
// basic check and decode
bd = Blinding.decode(_context, name);
// fill in key and secret
bd = new BlindData(_context, bd.getUnblindedPubKey(), bd.getBlindedSigType(), pw, auth, pk);
long now = _context.clock().now();
bd.setDate(now);
if (expires > 0) {
expires *= 24*60*60*1000L;
expires += now;
bd.setExpiration(expires);
}
} catch (IllegalArgumentException iae) {
System.out.println("Invalid b32 " + name + " - " + iae);
return;
}
boolean ssl = Boolean.parseBoolean(_clientOptions.getProperty("i2cp.SSL"));
String user = _clientOptions.getProperty("i2cp.username");
String ipw = _clientOptions.getProperty("i2cp.password");
I2PClient client = new I2PSimpleClient();
Properties opts = new Properties();
opts.put(I2PClient.PROP_TCP_HOST, host);
opts.put(I2PClient.PROP_TCP_PORT, port);
opts.put("i2cp.SSL", Boolean.toString(ssl));
if (user != null)
opts.put("i2cp.username", user);
if (ipw != null)
opts.put("i2cp.password", ipw);
I2PSession session = null;
try {
session = client.createSession(null, opts);
session.connect();
System.out.println("Sending: " + bd);
session.sendBlindingInfo(bd);
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
} catch (I2PSessionException ise) {
System.out.println("Send blinding info failed: " + ise);
} finally {
if (session != null) {
try { session.destroySession(); } catch (I2PSessionException ise) {}
}
}
}
/** /**
* Helper method to actually close the given task number (optionally forcing * Helper method to actually close the given task number (optionally forcing
* closure) * closure)

View File

@ -337,6 +337,8 @@ public class BlindingInfoMessage extends I2CPMessageImpl {
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
byte flags = (byte) _authType; byte flags = (byte) _authType;
if (_privkey != null)
flags |= FLAG_AUTH;
if (_secret != null) if (_secret != null)
flags |= FLAG_SECRET; flags |= FLAG_SECRET;
os.write(flags); os.write(flags);
@ -349,10 +351,13 @@ public class BlindingInfoMessage extends I2CPMessageImpl {
DataHelper.writeString(os, _host); DataHelper.writeString(os, _host);
} else if (_endpointType == TYPE_DEST) { } else if (_endpointType == TYPE_DEST) {
_dest.writeBytes(os); _dest.writeBytes(os);
} else { } else { // TYPE_KEY
DataHelper.writeLong(os, 2, _pubkey.getType().getCode());
os.write(_pubkey.getData());
}
if (_privkey != null) {
DataHelper.writeLong(os, 2, _privkey.getType().getCode()); DataHelper.writeLong(os, 2, _privkey.getType().getCode());
os.write(_privkey.getData()); os.write(_privkey.getData());
DataHelper.writeString(os, _host);
} }
if (_secret != null) if (_secret != null)
DataHelper.writeString(os, _secret); DataHelper.writeString(os, _secret);