1 package org
.asamk
.signal
.manager
;
3 import org
.whispersystems
.libsignal
.InvalidKeyException
;
4 import org
.whispersystems
.libsignal
.ecc
.Curve
;
5 import org
.whispersystems
.libsignal
.ecc
.ECPublicKey
;
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
;
16 import static org
.whispersystems
.signalservice
.internal
.util
.Util
.isEmpty
;
18 public record DeviceLinkInfo(String deviceIdentifier
, ECPublicKey deviceKey
) {
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");
26 var query
= getQueryMap(rawQuery
);
27 var deviceIdentifier
= query
.get("uuid");
28 var publicKeyEncoded
= query
.get("pub_key");
30 if (isEmpty(deviceIdentifier
) || isEmpty(publicKeyEncoded
)) {
31 throw new RuntimeException("Invalid device link uri");
34 final byte[] publicKeyBytes
;
36 publicKeyBytes
= Base64
.getDecoder().decode(publicKeyEncoded
);
37 } catch (IllegalArgumentException e
) {
38 throw new RuntimeException("Invalid device link uri", e
);
40 var deviceKey
= Curve
.decodePoint(publicKeyBytes
, 0);
42 return new DeviceLinkInfo(deviceIdentifier
, deviceKey
);
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
);
57 public URI
createDeviceLinkUri() {
58 final var deviceKeyString
= Base64
.getEncoder().encodeToString(deviceKey
.serialize()).replace("=", "");
60 return new URI("sgnl://linkdevice?uuid="
61 + URLEncoder
.encode(deviceIdentifier
, StandardCharsets
.UTF_8
)
63 + URLEncoder
.encode(deviceKeyString
, StandardCharsets
.UTF_8
));
64 } catch (URISyntaxException e
) {
65 throw new AssertionError(e
);