Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect filtered Tor controller commands #2205

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package bisq.tor.controller;

public class TorCommandFilteredException extends RuntimeException {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package bisq.tor.controller;

import bisq.security.keys.TorKeyPair;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class WhonixTorController implements AutoCloseable {
private final Socket controlSocket;
private final BufferedReader bufferedReader;
private final OutputStream outputStream;

public WhonixTorController() throws IOException {
controlSocket = new Socket("127.0.0.1", 9051);

InputStream inputStream = controlSocket.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.US_ASCII));

outputStream = controlSocket.getOutputStream();
}

@Override
public void close() throws IOException {
controlSocket.close();
}

public void addOnion(TorKeyPair torKeyPair, int onionPort, int localPort) throws IOException {
String base64SecretScalar = torKeyPair.getBase64SecretScalar();
String command = "ADD_ONION " + "ED25519-V3:" + base64SecretScalar + " Port=" + onionPort + "," + localPort + "\r\n";
byte[] commandBytes = command.getBytes(StandardCharsets.US_ASCII);

outputStream.write(commandBytes);
outputStream.flush();

String reply = bufferedReader.readLine();
if (reply.equals("510 Command filtered")) {
throw new TorCommandFilteredException();
}
}
}
13 changes: 8 additions & 5 deletions security/src/main/java/bisq/security/keys/TorKeyPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,19 @@ public static TorKeyPair fromProto(bisq.security.protobuf.TorKeyPair proto) {
proto.getOnionAddress());
}

public String getBase64SecretScalar() {
// Key Format definition:
// https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/control-spec.txt
byte[] secretScalar = generateSecretScalar(privateKey);
return java.util.Base64.getEncoder().encodeToString(secretScalar);
}

/**
* The format how the private key is stored in the tor directory
*/
public String getPrivateKeyInOpenSshFormat() {
// Key Format definition:
// https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/control-spec.txt
byte[] secretScalar = generateSecretScalar(privateKey);
String encoded = java.util.Base64.getEncoder().encodeToString(secretScalar);
return "-----BEGIN OPENSSH PRIVATE KEY-----\n" +
encoded + "\n" +
getBase64SecretScalar() + "\n" +
"-----END OPENSSH PRIVATE KEY-----\n";
}

Expand Down
Loading