From 2da3ac5b20ff3b7a60cf297c0a490bb480057334 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Thu, 24 Jul 2025 13:49:15 -0400 Subject: [PATCH] Update link device provisioning proto. --- .../linkdevice/LinkDeviceRepository.kt | 8 +++ .../signalservice/api/link/LinkDeviceApi.kt | 9 ++- .../src/main/protowire/Provisioning.proto | 60 +++++++++++-------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt index 2b81fe92ee..712f97cd2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt @@ -117,6 +117,14 @@ object LinkDeviceRepository { return false } + if (uri.scheme != "sgnl") { + return false + } + + if (uri.host != "linkdevice") { + return false + } + val ephemeralId: String? = uri.getQueryParameter("uuid") val publicKeyEncoded: String? = uri.getQueryParameter("pub_key") return ephemeralId.isNotNullOrBlank() && publicKeyEncoded.isNotNullOrBlank() diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/link/LinkDeviceApi.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/link/LinkDeviceApi.kt index b3c9ccdf9a..6fd2049405 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/link/LinkDeviceApi.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/link/LinkDeviceApi.kt @@ -116,13 +116,16 @@ class LinkDeviceApi( aci = aci.toString(), pni = pni.toStringWithoutPrefix(), number = e164, - profileKey = profileKey.serialize().toByteString(), provisioningCode = code, + userAgent = null, + profileKey = profileKey.serialize().toByteString(), provisioningVersion = ProvisioningVersion.CURRENT.value, - accountEntropyPool = accountEntropyPool.value, masterKey = masterKey.serialize().toByteString(), + ephemeralBackupKey = ephemeralMessageBackupKey?.value?.toByteString(), + accountEntropyPool = accountEntropyPool.value, mediaRootBackupKey = mediaRootBackupKey.value.toByteString(), - ephemeralBackupKey = ephemeralMessageBackupKey?.value?.toByteString() + aciBinary = aci.toByteString(), + pniBinary = pni.toByteStringWithoutPrefix() ) val ciphertext: ByteArray = cipher.encrypt(message) val body = ProvisioningMessage(encodeWithPadding(ciphertext)) diff --git a/libsignal-service/src/main/protowire/Provisioning.proto b/libsignal-service/src/main/protowire/Provisioning.proto index e18829a66e..2fde938e19 100644 --- a/libsignal-service/src/main/protowire/Provisioning.proto +++ b/libsignal-service/src/main/protowire/Provisioning.proto @@ -1,48 +1,56 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. +/* + * Copyright 2020 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only */ + syntax = "proto2"; package signalservice; -option java_package = "org.whispersystems.signalservice.internal.push"; +option java_package = "org.whispersystems.signalservice.internal.push"; option java_outer_classname = "ProvisioningProtos"; +// An opaque address sent by the server when clients first open a provisioning +// WebSocket message ProvisioningAddress { + + // The opaque provisioning address for the active provisioning WebSocket + // session; clients should not attempt to interpret or modify the contents + // of the address string optional string address = 1; } message ProvisionEnvelope { optional bytes publicKey = 1; - optional bytes body = 2; // Encrypted ProvisionMessage + optional bytes body = 2; // Encrypted ProvisionMessage } message ProvisionMessage { - optional bytes aciIdentityKeyPublic = 1; - optional bytes aciIdentityKeyPrivate = 2; - optional bytes pniIdentityKeyPublic = 11; - optional bytes pniIdentityKeyPrivate = 12; - optional string aci = 8; - optional string pni = 10; - optional string number = 3; - optional string provisioningCode = 4; - optional string userAgent = 5; - optional bytes profileKey = 6; - optional bool readReceipts = 7; - optional uint32 provisioningVersion = 9; - optional bytes masterKey = 13; - optional bytes ephemeralBackupKey = 14; // 32 bytes - optional string accountEntropyPool = 15; - optional bytes mediaRootBackupKey = 16; // 32-bytes - // NEXT ID: 17 + optional bytes aciIdentityKeyPublic = 1; + optional bytes aciIdentityKeyPrivate = 2; + optional bytes pniIdentityKeyPublic = 11; + optional bytes pniIdentityKeyPrivate = 12; + optional string aci = 8; + optional string pni = 10; + optional string number = 3; + optional string provisioningCode = 4; + optional string userAgent = 5; + optional bytes profileKey = 6; + optional bool readReceipts = 7; + optional uint32 provisioningVersion = 9; + optional bytes masterKey = 13; // Deprecated, but required by linked devices + optional bytes ephemeralBackupKey = 14; // 32 bytes + optional string accountEntropyPool = 15; + optional bytes mediaRootBackupKey = 16; // 32-bytes + optional bytes aciBinary = 17; // 16-byte UUID + optional bytes pniBinary = 18; // 16-byte UUID + // NEXT ID: 19 } enum ProvisioningVersion { option allow_alias = true; - INITIAL = 0; - TABLET_SUPPORT = 1; - CURRENT = 1; + INITIAL = 0; + TABLET_SUPPORT = 1; + CURRENT = 1; }