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