From af42315e47f2efb738711486a85550be2d067ea7 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Fri, 15 Sep 2023 18:44:17 +0200 Subject: [PATCH] Implement TorOnionKey Generation --- network/tor/tor/build.gradle | 2 + .../src/main/java/bisq/tor/TorIdentity.java | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/network/tor/tor/build.gradle b/network/tor/tor/build.gradle index ef6118be4f..9fd5333237 100644 --- a/network/tor/tor/build.gradle +++ b/network/tor/tor/build.gradle @@ -22,6 +22,8 @@ dependencies { implementation 'network:common' implementation 'network:socks5-socket-channel' + implementation libs.bouncycastle + implementation libs.google.guava implementation libs.failsafe implementation libs.tukaani diff --git a/network/tor/tor/src/main/java/bisq/tor/TorIdentity.java b/network/tor/tor/src/main/java/bisq/tor/TorIdentity.java index 1e4d29af9c..1ce8758e75 100644 --- a/network/tor/tor/src/main/java/bisq/tor/TorIdentity.java +++ b/network/tor/tor/src/main/java/bisq/tor/TorIdentity.java @@ -19,10 +19,15 @@ import lombok.Getter; import lombok.ToString; +import org.bouncycastle.crypto.digests.SHA512Digest; +import org.bouncycastle.math.ec.rfc8032.Ed25519; + +import java.security.SecureRandom; @Getter @ToString public class TorIdentity { + @ToString.Exclude private final String privateKey; private final int port; @@ -31,4 +36,38 @@ public TorIdentity(String privateKey, int port) { this.privateKey = privateKey; this.port = port; } + + public static TorIdentity generate(int port) { + // Key Format definition: + // https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/control-spec.txt + + byte[] privateKey = new byte[32]; + Ed25519.generatePrivateKey(new SecureRandom(), privateKey); + + byte[] secretScalar = generateSecretScalar(privateKey); + String base64EncodedSecretScalar = java.util.Base64.getEncoder() + .encodeToString(secretScalar); + + String torOnionKey = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + + base64EncodedSecretScalar + "\n" + + "-----END OPENSSH PRIVATE KEY-----\n"; + + return new TorIdentity(torOnionKey, port); + } + + private static byte[] generateSecretScalar(byte[] privateKey) { + // https://www.rfc-editor.org/rfc/rfc8032#section-5.1 + + SHA512Digest sha512Digest = new SHA512Digest(); + sha512Digest.update(privateKey, 0, privateKey.length); + + byte[] secretScalar = new byte[64]; + sha512Digest.doFinal(secretScalar, 0); + + secretScalar[0] &= (byte) 248; + secretScalar[31] &= 127; + secretScalar[31] |= 64; + + return secretScalar; + } }