]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/DeviceLinkInfo.java
3e35acedcfd7927416f62b33446a30c709bfd5da
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / DeviceLinkInfo.java
1 package org.asamk.signal.manager;
2
3 import org.whispersystems.libsignal.InvalidKeyException;
4 import org.whispersystems.libsignal.ecc.Curve;
5 import org.whispersystems.libsignal.ecc.ECPublicKey;
6
7 import java.net.URI;
8 import java.net.URISyntaxException;
9 import java.net.URLDecoder;
10 import java.net.URLEncoder;
11 import java.nio.charset.StandardCharsets;
12 import java.util.Base64;
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
17
18 public record DeviceLinkInfo(String deviceIdentifier, ECPublicKey deviceKey) {
19
20 public static DeviceLinkInfo parseDeviceLinkUri(URI linkUri) throws InvalidKeyException {
21 final var rawQuery = linkUri.getRawQuery();
22 if (isEmpty(rawQuery)) {
23 throw new RuntimeException("Invalid device link uri");
24 }
25
26 var query = getQueryMap(rawQuery);
27 var deviceIdentifier = query.get("uuid");
28 var publicKeyEncoded = query.get("pub_key");
29
30 if (isEmpty(deviceIdentifier) || isEmpty(publicKeyEncoded)) {
31 throw new RuntimeException("Invalid device link uri");
32 }
33
34 final byte[] publicKeyBytes;
35 try {
36 publicKeyBytes = Base64.getDecoder().decode(publicKeyEncoded);
37 } catch (IllegalArgumentException e) {
38 throw new RuntimeException("Invalid device link uri", e);
39 }
40 var deviceKey = Curve.decodePoint(publicKeyBytes, 0);
41
42 return new DeviceLinkInfo(deviceIdentifier, deviceKey);
43 }
44
45 private static Map<String, String> getQueryMap(String query) {
46 var params = query.split("&");
47 var map = new HashMap<String, String>();
48 for (var param : params) {
49 final var paramParts = param.split("=");
50 var name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8);
51 var value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8);
52 map.put(name, value);
53 }
54 return map;
55 }
56
57 public URI createDeviceLinkUri() {
58 final var deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", "");
59 try {
60 return new URI("sgnl://linkdevice?uuid="
61 + URLEncoder.encode(deviceIdentifier, StandardCharsets.UTF_8)
62 + "&pub_key="
63 + URLEncoder.encode(deviceKeyString, StandardCharsets.UTF_8));
64 } catch (URISyntaxException e) {
65 throw new AssertionError(e);
66 }
67 }
68 }