diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManager.java index 67350d2da..903fb4b58 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManager.java @@ -19,7 +19,6 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; @@ -129,7 +128,7 @@ public class Cdn3RemoteStorageManager implements RemoteStorageManager { * Serialized copy request for cdn3 storage manager */ record Cdn3CopyRequest( - String encryptionKey, String hmacKey, String iv, + String encryptionKey, String hmacKey, SourceDescriptor source, int expectedSourceLength, String dst) { @@ -137,7 +136,6 @@ public class Cdn3RemoteStorageManager implements RemoteStorageManager { String dst) { this(Base64.getEncoder().encodeToString(parameters.aesEncryptionKey().getEncoded()), Base64.getEncoder().encodeToString(parameters.hmacSHA256Key().getEncoded()), - Base64.getEncoder().encodeToString(parameters.iv().getIV()), source, expectedSourceLength, dst); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/backup/MediaEncryptionParameters.java b/service/src/main/java/org/whispersystems/textsecuregcm/backup/MediaEncryptionParameters.java index 6d726bf6a..7c5014f50 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/backup/MediaEncryptionParameters.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/backup/MediaEncryptionParameters.java @@ -1,24 +1,22 @@ package org.whispersystems.textsecuregcm.backup; -import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public record MediaEncryptionParameters( SecretKeySpec aesEncryptionKey, - SecretKeySpec hmacSHA256Key, - IvParameterSpec iv) { + SecretKeySpec hmacSHA256Key) { - public MediaEncryptionParameters(byte[] encryptionKey, byte[] macKey, byte[] iv) { + public MediaEncryptionParameters(byte[] encryptionKey, byte[] macKey) { this( new SecretKeySpec(encryptionKey, "AES"), - new SecretKeySpec(macKey, "HmacSHA256"), - new IvParameterSpec(iv)); + new SecretKeySpec(macKey, "HmacSHA256")); } public int outputSize(final int inputSize) { // AES-256 has 16-byte block size, and always adds a block if the plaintext is a multiple of the block size final int numBlocks = (inputSize + 16) / 16; + // 16-byte IV will be generated and prepended to the ciphertext // IV + AES-256 encrypted data + HmacSHA256 - return this.iv().getIV().length + (numBlocks * 16) + 32; + return 16 + (numBlocks * 16) + 32; } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ArchiveController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ArchiveController.java index 0138d1c6d..a7fd7739c 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ArchiveController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ArchiveController.java @@ -512,19 +512,13 @@ public class ArchiveController { @JsonDeserialize(using = ByteArrayAdapter.Deserializing.class) @NotNull @ExactlySize(32) - byte[] encryptionKey, - - @Schema(description = "A 16-byte IV for AES, encoded in standard padded base64", implementation = String.class) - @JsonDeserialize(using = ByteArrayAdapter.Deserializing.class) - @NotNull - @ExactlySize(16) - byte[] iv) { + byte[] encryptionKey) { CopyParameters toCopyParameters() { return new CopyParameters( sourceAttachment.cdn(), sourceAttachment.key(), objectLength, - new MediaEncryptionParameters(encryptionKey, hmacKey, iv), + new MediaEncryptionParameters(encryptionKey, hmacKey), mediaId); } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/backup/BackupManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/backup/BackupManagerTest.java index f1a8b4259..ed6cb4712 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/backup/BackupManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/backup/BackupManagerTest.java @@ -85,8 +85,7 @@ public class BackupManagerTest { private static final MediaEncryptionParameters COPY_ENCRYPTION_PARAM = new MediaEncryptionParameters( TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)); + TestRandomUtil.nextBytes(32)); private static final CopyParameters COPY_PARAM = new CopyParameters( 3, "abc", 100, COPY_ENCRYPTION_PARAM, TestRandomUtil.nextBytes(15)); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManagerTest.java index 7083714aa..e031ef30c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/backup/Cdn3RemoteStorageManagerTest.java @@ -39,7 +39,6 @@ public class Cdn3RemoteStorageManagerTest { private static final byte[] HMAC_KEY = TestRandomUtil.nextBytes(32); private static final byte[] AES_KEY = TestRandomUtil.nextBytes(32); - private static final byte[] IV = TestRandomUtil.nextBytes(16); @RegisterExtension private static final WireMockExtension wireMock = WireMockExtension.newInstance() @@ -66,7 +65,7 @@ public class Cdn3RemoteStorageManagerTest { @ParameterizedTest @ValueSource(ints = {2, 3}) public void copy(final int sourceCdn) throws JsonProcessingException { - final MediaEncryptionParameters encryptionParameters = new MediaEncryptionParameters(AES_KEY, HMAC_KEY, IV); + final MediaEncryptionParameters encryptionParameters = new MediaEncryptionParameters(AES_KEY, HMAC_KEY); final String scheme = switch (sourceCdn) { case 2 -> "gcs"; case 3 -> "r2"; @@ -99,7 +98,7 @@ public class Cdn3RemoteStorageManagerTest { 2, "a/test/source", 100, - new MediaEncryptionParameters(AES_KEY, HMAC_KEY, IV), + new MediaEncryptionParameters(AES_KEY, HMAC_KEY), "a/destination").toCompletableFuture()); } @@ -111,7 +110,7 @@ public class Cdn3RemoteStorageManagerTest { 2, "a/test/source", 100, - new MediaEncryptionParameters(AES_KEY, HMAC_KEY, IV), + new MediaEncryptionParameters(AES_KEY, HMAC_KEY), "a/destination").toCompletableFuture()); } @@ -122,7 +121,7 @@ public class Cdn3RemoteStorageManagerTest { 0, "a/test/source", 100, - new MediaEncryptionParameters(AES_KEY, HMAC_KEY, IV), + new MediaEncryptionParameters(AES_KEY, HMAC_KEY), "a/destination").toCompletableFuture()); } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java index ab3264de2..ad14dfe65 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java @@ -272,8 +272,7 @@ public class ArchiveControllerTest { @ParameterizedTest @MethodSource - public void setBackupIdException(final Exception ex, final boolean sync, final int expectedStatus) - throws RateLimitExceededException { + public void setBackupIdException(final Exception ex, final boolean sync, final int expectedStatus) { if (sync) { when(backupAuthManager.commitBackupId(any(), any(), any())).thenThrow(ex); } else { @@ -393,16 +392,14 @@ public class ArchiveControllerTest { 100, mediaIds[0], TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)), + TestRandomUtil.nextBytes(32)), new ArchiveController.CopyMediaRequest( new RemoteAttachment(3, "def"), 200, mediaIds[1], TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)) + TestRandomUtil.nextBytes(32)) )))); assertThat(r.getStatus()).isEqualTo(207); final ArchiveController.CopyMediaBatchResponse copyResponse = r.readEntity( @@ -438,8 +435,7 @@ public class ArchiveControllerTest { 100, mediaId, TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)) + TestRandomUtil.nextBytes(32)) ).toList(); Response r = resources.getJerseyTest() @@ -454,7 +450,7 @@ public class ArchiveControllerTest { assertThat(copyResponse.responses()).hasSize(4); - final ArchiveController.CopyMediaBatchResponse.Entry r1 = copyResponse.responses().get(0); + final ArchiveController.CopyMediaBatchResponse.Entry r1 = copyResponse.responses().getFirst(); assertThat(r1.cdn()).isEqualTo(1); assertThat(r1.mediaId()).isEqualTo(mediaIds[0]); assertThat(r1.status()).isEqualTo(200); @@ -494,16 +490,14 @@ public class ArchiveControllerTest { 1, mediaIds[0], TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)), + TestRandomUtil.nextBytes(32)), new ArchiveController.CopyMediaRequest( new RemoteAttachment(3, "def"), -1, mediaIds[1], TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)) + TestRandomUtil.nextBytes(32)) )))); assertThat(r.getStatus()).isEqualTo(422); } @@ -573,7 +567,7 @@ public class ArchiveControllerTest { } @Test - public void mediaUploadForm() throws RateLimitExceededException, VerificationFailedException { + public void mediaUploadForm() throws VerificationFailedException { final BackupAuthCredentialPresentation presentation = backupAuthTestUtil.getPresentation(BackupLevel.PAID, messagesBackupKey, aci); when(backupManager.authenticateBackupUser(any(), any())) @@ -675,8 +669,7 @@ public class ArchiveControllerTest { 100, TestRandomUtil.nextBytes(15), TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(32), - TestRandomUtil.nextBytes(16)))); + TestRandomUtil.nextBytes(32)))); assertThat(r.getStatus()).isEqualTo(422); }