From cefd70baf82907ad309278a54ac0a443c0e04029 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 28 Jun 2021 15:03:25 +0200 Subject: [PATCH] move size calculation methods to FileContentCryptor --- .../cryptomator/cryptolib/api/Cryptor.java | 42 ------------------- .../cryptolib/api/FileContentCryptor.java | 42 +++++++++++++++++++ .../cryptomator/cryptolib/api/FileHeader.java | 2 +- ...rTest.java => FileContentCryptorTest.java} | 18 ++++---- 4 files changed, 51 insertions(+), 53 deletions(-) rename src/test/java/org/cryptomator/cryptolib/api/{CryptorTest.java => FileContentCryptorTest.java} (70%) diff --git a/src/main/java/org/cryptomator/cryptolib/api/Cryptor.java b/src/main/java/org/cryptomator/cryptolib/api/Cryptor.java index 5a0b8c1..5e79c2c 100644 --- a/src/main/java/org/cryptomator/cryptolib/api/Cryptor.java +++ b/src/main/java/org/cryptomator/cryptolib/api/Cryptor.java @@ -10,8 +10,6 @@ import javax.security.auth.Destroyable; -import static com.google.common.base.Preconditions.checkArgument; - public interface Cryptor extends Destroyable, AutoCloseable { FileContentCryptor fileContentCryptor(); @@ -31,44 +29,4 @@ default void close() { destroy(); } - /** - * Calculates the size of the cleartext resulting from the given ciphertext decrypted with the given cryptor. - * - * @param ciphertextSize Length of encrypted payload. Not including the {@link FileHeaderCryptor#headerSize() length of the header}. - * @return Cleartext length of a ciphertextSize-sized ciphertext decrypted with cryptor. - */ - default long cleartextSize(long ciphertextSize) { - checkArgument(ciphertextSize >= 0, "expected ciphertextSize to be positive, but was %s", ciphertextSize); - long cleartextChunkSize = fileContentCryptor().cleartextChunkSize(); - long ciphertextChunkSize = fileContentCryptor().ciphertextChunkSize(); - long overheadPerChunk = ciphertextChunkSize - cleartextChunkSize; - long numFullChunks = ciphertextSize / ciphertextChunkSize; // floor by int-truncation - long additionalCiphertextBytes = ciphertextSize % ciphertextChunkSize; - if (additionalCiphertextBytes > 0 && additionalCiphertextBytes <= overheadPerChunk) { - throw new IllegalArgumentException("Method not defined for input value " + ciphertextSize); - } - long additionalCleartextBytes = (additionalCiphertextBytes == 0) ? 0 : additionalCiphertextBytes - overheadPerChunk; - assert additionalCleartextBytes >= 0; - return cleartextChunkSize * numFullChunks + additionalCleartextBytes; - } - - /** - * Calculates the size of the ciphertext resulting from the given cleartext encrypted with the given cryptor. - * - * @param cleartextSize Length of a unencrypted payload. - * @return Ciphertext length of a cleartextSize-sized cleartext encrypted with cryptor. - * Not including the {@link FileHeader#getFilesize() length of the header}. - */ - default long ciphertextSize(long cleartextSize) { - checkArgument(cleartextSize >= 0, "expected cleartextSize to be positive, but was %s", cleartextSize); - long cleartextChunkSize = fileContentCryptor().cleartextChunkSize(); - long ciphertextChunkSize = fileContentCryptor().ciphertextChunkSize(); - long overheadPerChunk = ciphertextChunkSize - cleartextChunkSize; - long numFullChunks = cleartextSize / cleartextChunkSize; // floor by int-truncation - long additionalCleartextBytes = cleartextSize % cleartextChunkSize; - long additionalCiphertextBytes = (additionalCleartextBytes == 0) ? 0 : additionalCleartextBytes + overheadPerChunk; - assert additionalCiphertextBytes >= 0; - return ciphertextChunkSize * numFullChunks + additionalCiphertextBytes; - } - } diff --git a/src/main/java/org/cryptomator/cryptolib/api/FileContentCryptor.java b/src/main/java/org/cryptomator/cryptolib/api/FileContentCryptor.java index d04983b..6cecb45 100644 --- a/src/main/java/org/cryptomator/cryptolib/api/FileContentCryptor.java +++ b/src/main/java/org/cryptomator/cryptolib/api/FileContentCryptor.java @@ -10,6 +10,8 @@ import java.nio.ByteBuffer; +import static com.google.common.base.Preconditions.checkArgument; + public interface FileContentCryptor { /** @@ -73,4 +75,44 @@ public interface FileContentCryptor { */ void decryptChunk(ByteBuffer ciphertextChunk, ByteBuffer cleartextChunk, long chunkNumber, FileHeader header, boolean authenticate) throws AuthenticationFailedException; + /** + * Calculates the size of the cleartext resulting from the given ciphertext decrypted with the given cryptor. + * + * @param ciphertextSize Length of encrypted payload. Not including the {@link FileHeaderCryptor#headerSize() length of the header}. + * @return Cleartext length of a ciphertextSize-sized ciphertext decrypted with cryptor. + */ + default long cleartextSize(long ciphertextSize) { + checkArgument(ciphertextSize >= 0, "expected ciphertextSize to be positive, but was %s", ciphertextSize); + long cleartextChunkSize = cleartextChunkSize(); + long ciphertextChunkSize = ciphertextChunkSize(); + long overheadPerChunk = ciphertextChunkSize - cleartextChunkSize; + long numFullChunks = ciphertextSize / ciphertextChunkSize; // floor by int-truncation + long additionalCiphertextBytes = ciphertextSize % ciphertextChunkSize; + if (additionalCiphertextBytes > 0 && additionalCiphertextBytes <= overheadPerChunk) { + throw new IllegalArgumentException("Method not defined for input value " + ciphertextSize); + } + long additionalCleartextBytes = (additionalCiphertextBytes == 0) ? 0 : additionalCiphertextBytes - overheadPerChunk; + assert additionalCleartextBytes >= 0; + return cleartextChunkSize * numFullChunks + additionalCleartextBytes; + } + + /** + * Calculates the size of the ciphertext resulting from the given cleartext encrypted with the given cryptor. + * + * @param cleartextSize Length of a unencrypted payload. + * @return Ciphertext length of a cleartextSize-sized cleartext encrypted with cryptor. + * Not including the {@link FileHeader#getFilesize() length of the header}. + */ + default long ciphertextSize(long cleartextSize) { + checkArgument(cleartextSize >= 0, "expected cleartextSize to be positive, but was %s", cleartextSize); + long cleartextChunkSize = cleartextChunkSize(); + long ciphertextChunkSize = ciphertextChunkSize(); + long overheadPerChunk = ciphertextChunkSize - cleartextChunkSize; + long numFullChunks = cleartextSize / cleartextChunkSize; // floor by int-truncation + long additionalCleartextBytes = cleartextSize % cleartextChunkSize; + long additionalCiphertextBytes = (additionalCleartextBytes == 0) ? 0 : additionalCleartextBytes + overheadPerChunk; + assert additionalCiphertextBytes >= 0; + return ciphertextChunkSize * numFullChunks + additionalCiphertextBytes; + } + } diff --git a/src/main/java/org/cryptomator/cryptolib/api/FileHeader.java b/src/main/java/org/cryptomator/cryptolib/api/FileHeader.java index 171eaa7..21ac961 100644 --- a/src/main/java/org/cryptomator/cryptolib/api/FileHeader.java +++ b/src/main/java/org/cryptomator/cryptolib/api/FileHeader.java @@ -11,7 +11,7 @@ public interface FileHeader { /** - * @deprecated No longer supported since vault version 5. Use {@link org.cryptomator.cryptolib.api.Cryptor#cleartextSize(long)} to calculate the cleartext size from the ciphertext size + * @deprecated No longer supported since vault version 5. Use {@link org.cryptomator.cryptolib.api.FileContentCryptor#cleartextSize(long)} to calculate the cleartext size from the ciphertext size * @return file size stored in file header */ @Deprecated diff --git a/src/test/java/org/cryptomator/cryptolib/api/CryptorTest.java b/src/test/java/org/cryptomator/cryptolib/api/FileContentCryptorTest.java similarity index 70% rename from src/test/java/org/cryptomator/cryptolib/api/CryptorTest.java rename to src/test/java/org/cryptomator/cryptolib/api/FileContentCryptorTest.java index e5f27a3..ab24ab9 100644 --- a/src/test/java/org/cryptomator/cryptolib/api/CryptorTest.java +++ b/src/test/java/org/cryptomator/cryptolib/api/FileContentCryptorTest.java @@ -7,18 +7,16 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mockito; -public class CryptorTest { +public class FileContentCryptorTest { - private final Cryptor cryptor = Mockito.mock(Cryptor.class); + private final FileContentCryptor contentCryptor = Mockito.mock(FileContentCryptor.class); @BeforeEach public void setup() { - FileContentCryptor contentCryptor = Mockito.mock(FileContentCryptor.class); - Mockito.when(cryptor.fileContentCryptor()).thenReturn(contentCryptor); Mockito.when(contentCryptor.cleartextChunkSize()).thenReturn(32); Mockito.when(contentCryptor.ciphertextChunkSize()).thenReturn(40); - Mockito.doCallRealMethod().when(cryptor).cleartextSize(Mockito.anyLong()); - Mockito.doCallRealMethod().when(cryptor).ciphertextSize(Mockito.anyLong()); + Mockito.doCallRealMethod().when(contentCryptor).cleartextSize(Mockito.anyLong()); + Mockito.doCallRealMethod().when(contentCryptor).ciphertextSize(Mockito.anyLong()); } @ParameterizedTest(name = "cleartextSize({1}) == {0}") @@ -34,14 +32,14 @@ public void setup() { "65,89" }) public void testCleartextSize(int cleartextSize, int ciphertextSize) { - Assertions.assertEquals(cleartextSize, cryptor.cleartextSize(ciphertextSize)); + Assertions.assertEquals(cleartextSize, contentCryptor.cleartextSize(ciphertextSize)); } @ParameterizedTest(name = "cleartextSize({0}) == undefined") @ValueSource(ints = {-1, 1, 8, 41, 48, 81, 88}) public void testCleartextSizeWithInvalidCiphertextSize(int invalidCiphertextSize) { Assertions.assertThrows(IllegalArgumentException.class, () -> { - cryptor.cleartextSize(invalidCiphertextSize); + contentCryptor.cleartextSize(invalidCiphertextSize); }); } @@ -58,14 +56,14 @@ public void testCleartextSizeWithInvalidCiphertextSize(int invalidCiphertextSize "65,89" }) public void testCiphertextSize(int cleartextSize, int ciphertextSize) { - Assertions.assertEquals(ciphertextSize, cryptor.ciphertextSize(cleartextSize)); + Assertions.assertEquals(ciphertextSize, contentCryptor.ciphertextSize(cleartextSize)); } @ParameterizedTest(name = "ciphertextSize({0}) == undefined") @ValueSource(ints = {-1}) public void testCiphertextSizewithInvalidCleartextSize(int invalidCleartextSize) { Assertions.assertThrows(IllegalArgumentException.class, () -> { - cryptor.ciphertextSize(invalidCleartextSize); + contentCryptor.ciphertextSize(invalidCleartextSize); }); }