mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Match incremental MAC calculation.
This commit is contained in:
@@ -19,8 +19,8 @@ import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
@@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.service.NotificationController;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherOutputStream;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||
@@ -69,7 +69,7 @@ public final class AttachmentUploadJob extends BaseJob {
|
||||
|
||||
public static long getMaxPlaintextSize() {
|
||||
long maxCipherTextSize = FeatureFlags.maxAttachmentSizeBytes();
|
||||
long maxPaddedSize = AttachmentCipherOutputStream.getPlaintextLength(maxCipherTextSize);
|
||||
long maxPaddedSize = AttachmentCipherStreamUtil.getPlaintextLength(maxCipherTextSize);
|
||||
return PaddingInputStream.getMaxUnpaddedSize(maxPaddedSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.signal.libsignal.protocol.state.PreKeyBundle;
|
||||
import org.signal.libsignal.protocol.util.Pair;
|
||||
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherOutputStream;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||
import org.whispersystems.signalservice.api.crypto.EnvelopeContent;
|
||||
import org.whispersystems.signalservice.api.crypto.SignalGroupSessionBuilder;
|
||||
@@ -786,7 +787,7 @@ public class SignalServiceMessageSender {
|
||||
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);
|
||||
long ciphertextLength = AttachmentCipherStreamUtil.getCiphertextLength(paddedLength);
|
||||
PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(),
|
||||
dataStream,
|
||||
ciphertextLength,
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.signal.libsignal.protocol.incrementalmac.ChunkSizeChoice;
|
||||
import org.signal.libsignal.protocol.incrementalmac.IncrementalMacInputStream;
|
||||
import org.signal.libsignal.protocol.kdf.HKDFv3;
|
||||
import org.signal.libsignal.protocol.logging.Log;
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
|
||||
import org.whispersystems.signalservice.internal.util.ContentLengthInputStream;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
@@ -78,10 +80,12 @@ public class AttachmentCipherInputStream extends FilterInputStream {
|
||||
}
|
||||
wrappedStream = new FileInputStream(file);
|
||||
} else {
|
||||
final int dataSize = Math.toIntExact(AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(plaintextLength)));
|
||||
final ChunkSizeChoice sizeChoice = ChunkSizeChoice.inferChunkSize(dataSize);
|
||||
wrappedStream = new IncrementalMacInputStream(
|
||||
new FileInputStream(file),
|
||||
parts[1],
|
||||
ChunkSizeChoice.inferChunkSize(Math.toIntExact(plaintextLength)),
|
||||
sizeChoice,
|
||||
incrementalDigest);
|
||||
}
|
||||
InputStream inputStream = new AttachmentCipherInputStream(wrappedStream, parts[0], file.length() - BLOCK_SIZE - mac.getMacLength());
|
||||
|
||||
@@ -88,14 +88,6 @@ public class AttachmentCipherOutputStream extends DigestingOutputStream {
|
||||
}
|
||||
}
|
||||
|
||||
public static long getCiphertextLength(long plaintextLength) {
|
||||
return 16 + (((plaintextLength / 16) + 1) * 16) + 32;
|
||||
}
|
||||
|
||||
public static long getPlaintextLength(long ciphertextLength) {
|
||||
return (((ciphertextLength - 16 - 32) / 16) - 1) * 16;
|
||||
}
|
||||
|
||||
private Mac initializeMac() {
|
||||
try {
|
||||
return Mac.getInstance("HmacSHA256");
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.crypto
|
||||
|
||||
class AttachmentCipherStreamUtil {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getCiphertextLength(plaintextLength: Long): Long {
|
||||
return 16 + (plaintextLength / 16 + 1) * 16 + 32
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPlaintextLength(ciphertextLength: Long): Long {
|
||||
return ((ciphertextLength - 16 - 32) / 16 - 1) * 16
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,8 @@ class AttachmentCipherOutputStreamFactory(private val key: ByteArray, private va
|
||||
}
|
||||
|
||||
val privateKey = key.sliceArray(AES_KEY_LENGTH until key.size)
|
||||
val chunkSizeChoice = ChunkSizeChoice.inferChunkSize(length.toInt())
|
||||
val incrementalStream = IncrementalMacOutputStream(wrap, privateKey, chunkSizeChoice, incrementalDigestOut)
|
||||
val sizeChoice = ChunkSizeChoice.inferChunkSize(length.toInt())
|
||||
val incrementalStream = IncrementalMacOutputStream(wrap, privateKey, sizeChoice, incrementalDigestOut)
|
||||
return createFor(incrementalStream)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class AttachmentCipherTest {
|
||||
public void attachment_encryptDecrypt() throws IOException, InvalidMessageException {
|
||||
byte[] key = Util.getSecretBytes(64);
|
||||
byte[] plaintextInput = "Peter Parker".getBytes();
|
||||
EncryptResult encryptResult = encryptData(plaintextInput, key, true);
|
||||
EncryptResult encryptResult = encryptData(plaintextInput, key, false);
|
||||
File cipherFile = writeToFile(encryptResult.ciphertext);
|
||||
InputStream inputStream = AttachmentCipherInputStream.createForAttachment(cipherFile, plaintextInput.length, key, encryptResult.digest, encryptResult.incrementalDigest);
|
||||
byte[] plaintextOutput = readInputStreamFully(inputStream);
|
||||
@@ -158,8 +158,7 @@ public final class AttachmentCipherTest {
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(plaintextInput);
|
||||
InputStream paddedInputStream = new PaddingInputStream(inputStream, length);
|
||||
ByteArrayOutputStream destinationOutputStream = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream incrementalDigestOutputStream = new ByteArrayOutputStream();
|
||||
DigestingOutputStream encryptingOutputStream = new AttachmentCipherOutputStreamFactory(key, iv).createIncrementalFor(destinationOutputStream, length, incrementalDigestOutputStream);
|
||||
DigestingOutputStream encryptingOutputStream = new AttachmentCipherOutputStreamFactory(key, iv).createFor(destinationOutputStream);
|
||||
|
||||
Util.copy(paddedInputStream, encryptingOutputStream);
|
||||
|
||||
@@ -168,11 +167,10 @@ public final class AttachmentCipherTest {
|
||||
|
||||
byte[] encryptedData = destinationOutputStream.toByteArray();
|
||||
byte[] digest = encryptingOutputStream.getTransmittedDigest();
|
||||
byte[] incrementalDigest = incrementalDigestOutputStream.toByteArray();
|
||||
|
||||
File cipherFile = writeToFile(encryptedData);
|
||||
|
||||
InputStream decryptedStream = AttachmentCipherInputStream.createForAttachment(cipherFile, length, key, digest, incrementalDigest);
|
||||
InputStream decryptedStream = AttachmentCipherInputStream.createForAttachment(cipherFile, length, key, digest, null);
|
||||
byte[] plaintextOutput = readInputStreamFully(decryptedStream);
|
||||
|
||||
assertArrayEquals(plaintextInput, plaintextOutput);
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.whispersystems.signalservice.internal.push.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherOutputStream;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -14,7 +15,7 @@ import static org.junit.Assert.assertEquals;
|
||||
public class DigestingRequestBodyTest {
|
||||
|
||||
private static int CONTENT_LENGTH = 70000;
|
||||
private static int TOTAL_LENGTH = (int) AttachmentCipherOutputStream.getCiphertextLength(CONTENT_LENGTH);
|
||||
private static int TOTAL_LENGTH = (int) AttachmentCipherStreamUtil.getCiphertextLength(CONTENT_LENGTH);
|
||||
|
||||
private final byte[] attachmentKey = Util.getSecretBytes(64);
|
||||
private final byte[] attachmentIV = Util.getSecretBytes(16);
|
||||
|
||||
Reference in New Issue
Block a user