--- /dev/null
+package org.asamk.signal.manager;
+
+import org.whispersystems.libsignal.InvalidKeyException;
+import org.whispersystems.libsignal.ecc.Curve;
+import org.whispersystems.libsignal.ecc.ECPublicKey;
+
+import java.net.URI;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
+
+public class DeviceLinkInfo {
+
+ final String deviceIdentifier;
+ final ECPublicKey deviceKey;
+
+ public static DeviceLinkInfo parseDeviceLinkUri(URI linkUri) throws InvalidKeyException {
+ final String rawQuery = linkUri.getRawQuery();
+ if (isEmpty(rawQuery)) {
+ throw new RuntimeException("Invalid device link uri");
+ }
+
+ Map<String, String> query = getQueryMap(rawQuery);
+ String deviceIdentifier = query.get("uuid");
+ String publicKeyEncoded = query.get("pub_key");
+
+ if (isEmpty(deviceIdentifier) || isEmpty(publicKeyEncoded)) {
+ throw new RuntimeException("Invalid device link uri");
+ }
+
+ final byte[] publicKeyBytes;
+ try {
+ publicKeyBytes = Base64.getDecoder().decode(publicKeyEncoded);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Invalid device link uri", e);
+ }
+ ECPublicKey deviceKey = Curve.decodePoint(publicKeyBytes, 0);
+
+ return new DeviceLinkInfo(deviceIdentifier, deviceKey);
+ }
+
+ private static Map<String, String> getQueryMap(String query) {
+ String[] params = query.split("&");
+ Map<String, String> map = new HashMap<>();
+ for (String param : params) {
+ final String[] paramParts = param.split("=");
+ String name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8);
+ String value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8);
+ map.put(name, value);
+ }
+ return map;
+ }
+
+ public DeviceLinkInfo(final String deviceIdentifier, final ECPublicKey deviceKey) {
+ this.deviceIdentifier = deviceIdentifier;
+ this.deviceKey = deviceKey;
+ }
+
+ public String createDeviceLinkUri() {
+ final String deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", "");
+ return "tsdevice:/?uuid="
+ + URLEncoder.encode(deviceIdentifier, StandardCharsets.UTF_8)
+ + "&pub_key="
+ + URLEncoder.encode(deviceKeyString, StandardCharsets.UTF_8);
+ }
+}