Commit 1ec3fa3a authored by akwizgran's avatar akwizgran

Implement Tor rendezvous crypto.

parent 64ae99bb
......@@ -41,11 +41,12 @@ class AndroidTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
backoff, torRendezvousCrypto, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext;
PowerManager pm = (PowerManager)
......
......@@ -106,10 +106,12 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}
......
......@@ -105,6 +105,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Clock clock;
private final BatteryManager batteryManager;
private final Backoff backoff;
private final TorRendezvousCrypto torRendezvousCrypto;
private final PluginCallback callback;
private final String architecture;
private final CircumventionProvider circumventionProvider;
......@@ -131,6 +132,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor;
......@@ -142,6 +144,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.backoff = backoff;
this.torRendezvousCrypto = torRendezvousCrypto;
this.callback = callback;
this.architecture = architecture;
this.maxLatency = maxLatency;
......@@ -609,13 +612,58 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public boolean supportsRendezvous() {
return false;
return true;
}
@Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
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
......
package org.briarproject.bramble.plugin.tor;
interface TorRendezvousCrypto {
String getOnionAddress(byte[] seed);
String getPrivateKeyBlob(byte[] seed);
}
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"));
}
}
......@@ -25,12 +25,13 @@ abstract class JavaTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
torDirectory);
backoff, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory);
}
@Override
......
......@@ -25,12 +25,13 @@ class UnixTorPlugin extends JavaTorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
torDirectory);
backoff, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory);
}
@Override
......
......@@ -96,10 +96,12 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, networkManager,
locationUtils, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, callback,
architecture, MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, MAX_LATENCY,
MAX_IDLE_TIME, torDirectory);
eventBus.addListener(plugin);
return plugin;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment