Implement Tor rendezvous crypto.

This commit is contained in:
akwizgran
2019-06-05 15:46:22 +01:00
parent 64ae99bbce
commit 1ec3fa3ade
8 changed files with 119 additions and 10 deletions

View File

@@ -41,11 +41,12 @@ class AndroidTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff, BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency, PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) { int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory, super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime, backoff, torRendezvousCrypto, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE)); appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext; this.appContext = appContext;
PowerManager pm = (PowerManager) PowerManager pm = (PowerManager)

View File

@@ -106,10 +106,12 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler, AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory, appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME); backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -105,6 +105,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Clock clock; private final Clock clock;
private final BatteryManager batteryManager; private final BatteryManager batteryManager;
private final Backoff backoff; private final Backoff backoff;
private final TorRendezvousCrypto torRendezvousCrypto;
private final PluginCallback callback; private final PluginCallback callback;
private final String architecture; private final String architecture;
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
@@ -131,6 +132,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff, BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency, PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) { int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
@@ -142,6 +144,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
this.circumventionProvider = circumventionProvider; this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager; this.batteryManager = batteryManager;
this.backoff = backoff; this.backoff = backoff;
this.torRendezvousCrypto = torRendezvousCrypto;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
@@ -609,13 +612,58 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public boolean supportsRendezvous() { public boolean supportsRendezvous() {
return false; return true;
} }
@Override @Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
boolean alice, ConnectionHandler incoming) { boolean alice, ConnectionHandler incoming) {
throw new UnsupportedOperationException(); byte[] aliceSeed = k.getKeyMaterial(32);
byte[] bobSeed = k.getKeyMaterial(32);
byte[] localSeed = alice ? aliceSeed : bobSeed;
byte[] remoteSeed = alice ? bobSeed : aliceSeed;
String blob = torRendezvousCrypto.getPrivateKeyBlob(localSeed);
String localOnion = torRendezvousCrypto.getOnionAddress(localSeed);
String remoteOnion = torRendezvousCrypto.getOnionAddress(remoteSeed);
TransportProperties remote = new TransportProperties();
remote.put(PROP_ONION_V3, remoteOnion);
try {
ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", 0));
int port = ss.getLocalPort();
ioExecutor.execute(() -> {
try {
//noinspection InfiniteLoopStatement
while (true) {
Socket s = ss.accept();
incoming.handleConnection(
new TorTransportConnection(this, s));
}
} catch (IOException e) {
// This is expected when the socket is closed
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
}
});
Map<Integer, String> portLines =
singletonMap(80, "127.0.0.1:" + port);
controlConnection.addOnion(blob, portLines);
return new RendezvousEndpoint() {
@Override
public TransportProperties getRemoteTransportProperties() {
return remote;
}
@Override
public void close() throws IOException {
controlConnection.delOnion(localOnion);
tryToClose(ss);
}
};
} catch (IOException e) {
logException(LOG, WARNING, e);
return null;
}
} }
@Override @Override

View File

@@ -0,0 +1,8 @@
package org.briarproject.bramble.plugin.tor;
interface TorRendezvousCrypto {
String getOnionAddress(byte[] seed);
String getPrivateKeyBlob(byte[] seed);
}

View File

@@ -0,0 +1,46 @@
package org.briarproject.bramble.plugin.tor;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.briarproject.bramble.util.Base32;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.SHA3Digest;
import org.spongycastle.util.encoders.Base64;
import java.nio.charset.Charset;
import static java.lang.System.arraycopy;
public class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
private static final EdDSANamedCurveSpec CURVE_SPEC =
EdDSANamedCurveTable.getByName("Ed25519");
@Override
public String getOnionAddress(byte[] seed) {
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
byte[] publicKey = spec.getA().toByteArray();
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update((byte) 3);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + 3];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, 2);
address[address.length - 1] = 3;
return Base32.encode(address).toLowerCase();
}
@Override
public String getPrivateKeyBlob(byte[] seed) {
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
byte[] hash = spec.getH();
byte[] base64 = Base64.encode(hash);
return "ED25519-V3:" + new String(base64, Charset.forName("US-ASCII"));
}
}

View File

@@ -25,12 +25,13 @@ abstract class JavaTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff, BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency, PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) { int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory, super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime, backoff, torRendezvousCrypto, callback, architecture,
torDirectory); maxLatency, maxIdleTime, torDirectory);
} }
@Override @Override

View File

@@ -25,12 +25,13 @@ class UnixTorPlugin extends JavaTorPlugin {
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff, BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency, PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) { int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory, super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime, backoff, torRendezvousCrypto, callback, architecture,
torDirectory); maxLatency, maxIdleTime, torDirectory);
} }
@Override @Override

View File

@@ -96,10 +96,12 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, networkManager, UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, networkManager,
locationUtils, torSocketFactory, clock, resourceProvider, locationUtils, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, callback, circumventionProvider, batteryManager, backoff,
architecture, MAX_LATENCY, MAX_IDLE_TIME, torDirectory); torRendezvousCrypto, callback, architecture, MAX_LATENCY,
MAX_IDLE_TIME, torDirectory);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }