mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 21:59:54 +01:00
Implement Tor rendezvous crypto.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
interface TorRendezvousCrypto {
|
||||||
|
|
||||||
|
String getOnionAddress(byte[] seed);
|
||||||
|
|
||||||
|
String getPrivateKeyBlob(byte[] seed);
|
||||||
|
}
|
||||||
@@ -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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user