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
.ECPublicKey
;
8 import java
.net
.URISyntaxException
;
9 import java
.net
.URLEncoder
;
10 import java
.nio
.charset
.StandardCharsets
;
11 import java
.util
.Base64
;
13 import static org
.whispersystems
.signalservice
.internal
.util
.Util
.isEmpty
;
15 public record DeviceLinkUrl(String deviceIdentifier
, ECPublicKey deviceKey
) {
17 public static DeviceLinkUrl
parseDeviceLinkUri(URI linkUri
) throws InvalidDeviceLinkException
{
18 final var rawQuery
= linkUri
.getRawQuery();
19 if (isEmpty(rawQuery
)) {
20 throw new RuntimeException("Invalid device link uri");
23 var query
= Utils
.getQueryMap(rawQuery
);
24 var deviceIdentifier
= query
.get("uuid");
25 var publicKeyEncoded
= query
.get("pub_key");
27 if (isEmpty(deviceIdentifier
) || isEmpty(publicKeyEncoded
)) {
28 throw new InvalidDeviceLinkException("Invalid device link uri");
31 final byte[] publicKeyBytes
;
33 publicKeyBytes
= Base64
.getDecoder().decode(publicKeyEncoded
);
34 } catch (IllegalArgumentException e
) {
35 throw new InvalidDeviceLinkException("Invalid device link uri", e
);
37 ECPublicKey deviceKey
;
39 deviceKey
= new ECPublicKey(publicKeyBytes
);
40 } catch (InvalidKeyException e
) {
41 throw new InvalidDeviceLinkException("Invalid device link", e
);
44 return new DeviceLinkUrl(deviceIdentifier
, deviceKey
);
47 public URI
createDeviceLinkUri() {
48 final var deviceKeyString
= Base64
.getEncoder().encodeToString(deviceKey
.serialize()).replace("=", "");
50 return new URI("sgnl://linkdevice?uuid="
51 + URLEncoder
.encode(deviceIdentifier
, StandardCharsets
.UTF_8
)
53 + URLEncoder
.encode(deviceKeyString
, StandardCharsets
.UTF_8
));
54 } catch (URISyntaxException e
) {
55 throw new AssertionError(e
);