1 package org
.asamk
.signal
.manager
.api
;
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
;
9 import java
.net
.URISyntaxException
;
10 import java
.net
.URLEncoder
;
11 import java
.nio
.charset
.StandardCharsets
;
12 import java
.util
.Base64
;
14 import static org
.whispersystems
.signalservice
.internal
.util
.Util
.isEmpty
;
16 public record DeviceLinkUrl(String deviceIdentifier
, ECPublicKey deviceKey
) {
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");
24 var query
= Utils
.getQueryMap(rawQuery
);
25 var deviceIdentifier
= query
.get("uuid");
26 var publicKeyEncoded
= query
.get("pub_key");
28 if (isEmpty(deviceIdentifier
) || isEmpty(publicKeyEncoded
)) {
29 throw new InvalidDeviceLinkException("Invalid device link uri");
32 final byte[] publicKeyBytes
;
34 publicKeyBytes
= Base64
.getDecoder().decode(publicKeyEncoded
);
35 } catch (IllegalArgumentException e
) {
36 throw new InvalidDeviceLinkException("Invalid device link uri", e
);
38 ECPublicKey deviceKey
;
40 deviceKey
= Curve
.decodePoint(publicKeyBytes
, 0);
41 } catch (InvalidKeyException e
) {
42 throw new InvalidDeviceLinkException("Invalid device link", e
);
45 return new DeviceLinkUrl(deviceIdentifier
, deviceKey
);
48 public URI
createDeviceLinkUri() {
49 final var deviceKeyString
= Base64
.getEncoder().encodeToString(deviceKey
.serialize()).replace("=", "");
51 return new URI("sgnl://linkdevice?uuid="
52 + URLEncoder
.encode(deviceIdentifier
, StandardCharsets
.UTF_8
)
54 + URLEncoder
.encode(deviceKeyString
, StandardCharsets
.UTF_8
));
55 } catch (URISyntaxException e
) {
56 throw new AssertionError(e
);