From fba9b46fe95d71df43acf5320f0d0192769b30d6 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Wed, 23 Aug 2023 23:07:58 -0400 Subject: [PATCH] Convert Provisioning, ResumeableUploads, and StickerResources protos to wire. --- .../secondary/SecondaryProvisioningCipher.kt | 23 +++++------ .../SecondaryProvisioningCipherTest.kt | 28 +++++++------- .../api/SignalServiceAccountManager.java | 27 +++++++------ .../api/SignalServiceMessageReceiver.java | 16 ++++---- .../api/SignalServiceMessageSender.java | 4 +- .../crypto/PrimaryProvisioningCipher.java | 20 +++++----- .../push/http/ResumableUploadSpec.java | 38 +++++++++---------- .../{proto => protowire}/Provisioning.proto | 0 .../ResumableUploads.proto | 0 .../StickerResources.proto | 0 10 files changed, 78 insertions(+), 78 deletions(-) rename libsignal/service/src/main/{proto => protowire}/Provisioning.proto (100%) rename libsignal/service/src/main/{proto => protowire}/ResumableUploads.proto (100%) rename libsignal/service/src/main/{proto => protowire}/StickerResources.proto (100%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipher.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipher.kt index 09fc09ba6a..7736703495 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipher.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipher.kt @@ -9,7 +9,8 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKey import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.whispersystems.signalservice.api.util.UuidUtil import org.whispersystems.signalservice.internal.crypto.PrimaryProvisioningCipher -import org.whispersystems.signalservice.internal.push.ProvisioningProtos +import org.whispersystems.signalservice.internal.push.ProvisionEnvelope +import org.whispersystems.signalservice.internal.push.ProvisionMessage import java.security.InvalidKeyException import java.security.MessageDigest import java.security.NoSuchAlgorithmException @@ -26,9 +27,9 @@ class SecondaryProvisioningCipher private constructor(private val secondaryIdent val secondaryDevicePublicKey: IdentityKey = secondaryIdentityKeyPair.publicKey - fun decrypt(envelope: ProvisioningProtos.ProvisionEnvelope): ProvisionDecryptResult { - val primaryEphemeralPublicKey = envelope.publicKey.toByteArray() - val body = envelope.body.toByteArray() + fun decrypt(envelope: ProvisionEnvelope): ProvisionDecryptResult { + val primaryEphemeralPublicKey = envelope.publicKey!!.toByteArray() + val body = envelope.body!!.toByteArray() val provisionMessageLength = body.size - VERSION_LENGTH - IV_LENGTH - MAC_LENGTH @@ -64,17 +65,17 @@ class SecondaryProvisioningCipher private constructor(private val secondaryIdent return ProvisionDecryptResult.Error } - val provisioningMessage = ProvisioningProtos.ProvisionMessage.parseFrom(plaintext) + val provisioningMessage = ProvisionMessage.ADAPTER.decode(plaintext) return ProvisionDecryptResult.Success( uuid = UuidUtil.parseOrThrow(provisioningMessage.aci), - e164 = provisioningMessage.number, - identityKeyPair = IdentityKeyPair(IdentityKey(provisioningMessage.aciIdentityKeyPublic.toByteArray()), Curve.decodePrivatePoint(provisioningMessage.aciIdentityKeyPrivate.toByteArray())), - profileKey = ProfileKey(provisioningMessage.profileKey.toByteArray()), - areReadReceiptsEnabled = provisioningMessage.readReceipts, + e164 = provisioningMessage.number!!, + identityKeyPair = IdentityKeyPair(IdentityKey(provisioningMessage.aciIdentityKeyPublic!!.toByteArray()), Curve.decodePrivatePoint(provisioningMessage.aciIdentityKeyPrivate!!.toByteArray())), + profileKey = ProfileKey(provisioningMessage.profileKey!!.toByteArray()), + areReadReceiptsEnabled = provisioningMessage.readReceipts == true, primaryUserAgent = provisioningMessage.userAgent, - provisioningCode = provisioningMessage.provisioningCode, - provisioningVersion = provisioningMessage.provisioningVersion + provisioningCode = provisioningMessage.provisioningCode!!, + provisioningVersion = provisioningMessage.provisioningVersion!! ) } diff --git a/app/src/test/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipherTest.kt b/app/src/test/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipherTest.kt index 6a7b07d4f7..22b0e56b13 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipherTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/registration/secondary/SecondaryProvisioningCipherTest.kt @@ -1,6 +1,6 @@ package org.thoughtcrime.securesms.registration.secondary -import com.google.protobuf.ByteString +import okio.ByteString import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.instanceOf import org.hamcrest.Matchers.`is` @@ -8,9 +8,9 @@ import org.junit.Test import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.whispersystems.signalservice.internal.crypto.PrimaryProvisioningCipher -import org.whispersystems.signalservice.internal.push.ProvisioningProtos -import org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisionMessage -import org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisioningVersion +import org.whispersystems.signalservice.internal.push.ProvisionEnvelope +import org.whispersystems.signalservice.internal.push.ProvisionMessage +import org.whispersystems.signalservice.internal.push.ProvisioningVersion import java.util.UUID class SecondaryProvisioningCipherTest { @@ -23,16 +23,18 @@ class SecondaryProvisioningCipherTest { val primaryProfileKey = ProfileKeyUtil.createNew() val primaryProvisioningCipher = PrimaryProvisioningCipher(provisioningCipher.secondaryDevicePublicKey.publicKey) - val message = ProvisionMessage.newBuilder() - .setAciIdentityKeyPublic(ByteString.copyFrom(primaryIdentityKeyPair.publicKey.serialize())) - .setAciIdentityKeyPrivate(ByteString.copyFrom(primaryIdentityKeyPair.privateKey.serialize())) - .setProvisioningCode("code") - .setProvisioningVersion(ProvisioningVersion.CURRENT_VALUE) - .setNumber("+14045555555") - .setAci(UUID.randomUUID().toString()) - .setProfileKey(ByteString.copyFrom(primaryProfileKey.serialize())) + val message = ProvisionMessage( + aciIdentityKeyPublic = ByteString.of(*primaryIdentityKeyPair.publicKey.serialize()), + aciIdentityKeyPrivate = ByteString.of(*primaryIdentityKeyPair.privateKey.serialize()), + provisioningCode = "code", + provisioningVersion = ProvisioningVersion.CURRENT.value, + number = "+14045555555", + aci = UUID.randomUUID().toString(), + profileKey = ByteString.of(*primaryProfileKey.serialize()), + readReceipts = true + ) - val provisionMessage = ProvisioningProtos.ProvisionEnvelope.parseFrom(primaryProvisioningCipher.encrypt(message.build())) + val provisionMessage = ProvisionEnvelope.ADAPTER.decode(primaryProvisioningCipher.encrypt(message)) val result = provisioningCipher.decrypt(provisionMessage) assertThat(result, instanceOf(SecondaryProvisioningCipher.ProvisionDecryptResult.Success::class.java)) diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index ac618c726e..915f179a42 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -61,6 +61,8 @@ import org.whispersystems.signalservice.internal.push.BackupAuthCheckResponse; import org.whispersystems.signalservice.internal.push.CdsiAuthResponse; import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts; import org.whispersystems.signalservice.internal.push.ProfileAvatarData; +import org.whispersystems.signalservice.internal.push.ProvisionMessage; +import org.whispersystems.signalservice.internal.push.ProvisioningVersion; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse; import org.whispersystems.signalservice.internal.push.RemoteConfigResponse; @@ -104,9 +106,6 @@ import javax.annotation.Nullable; import io.reactivex.rxjava3.core.Single; -import static org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisionMessage; -import static org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisioningVersion; - /** * The main interface for creating, registering, and * managing a Signal Service account. @@ -662,17 +661,17 @@ public class SignalServiceAccountManager { Preconditions.checkArgument(pni != null, "Missing PNI!"); PrimaryProvisioningCipher cipher = new PrimaryProvisioningCipher(deviceKey); - ProvisionMessage.Builder message = ProvisionMessage.newBuilder() - .setAciIdentityKeyPublic(ByteString.copyFrom(aciIdentityKeyPair.getPublicKey().serialize())) - .setAciIdentityKeyPrivate(ByteString.copyFrom(aciIdentityKeyPair.getPrivateKey().serialize())) - .setPniIdentityKeyPublic(ByteString.copyFrom(pniIdentityKeyPair.getPublicKey().serialize())) - .setPniIdentityKeyPrivate(ByteString.copyFrom(pniIdentityKeyPair.getPrivateKey().serialize())) - .setAci(aci.toString()) - .setPni(pni.toStringWithoutPrefix()) - .setNumber(e164) - .setProfileKey(ByteString.copyFrom(profileKey.serialize())) - .setProvisioningCode(code) - .setProvisioningVersion(ProvisioningVersion.CURRENT_VALUE); + ProvisionMessage.Builder message = new ProvisionMessage.Builder() + .aciIdentityKeyPublic(okio.ByteString.of(aciIdentityKeyPair.getPublicKey().serialize())) + .aciIdentityKeyPrivate(okio.ByteString.of(aciIdentityKeyPair.getPrivateKey().serialize())) + .pniIdentityKeyPublic(okio.ByteString.of(pniIdentityKeyPair.getPublicKey().serialize())) + .pniIdentityKeyPrivate(okio.ByteString.of(pniIdentityKeyPair.getPrivateKey().serialize())) + .aci(aci.toString()) + .pni(pni.toStringWithoutPrefix()) + .number(e164) + .profileKey(okio.ByteString.of(profileKey.serialize())) + .provisioningCode(code) + .provisioningVersion(ProvisioningVersion.CURRENT.getValue()); byte[] ciphertext = cipher.encrypt(message.build()); this.pushServiceSocket.sendProvisioningMessage(deviceIdentifier, ciphertext); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java index 0a5b68562b..e0abd3df74 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java @@ -27,7 +27,7 @@ import org.whispersystems.signalservice.internal.configuration.SignalServiceConf import org.whispersystems.signalservice.internal.push.IdentityCheckRequest; import org.whispersystems.signalservice.internal.push.IdentityCheckResponse; import org.whispersystems.signalservice.internal.push.PushServiceSocket; -import org.whispersystems.signalservice.internal.sticker.StickerProtos; +import org.whispersystems.signalservice.internal.sticker.Pack; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.concurrent.FutureTransformers; import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture; @@ -185,15 +185,15 @@ public class SignalServiceMessageReceiver { InputStream cipherStream = AttachmentCipherInputStream.createForStickerData(manifestBytes, packKey); - StickerProtos.Pack pack = StickerProtos.Pack.parseFrom(Util.readFullyAsBytes(cipherStream)); - List stickers = new ArrayList<>(pack.getStickersCount()); - SignalServiceStickerManifest.StickerInfo cover = pack.hasCover() ? new SignalServiceStickerManifest.StickerInfo(pack.getCover().getId(), pack.getCover().getEmoji(), pack.getCover().getContentType()) - : null; + Pack pack = Pack.ADAPTER.decode(Util.readFullyAsBytes(cipherStream)); + List stickers = new ArrayList<>(pack.stickers.size()); + SignalServiceStickerManifest.StickerInfo cover = pack.cover != null ? new SignalServiceStickerManifest.StickerInfo(pack.cover.id, pack.cover.emoji, pack.cover.contentType) + : null; - for (StickerProtos.Pack.Sticker sticker : pack.getStickersList()) { - stickers.add(new SignalServiceStickerManifest.StickerInfo(sticker.getId(), sticker.getEmoji(), sticker.getContentType())); + for (Pack.Sticker sticker : pack.stickers) { + stickers.add(new SignalServiceStickerManifest.StickerInfo(sticker.id, sticker.emoji, sticker.contentType)); } - return new SignalServiceStickerManifest(pack.getTitle(), pack.getAuthor(), cover, stickers); + return new SignalServiceStickerManifest(pack.title, pack.author, cover, stickers); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 8cf2b2d100..7b79ce492b 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -96,7 +96,7 @@ import org.whispersystems.signalservice.internal.push.GroupStaleDevices; import org.whispersystems.signalservice.internal.push.MismatchedDevices; import org.whispersystems.signalservice.internal.push.OutgoingPushMessage; import org.whispersystems.signalservice.internal.push.OutgoingPushMessageList; -import org.whispersystems.signalservice.internal.push.ProvisioningProtos; +import org.whispersystems.signalservice.internal.push.ProvisioningVersion; import org.whispersystems.signalservice.internal.push.PushAttachmentData; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.push.SendGroupMessageResponse; @@ -1522,7 +1522,7 @@ public class SignalServiceMessageSender { configurationMessage.setLinkPreviews(configuration.getLinkPreviews().get()); } - configurationMessage.setProvisioningVersion(ProvisioningProtos.ProvisioningVersion.CURRENT_VALUE); + configurationMessage.setProvisioningVersion(ProvisioningVersion.CURRENT.getValue()); return container.setSyncMessage(syncMessage.setConfiguration(configurationMessage)).build(); } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/crypto/PrimaryProvisioningCipher.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/crypto/PrimaryProvisioningCipher.java index 0c1ef5934e..72b13f6382 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/crypto/PrimaryProvisioningCipher.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/crypto/PrimaryProvisioningCipher.java @@ -6,13 +6,13 @@ package org.whispersystems.signalservice.internal.crypto; -import com.google.protobuf.ByteString; - import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.signal.libsignal.protocol.kdf.HKDF; +import org.whispersystems.signalservice.internal.push.ProvisionEnvelope; +import org.whispersystems.signalservice.internal.push.ProvisionMessage; import org.whispersystems.signalservice.internal.util.Util; import java.security.NoSuchAlgorithmException; @@ -24,9 +24,7 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; -import static org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisionEnvelope; -import static org.whispersystems.signalservice.internal.push.ProvisioningProtos.ProvisionMessage; - +import okio.ByteString; public class PrimaryProvisioningCipher { @@ -45,15 +43,15 @@ public class PrimaryProvisioningCipher { byte[][] parts = Util.split(derivedSecret, 32, 32); byte[] version = {0x01}; - byte[] ciphertext = getCiphertext(parts[0], message.toByteArray()); + byte[] ciphertext = getCiphertext(parts[0], message.encode()); byte[] mac = getMac(parts[1], Util.join(version, ciphertext)); byte[] body = Util.join(version, ciphertext, mac); - return ProvisionEnvelope.newBuilder() - .setPublicKey(ByteString.copyFrom(ourKeyPair.getPublicKey().serialize())) - .setBody(ByteString.copyFrom(body)) - .build() - .toByteArray(); + return new ProvisionEnvelope.Builder() + .publicKey(ByteString.of(ourKeyPair.getPublicKey().serialize())) + .body(ByteString.of(body)) + .build() + .encode(); } private byte[] getCiphertext(byte[] key, byte[] message) { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java index 7d32474e17..f814104d6f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java @@ -1,13 +1,13 @@ package org.whispersystems.signalservice.internal.push.http; -import com.google.protobuf.ByteString; - -import org.signal.protos.resumableuploads.ResumableUploads; +import org.signal.protos.resumableuploads.ResumableUpload; import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException; import org.whispersystems.util.Base64; import java.io.IOException; +import okio.ByteString; + public final class ResumableUploadSpec { private final byte[] secretKey; @@ -58,31 +58,31 @@ public final class ResumableUploadSpec { } public String serialize() { - ResumableUploads.ResumableUpload.Builder builder = ResumableUploads.ResumableUpload.newBuilder() - .setSecretKey(ByteString.copyFrom(getSecretKey())) - .setIv(ByteString.copyFrom(getIV())) - .setTimeout(getExpirationTimestamp()) - .setCdnNumber(getCdnNumber()) - .setCdnKey(getCdnKey()) - .setLocation(getResumeLocation()) - .setTimeout(getExpirationTimestamp()); + ResumableUpload.Builder builder = new ResumableUpload.Builder() + .secretKey(ByteString.of(getSecretKey())) + .iv(ByteString.of(getIV())) + .timeout(getExpirationTimestamp()) + .cdnNumber(getCdnNumber()) + .cdnKey(getCdnKey()) + .location(getResumeLocation()) + .timeout(getExpirationTimestamp()); - return Base64.encodeBytes(builder.build().toByteArray()); + return Base64.encodeBytes(builder.build().encode()); } public static ResumableUploadSpec deserialize(String serializedSpec) throws ResumeLocationInvalidException { if (serializedSpec == null) return null; try { - ResumableUploads.ResumableUpload resumableUpload = ResumableUploads.ResumableUpload.parseFrom(ByteString.copyFrom(Base64.decode(serializedSpec))); + ResumableUpload resumableUpload = ResumableUpload.ADAPTER.decode(Base64.decode(serializedSpec)); return new ResumableUploadSpec( - resumableUpload.getSecretKey().toByteArray(), - resumableUpload.getIv().toByteArray(), - resumableUpload.getCdnKey(), - resumableUpload.getCdnNumber(), - resumableUpload.getLocation(), - resumableUpload.getTimeout() + resumableUpload.secretKey.toByteArray(), + resumableUpload.iv.toByteArray(), + resumableUpload.cdnKey, + resumableUpload.cdnNumber, + resumableUpload.location, + resumableUpload.timeout ); } catch (IOException e) { throw new ResumeLocationInvalidException(); diff --git a/libsignal/service/src/main/proto/Provisioning.proto b/libsignal/service/src/main/protowire/Provisioning.proto similarity index 100% rename from libsignal/service/src/main/proto/Provisioning.proto rename to libsignal/service/src/main/protowire/Provisioning.proto diff --git a/libsignal/service/src/main/proto/ResumableUploads.proto b/libsignal/service/src/main/protowire/ResumableUploads.proto similarity index 100% rename from libsignal/service/src/main/proto/ResumableUploads.proto rename to libsignal/service/src/main/protowire/ResumableUploads.proto diff --git a/libsignal/service/src/main/proto/StickerResources.proto b/libsignal/service/src/main/protowire/StickerResources.proto similarity index 100% rename from libsignal/service/src/main/proto/StickerResources.proto rename to libsignal/service/src/main/protowire/StickerResources.proto