]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/internal/DeviceLinkInfo.java
Refactor manager lib package structure
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / internal / DeviceLinkInfo.java
diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/DeviceLinkInfo.java b/lib/src/main/java/org/asamk/signal/manager/internal/DeviceLinkInfo.java
new file mode 100644 (file)
index 0000000..50f0402
--- /dev/null
@@ -0,0 +1,60 @@
+package org.asamk.signal.manager.internal;
+
+import org.asamk.signal.manager.api.InvalidDeviceLinkException;
+import org.asamk.signal.manager.util.Utils;
+import org.signal.libsignal.protocol.InvalidKeyException;
+import org.signal.libsignal.protocol.ecc.Curve;
+import org.signal.libsignal.protocol.ecc.ECPublicKey;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
+
+public record DeviceLinkInfo(String deviceIdentifier, ECPublicKey deviceKey) {
+
+    public static DeviceLinkInfo parseDeviceLinkUri(URI linkUri) throws InvalidDeviceLinkException {
+        final var rawQuery = linkUri.getRawQuery();
+        if (isEmpty(rawQuery)) {
+            throw new RuntimeException("Invalid device link uri");
+        }
+
+        var query = Utils.getQueryMap(rawQuery);
+        var deviceIdentifier = query.get("uuid");
+        var publicKeyEncoded = query.get("pub_key");
+
+        if (isEmpty(deviceIdentifier) || isEmpty(publicKeyEncoded)) {
+            throw new InvalidDeviceLinkException("Invalid device link uri");
+        }
+
+        final byte[] publicKeyBytes;
+        try {
+            publicKeyBytes = Base64.getDecoder().decode(publicKeyEncoded);
+        } catch (IllegalArgumentException e) {
+            throw new InvalidDeviceLinkException("Invalid device link uri", e);
+        }
+        ECPublicKey deviceKey;
+        try {
+            deviceKey = Curve.decodePoint(publicKeyBytes, 0);
+        } catch (InvalidKeyException e) {
+            throw new InvalidDeviceLinkException("Invalid device link", e);
+        }
+
+        return new DeviceLinkInfo(deviceIdentifier, deviceKey);
+    }
+
+    public URI createDeviceLinkUri() {
+        final var deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", "");
+        try {
+            return new URI("sgnl://linkdevice?uuid="
+                    + URLEncoder.encode(deviceIdentifier, StandardCharsets.UTF_8)
+                    + "&pub_key="
+                    + URLEncoder.encode(deviceKeyString, StandardCharsets.UTF_8));
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e);
+        }
+    }
+}