Revert "Fix contact photo upload failure."

This reverts commit 06dc8ccbdd.
This commit is contained in:
Nicholas Tinsley
2023-08-18 15:52:42 -04:00
committed by Cody Henthorne
parent 61b97fd09b
commit b5f82beb46
11 changed files with 40 additions and 103 deletions

View File

@@ -65,8 +65,8 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMes
import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage;
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.DistributionId;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
@@ -123,10 +123,8 @@ import org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevic
import org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException;
import org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException;
import org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException;
import org.whispersystems.signalservice.internal.push.http.AttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
import org.whispersystems.signalservice.internal.push.http.IncrementalAttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.LegacyAttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.OutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.PartialSendBatchCompleteListener;
import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener;
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
@@ -784,20 +782,18 @@ public class SignalServiceMessageSender {
}
public SignalServiceAttachmentPointer uploadAttachment(SignalServiceAttachmentStream attachment) throws IOException {
byte[] attachmentKey = attachment.getResumableUploadSpec().map(ResumableUploadSpec::getSecretKey).orElseGet(() -> Util.getSecretBytes(64));
byte[] attachmentIV = attachment.getResumableUploadSpec().map(ResumableUploadSpec::getIV).orElseGet(() -> Util.getSecretBytes(16));
long paddedLength = PaddingInputStream.getPaddedSize(attachment.getLength());
InputStream dataStream = new PaddingInputStream(attachment.getInputStream(), attachment.getLength());
long ciphertextLength = AttachmentCipherOutputStream.getCiphertextLength(paddedLength);
OutputStreamFactory outputStreamFactory = attachment.isIncremental() ? new IncrementalAttachmentCipherOutputStreamFactory(attachmentKey, attachmentIV)
: new LegacyAttachmentCipherOutputStreamFactory(attachmentKey, attachmentIV);
PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(),
dataStream,
ciphertextLength,
outputStreamFactory,
attachment.getListener(),
attachment.getCancelationSignal(),
attachment.getResumableUploadSpec().orElse(null));
byte[] attachmentKey = attachment.getResumableUploadSpec().map(ResumableUploadSpec::getSecretKey).orElseGet(() -> Util.getSecretBytes(64));
byte[] attachmentIV = attachment.getResumableUploadSpec().map(ResumableUploadSpec::getIV).orElseGet(() -> Util.getSecretBytes(16));
long paddedLength = PaddingInputStream.getPaddedSize(attachment.getLength());
InputStream dataStream = new PaddingInputStream(attachment.getInputStream(), attachment.getLength());
long ciphertextLength = AttachmentCipherOutputStream.getCiphertextLength(paddedLength);
PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(),
dataStream,
ciphertextLength,
new AttachmentCipherOutputStreamFactory(attachmentKey, attachmentIV),
attachment.getListener(),
attachment.getCancelationSignal(),
attachment.getResumableUploadSpec().orElse(null));
if (attachment.getResumableUploadSpec().isPresent()) {
return uploadAttachmentV3(attachment, attachmentKey, attachmentData);
@@ -835,7 +831,7 @@ public class SignalServiceMessageSender {
attachment.getPreview(),
attachment.getWidth(), attachment.getHeight(),
Optional.of(attachmentIdAndDigest.second().getDigest()),
Optional.ofNullable(attachmentIdAndDigest.second().getIncrementalDigest()),
Optional.of(attachmentIdAndDigest.second().getIncrementalDigest()),
attachment.getFileName(),
attachment.getVoiceNote(),
attachment.isBorderless(),

View File

@@ -62,7 +62,6 @@ public abstract class SignalServiceAttachment {
private String blurHash;
private long uploadTimestamp;
private ResumableUploadSpec resumableUploadSpec;
private boolean isIncremental;
private Builder() {}
@@ -141,11 +140,6 @@ public abstract class SignalServiceAttachment {
return this;
}
public Builder withIncremental(boolean isIncremental) {
this.isIncremental = isIncremental;
return this;
}
public SignalServiceAttachmentStream build() {
if (inputStream == null) throw new IllegalArgumentException("Must specify stream!");
if (contentType == null) throw new IllegalArgumentException("No content type specified!");
@@ -166,8 +160,7 @@ public abstract class SignalServiceAttachment {
Optional.ofNullable(blurHash),
listener,
cancelationSignal,
Optional.ofNullable(resumableUploadSpec),
isIncremental);
Optional.ofNullable(resumableUploadSpec));
}
}

View File

@@ -35,7 +35,6 @@ public class SignalServiceAttachmentStream extends SignalServiceAttachment imple
private final Optional<String> caption;
private final Optional<String> blurHash;
private final Optional<ResumableUploadSpec> resumableUploadSpec;
private final boolean isIncremental;
public SignalServiceAttachmentStream(InputStream inputStream,
String contentType,
@@ -47,7 +46,7 @@ public class SignalServiceAttachmentStream extends SignalServiceAttachment imple
ProgressListener listener,
CancelationSignal cancelationSignal)
{
this(inputStream, contentType, length, fileName, voiceNote, borderless, gif, Optional.empty(), 0, 0, System.currentTimeMillis(), Optional.empty(), Optional.empty(), listener, cancelationSignal, Optional.empty(), false);
this(inputStream, contentType, length, fileName, voiceNote, borderless, gif, Optional.empty(), 0, 0, System.currentTimeMillis(), Optional.empty(), Optional.empty(), listener, cancelationSignal, Optional.empty());
}
public SignalServiceAttachmentStream(InputStream inputStream,
@@ -65,8 +64,7 @@ public class SignalServiceAttachmentStream extends SignalServiceAttachment imple
Optional<String> blurHash,
ProgressListener listener,
CancelationSignal cancelationSignal,
Optional<ResumableUploadSpec> resumableUploadSpec,
boolean isIncremental)
Optional<ResumableUploadSpec> resumableUploadSpec)
{
super(contentType);
this.inputStream = inputStream;
@@ -84,7 +82,6 @@ public class SignalServiceAttachmentStream extends SignalServiceAttachment imple
this.blurHash = blurHash;
this.cancelationSignal = cancelationSignal;
this.resumableUploadSpec = resumableUploadSpec;
this.isIncremental = isIncremental;
}
@Override
@@ -157,10 +154,6 @@ public class SignalServiceAttachmentStream extends SignalServiceAttachment imple
return resumableUploadSpec;
}
public boolean isIncremental() {
return isIncremental;
}
@Override
public void close() throws IOException {
inputStream.close();

View File

@@ -1,12 +1,8 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.internal.push.http
import org.signal.libsignal.protocol.incrementalmac.ChunkSizeChoice
import org.signal.libsignal.protocol.incrementalmac.IncrementalMacOutputStream
import org.whispersystems.signalservice.api.crypto.AttachmentCipherOutputStream
import org.whispersystems.signalservice.api.crypto.DigestingOutputStream
import java.io.IOException
import java.io.OutputStream
@@ -14,21 +10,24 @@ import java.io.OutputStream
/**
* Creates [AttachmentCipherOutputStream] using the provided [key] and [iv].
*
* [createFor] is straightforward, and is the legacy behavior.
* [createIncrementalFor] first wraps the stream in an [IncrementalMacOutputStream] to calculate MAC digests on chunks as the stream is written to.
*
* @property key
* @property iv
*/
class IncrementalAttachmentCipherOutputStreamFactory(private val key: ByteArray, private val iv: ByteArray) : IncrementalOutputStreamFactory {
private val legacyDelegate = LegacyAttachmentCipherOutputStreamFactory(key, iv)
class AttachmentCipherOutputStreamFactory(private val key: ByteArray, private val iv: ByteArray) : OutputStreamFactory {
companion object {
private const val AES_KEY_LENGTH = 32
}
@Throws(IOException::class)
override fun createIncrementalFor(wrap: OutputStream?, length: Long, incrementalDigestOut: OutputStream?): DigestingOutputStream {
override fun createFor(wrap: OutputStream): DigestingOutputStream {
return AttachmentCipherOutputStream(key, iv, wrap)
}
@Throws(IOException::class)
fun createIncrementalFor(wrap: OutputStream?, length: Long, incrementalDigestOut: OutputStream?): DigestingOutputStream {
if (length > Int.MAX_VALUE) {
throw IllegalArgumentException("Attachment length overflows int!")
}
@@ -36,6 +35,6 @@ class IncrementalAttachmentCipherOutputStreamFactory(private val key: ByteArray,
val privateKey = key.sliceArray(AES_KEY_LENGTH until key.size)
val chunkSizeChoice = ChunkSizeChoice.inferChunkSize(length.toInt().coerceAtLeast(1))
val incrementalStream = IncrementalMacOutputStream(wrap, privateKey, chunkSizeChoice, incrementalDigestOut)
return legacyDelegate.createFor(incrementalStream)
return createFor(incrementalStream)
}
}

View File

@@ -41,9 +41,9 @@ class DigestingRequestBody(
override fun writeTo(sink: BufferedSink) {
val digestStream = ByteArrayOutputStream()
val inner = SkippingOutputStream(contentStart, sink.outputStream())
val isIncremental = outputStreamFactory is IncrementalOutputStreamFactory
val isIncremental = outputStreamFactory is AttachmentCipherOutputStreamFactory
val outputStream: DigestingOutputStream = if (isIncremental) {
(outputStreamFactory as IncrementalOutputStreamFactory).createIncrementalFor(inner, contentLength, digestStream)
(outputStreamFactory as AttachmentCipherOutputStreamFactory).createIncrementalFor(inner, contentLength, digestStream)
} else {
outputStreamFactory.createFor(inner)
}

View File

@@ -1,16 +0,0 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.internal.push.http
import org.whispersystems.signalservice.api.crypto.DigestingOutputStream
import java.io.OutputStream
interface IncrementalOutputStreamFactory : OutputStreamFactory {
override fun createFor(wrap: OutputStream?): DigestingOutputStream = error("Use createIncrementalFor instead.")
fun createIncrementalFor(wrap: OutputStream?, length: Long, incrementalDigestOut: OutputStream?): DigestingOutputStream
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.internal.push.http
import org.whispersystems.signalservice.api.crypto.AttachmentCipherOutputStream
import org.whispersystems.signalservice.api.crypto.DigestingOutputStream
import java.io.IOException
import java.io.OutputStream
/**
* Creates [AttachmentCipherOutputStream] using the provided [key] and [iv].
*
* [createFor] is straightforward, and is the legacy behavior.
*
* @property key
* @property iv
*/
class LegacyAttachmentCipherOutputStreamFactory(private val key: ByteArray, private val iv: ByteArray) : OutputStreamFactory {
@Throws(IOException::class)
override fun createFor(wrap: OutputStream): DigestingOutputStream {
return AttachmentCipherOutputStream(key, iv, wrap)
}
}

View File

@@ -6,8 +6,7 @@ import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.incrementalmac.InvalidMacException;
import org.signal.libsignal.protocol.kdf.HKDFv3;
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
import org.whispersystems.signalservice.internal.push.http.IncrementalAttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.LegacyAttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.push.http.AttachmentCipherOutputStreamFactory;
import org.whispersystems.signalservice.internal.util.Util;
import java.io.ByteArrayInputStream;
@@ -160,7 +159,7 @@ public final class AttachmentCipherTest {
InputStream paddedInputStream = new PaddingInputStream(inputStream, length);
ByteArrayOutputStream destinationOutputStream = new ByteArrayOutputStream();
ByteArrayOutputStream incrementalDigestOutputStream = new ByteArrayOutputStream();
DigestingOutputStream encryptingOutputStream = new IncrementalAttachmentCipherOutputStreamFactory(key, iv).createIncrementalFor(destinationOutputStream, length, incrementalDigestOutputStream);
DigestingOutputStream encryptingOutputStream = new AttachmentCipherOutputStreamFactory(key, iv).createIncrementalFor(destinationOutputStream, length, incrementalDigestOutputStream);
Util.copy(paddedInputStream, encryptingOutputStream);
@@ -302,15 +301,16 @@ public final class AttachmentCipherTest {
}
private static EncryptResult encryptData(byte[] data, byte[] keyMaterial, boolean withIncremental) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayOutputStream incrementalDigestOut = new ByteArrayOutputStream();
byte[] iv = Util.getSecretBytes(16);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayOutputStream incrementalDigestOut = new ByteArrayOutputStream();
byte[] iv = Util.getSecretBytes(16);
AttachmentCipherOutputStreamFactory factory = new AttachmentCipherOutputStreamFactory(keyMaterial, iv);
DigestingOutputStream encryptStream;
if (withIncremental) {
encryptStream = new IncrementalAttachmentCipherOutputStreamFactory(keyMaterial, iv).createIncrementalFor(outputStream, data.length, incrementalDigestOut);
encryptStream = factory.createIncrementalFor(outputStream, data.length, incrementalDigestOut);
} else {
encryptStream = new LegacyAttachmentCipherOutputStreamFactory(keyMaterial, iv).createFor(outputStream);
encryptStream = factory.createFor(outputStream);
}

View File

@@ -20,7 +20,7 @@ public class DigestingRequestBodyTest {
private final byte[] attachmentIV = Util.getSecretBytes(16);
private final byte[] input = Util.getSecretBytes(CONTENT_LENGTH);
private final OutputStreamFactory outputStreamFactory = new LegacyAttachmentCipherOutputStreamFactory(attachmentKey, attachmentIV);
private final OutputStreamFactory outputStreamFactory = new AttachmentCipherOutputStreamFactory(attachmentKey, attachmentIV);
@Test
public void givenSameKeyAndIV_whenIWriteToBuffer_thenIExpectSameDigests() throws Exception {