diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherInputStream.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherInputStream.java index 0be576153c..8ceb1226ea 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherInputStream.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherInputStream.java @@ -162,10 +162,12 @@ public class AttachmentCipherInputStream extends FilterInputStream { private int readFinal(byte[] buffer, int offset, int length) throws IOException { try { - int flourish = cipher.doFinal(buffer, offset); + byte[] internal = new byte[buffer.length]; + int actualLength = Math.min(length, cipher.doFinal(internal, 0)); + System.arraycopy(internal, 0, buffer, offset, actualLength); done = true; - return flourish; + return actualLength; } catch (IllegalBlockSizeException | BadPaddingException | ShortBufferException e) { throw new IOException(e); } diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherTest.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherTest.java index 23b496ff2a..82e3e25ff5 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherTest.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/crypto/AttachmentCipherTest.java @@ -4,8 +4,11 @@ import org.conscrypt.Conscrypt; import org.junit.Test; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.kdf.HKDFv3; +import org.whispersystems.signalservice.internal.crypto.PaddingInputStream; +import org.whispersystems.signalservice.internal.push.http.AttachmentCipherOutputStreamFactory; import org.whispersystems.signalservice.internal.util.Util; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -103,6 +106,43 @@ public final class AttachmentCipherTest { assertTrue(hitCorrectException); } + @Test + public void attachment_encryptDecryptPaddedContent() throws IOException, InvalidMessageException { + int[] lengths = { 531, 600, 724, 1019, 1024 }; + + for (int length : lengths) { + byte[] plaintextInput = new byte[length]; + + for (int i = 0; i < length; i++) { + plaintextInput[i] = (byte) 0x97; + } + + byte[] key = Util.getSecretBytes(64); + ByteArrayInputStream inputStream = new ByteArrayInputStream(plaintextInput); + InputStream dataStream = new PaddingInputStream(inputStream, length); + ByteArrayOutputStream encryptedStream = new ByteArrayOutputStream(); + DigestingOutputStream digestStream = new AttachmentCipherOutputStreamFactory(key, null).createFor(encryptedStream); + + Util.copy(dataStream, digestStream); + digestStream.flush(); + + byte[] digest = digestStream.getTransmittedDigest(); + byte[] encryptedData = encryptedStream.toByteArray(); + + encryptedStream.close(); + inputStream.close(); + + File cipherFile = writeToFile(encryptedData); + + InputStream decryptedStream = AttachmentCipherInputStream.createForAttachment(cipherFile, length, key, digest); + byte[] plaintextOutput = readInputStreamFully(decryptedStream); + + assertArrayEquals(plaintextInput, plaintextOutput); + + cipherFile.delete(); + } + } + @Test public void attachment_decryptFailOnNullDigest() throws IOException { File cipherFile = null;