From ddf6353729ab07049057dd41a04f9feca98031f7 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 5 Jan 2016 16:55:52 +0100 Subject: [PATCH] Using DI to stack up filesystem layers --- .../cryptomator/crypto/CryptoComponent.java | 15 --- .../crypto/CryptoFileSystemFactory.java | 27 ----- ...ptoModule.java => CryptoEngineModule.java} | 6 +- .../engine/impl/FileContentCryptorImpl.java | 2 +- .../blockaligned/BlockAlignedFileSystem.java | 2 +- .../BlockAlignedFileSystemFactory.java | 20 ++++ .../filesystem/crypto/CryptoFileSystem.java | 2 +- .../crypto/CryptoFileSystemComponent.java | 15 +++ .../crypto/CryptoFileSystemFactory.java | 32 ++++++ .../CryptoFileSystemIntegrationTest.java | 60 ---------- .../crypto/CryptoTestComponent.java | 15 --- .../engine/impl/CryptoEngineTestModule.java | 23 ++++ .../crypto/engine/impl/CryptoTestModule.java | 31 ------ ...ptoFileSystemComponentIntegrationTest.java | 104 +++++++++++++++++ .../filesystem/crypto/DirectoryPrinter.java | 37 ------ .../EncryptAndShortenIntegrationTest.java | 105 ------------------ main/filesystem-nameshortening/pom.xml | 11 ++ .../blacklisting/BlacklistingFileSystem.java | 2 +- .../BlacklistingFileSystemFactory.java | 22 ++++ .../shortening/ShorteningFileSystem.java | 2 +- .../ShorteningFileSystemFactory.java | 32 ++++++ .../ShorteningFileSystemFactoryTest.java | 59 ++++++++++ .../ShorteningFileSystemTestComponent.java | 13 +++ 23 files changed, 339 insertions(+), 298 deletions(-) delete mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoComponent.java delete mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoFileSystemFactory.java rename main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/{CryptoModule.java => CryptoEngineModule.java} (77%) create mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystemFactory.java create mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java create mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java delete mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoFileSystemIntegrationTest.java delete mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoTestComponent.java create mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoEngineTestModule.java delete mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoTestModule.java create mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java delete mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/DirectoryPrinter.java delete mode 100644 main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/EncryptAndShortenIntegrationTest.java create mode 100644 main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystemFactory.java create mode 100644 main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactory.java create mode 100644 main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactoryTest.java create mode 100644 main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTestComponent.java diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoComponent.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoComponent.java deleted file mode 100644 index 927a0a6ab..000000000 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoComponent.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cryptomator.crypto; - -import javax.inject.Singleton; - -import org.cryptomator.crypto.engine.impl.CryptoModule; - -import dagger.Component; - -@Singleton -@Component(modules = CryptoModule.class) -interface CryptoComponent { - - CryptoFileSystemFactory cryptoFileSystemFactory(); - -} diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoFileSystemFactory.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoFileSystemFactory.java deleted file mode 100644 index bca2ce86d..000000000 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/CryptoFileSystemFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cryptomator.crypto; - -import javax.inject.Inject; -import javax.inject.Provider; -import javax.inject.Singleton; - -import org.cryptomator.crypto.engine.Cryptor; -import org.cryptomator.crypto.engine.impl.FileContentCryptorImpl; -import org.cryptomator.filesystem.FileSystem; -import org.cryptomator.filesystem.Folder; -import org.cryptomator.filesystem.blockaligned.BlockAlignedFileSystem; -import org.cryptomator.filesystem.crypto.CryptoFileSystem; - -@Singleton -public class CryptoFileSystemFactory { - - private final Provider cryptorProvider; - - @Inject - public CryptoFileSystemFactory(Provider cryptorProvider) { - this.cryptorProvider = cryptorProvider; - } - - public FileSystem get(Folder root, CharSequence passphrase) { - return new BlockAlignedFileSystem(new CryptoFileSystem(root, cryptorProvider.get(), passphrase), FileContentCryptorImpl.CHUNK_SIZE); - } -} diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoModule.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoEngineModule.java similarity index 77% rename from main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoModule.java rename to main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoEngineModule.java index 4be4e6621..2ded341b7 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoModule.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptoEngineModule.java @@ -9,15 +9,15 @@ import dagger.Module; import dagger.Provides; @Module -public class CryptoModule { +public class CryptoEngineModule { @Provides - Cryptor provideCryptor(SecureRandom secureRandom) { + public Cryptor provideCryptor(SecureRandom secureRandom) { return new CryptorImpl(secureRandom); } @Provides - SecureRandom provideSecureRandom() { + public SecureRandom provideSecureRandom() { try { return SecureRandom.getInstanceStrong(); } catch (NoSuchAlgorithmException e) { diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentCryptorImpl.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentCryptorImpl.java index 144d1555c..acb4b456e 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentCryptorImpl.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentCryptorImpl.java @@ -21,7 +21,7 @@ import org.cryptomator.crypto.engine.FileContentEncryptor; public class FileContentCryptorImpl implements FileContentCryptor { public static final int CHUNK_SIZE = 32 * 1024; - static final int MAC_SIZE = 32; + public static final int MAC_SIZE = 32; private final SecretKey encryptionKey; private final SecretKey macKey; diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java index 1a0df25e1..9d182b3bb 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java @@ -11,7 +11,7 @@ package org.cryptomator.filesystem.blockaligned; import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; -public class BlockAlignedFileSystem extends BlockAlignedFolder implements FileSystem { +class BlockAlignedFileSystem extends BlockAlignedFolder implements FileSystem { public BlockAlignedFileSystem(Folder delegate, int blockSize) { super(null, delegate, blockSize); diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystemFactory.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystemFactory.java new file mode 100644 index 000000000..aec55eb8f --- /dev/null +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystemFactory.java @@ -0,0 +1,20 @@ +package org.cryptomator.filesystem.blockaligned; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.cryptomator.crypto.engine.impl.FileContentCryptorImpl; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; + +@Singleton +public class BlockAlignedFileSystemFactory { + + @Inject + public BlockAlignedFileSystemFactory() { + } + + public FileSystem get(Folder root) { + return new BlockAlignedFileSystem(root, FileContentCryptorImpl.CHUNK_SIZE); + } +} diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java index b19555e20..779d860b2 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java @@ -19,7 +19,7 @@ import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.ReadableFile; import org.cryptomator.filesystem.WritableFile; -public class CryptoFileSystem extends CryptoFolder implements FileSystem { +class CryptoFileSystem extends CryptoFolder implements FileSystem { private static final String DATA_ROOT_DIR = "d"; private static final String ROOT_DIR_FILE = "root"; diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java new file mode 100644 index 000000000..c75864fc2 --- /dev/null +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponent.java @@ -0,0 +1,15 @@ +package org.cryptomator.filesystem.crypto; + +import javax.inject.Singleton; + +import org.cryptomator.crypto.engine.impl.CryptoEngineModule; + +import dagger.Component; + +@Singleton +@Component(modules = CryptoEngineModule.class) +interface CryptoFileSystemComponent { + + CryptoFileSystemFactory cryptoFileSystemFactory(); + +} diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java new file mode 100644 index 000000000..de89639c2 --- /dev/null +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java @@ -0,0 +1,32 @@ +package org.cryptomator.filesystem.crypto; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.cryptomator.crypto.engine.Cryptor; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.blockaligned.BlockAlignedFileSystemFactory; +import org.cryptomator.filesystem.shortening.ShorteningFileSystemFactory; + +@Singleton +public class CryptoFileSystemFactory { + + private final Provider cryptorProvider; + private final ShorteningFileSystemFactory shorteningFileSystemFactory; + private final BlockAlignedFileSystemFactory blockAlignedFileSystemFactory; + + @Inject + public CryptoFileSystemFactory(Provider cryptorProvider, ShorteningFileSystemFactory shorteningFileSystemFactory, BlockAlignedFileSystemFactory blockAlignedFileSystemFactory) { + this.cryptorProvider = cryptorProvider; + this.shorteningFileSystemFactory = shorteningFileSystemFactory; + this.blockAlignedFileSystemFactory = blockAlignedFileSystemFactory; + } + + public FileSystem get(Folder root, CharSequence passphrase) { + final FileSystem nameShorteningFs = shorteningFileSystemFactory.get(root); + final FileSystem cryptoFs = new CryptoFileSystem(nameShorteningFs, cryptorProvider.get(), passphrase); + return blockAlignedFileSystemFactory.get(cryptoFs); + } +} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoFileSystemIntegrationTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoFileSystemIntegrationTest.java deleted file mode 100644 index e7ff9c454..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoFileSystemIntegrationTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.cryptomator.crypto; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -import org.cryptomator.filesystem.File; -import org.cryptomator.filesystem.FileSystem; -import org.cryptomator.filesystem.Folder; -import org.cryptomator.filesystem.ReadableFile; -import org.cryptomator.filesystem.WritableFile; -import org.cryptomator.filesystem.inmem.InMemoryFileSystem; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class CryptoFileSystemIntegrationTest { - - private FileSystem ciphertextFs; - private FileSystem cleartextFs; - - @Before - public void setupFileSystems() { - ciphertextFs = new InMemoryFileSystem(); - // final Predicate isMetadataFolder = (Node node) -> node.equals(physicalFs.folder("m")); - // final FileSystem metadataHidingFs = new BlacklistingFileSystem(physicalFs, isMetadataFolder); - // final FileSystem shorteningFs = new ShorteningFileSystem(metadataHidingFs, physicalFs.folder("m"), 70); - cleartextFs = DaggerCryptoTestComponent.create().cryptoFileSystemFactory().get(ciphertextFs, "TopSecret"); - cleartextFs.create(); - } - - @Test - public void testRandomAccess() { - File cleartextFile = cleartextFs.file("test"); - try (WritableFile writable = cleartextFile.openWritable()) { - ByteBuffer buf = ByteBuffer.allocate(25000); - for (int i = 0; i < 40; i++) { // 40 * 25k = 1M - buf.clear(); - Arrays.fill(buf.array(), (byte) i); - writable.write(buf); - } - } - - Folder ciphertextRootFolder = ciphertextFs.folder("d").folders().findAny().get().folders().findAny().get(); - Assert.assertTrue(ciphertextRootFolder.exists()); - File ciphertextFile = ciphertextRootFolder.files().findAny().get(); - Assert.assertTrue(ciphertextFile.exists()); - - try (ReadableFile readable = cleartextFile.openReadable()) { - ByteBuffer buf = ByteBuffer.allocate(1); - for (int i = 0; i < 40; i++) { - buf.clear(); - readable.position(i * 25000 + (long) Math.random() * 24999); - readable.read(buf); - buf.flip(); - Assert.assertEquals(i, buf.get()); - } - } - } - -} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoTestComponent.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoTestComponent.java deleted file mode 100644 index d98995407..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/CryptoTestComponent.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cryptomator.crypto; - -import javax.inject.Singleton; - -import org.cryptomator.crypto.engine.impl.CryptoTestModule; - -import dagger.Component; - -@Singleton -@Component(modules = CryptoTestModule.class) -interface CryptoTestComponent { - - CryptoFileSystemFactory cryptoFileSystemFactory(); - -} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoEngineTestModule.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoEngineTestModule.java new file mode 100644 index 000000000..983d800ce --- /dev/null +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoEngineTestModule.java @@ -0,0 +1,23 @@ +package org.cryptomator.crypto.engine.impl; + +import java.security.SecureRandom; +import java.util.Arrays; + +/** + * Used as drop-in-replacement for {@link CryptoEngineModule} during unit tests. + */ +public class CryptoEngineTestModule extends CryptoEngineModule { + + @Override + public SecureRandom provideSecureRandom() { + return new SecureRandom() { + + @Override + public void nextBytes(byte[] bytes) { + Arrays.fill(bytes, (byte) 0x00); + } + + }; + } + +} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoTestModule.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoTestModule.java deleted file mode 100644 index 5f9c31165..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/CryptoTestModule.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cryptomator.crypto.engine.impl; - -import java.security.SecureRandom; -import java.util.Arrays; - -import org.cryptomator.crypto.engine.Cryptor; - -import dagger.Module; -import dagger.Provides; - -@Module -public class CryptoTestModule { - - @Provides - Cryptor provideCryptor(SecureRandom secureRandom) { - return new CryptorImpl(secureRandom); - } - - @Provides - SecureRandom provideSecureRandom() { - return new SecureRandom() { - - @Override - public void nextBytes(byte[] bytes) { - Arrays.fill(bytes, (byte) 0x00); - } - - }; - } - -} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java new file mode 100644 index 000000000..f34e10bac --- /dev/null +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java @@ -0,0 +1,104 @@ +package org.cryptomator.filesystem.crypto; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import org.cryptomator.crypto.engine.impl.CryptoEngineTestModule; +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.Node; +import org.cryptomator.filesystem.ReadableFile; +import org.cryptomator.filesystem.WritableFile; +import org.cryptomator.filesystem.inmem.InMemoryFileSystem; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CryptoFileSystemComponentIntegrationTest { + + private static final CryptoFileSystemComponent cryptoFsComp = DaggerCryptoFileSystemComponent.builder().cryptoEngineModule(new CryptoEngineTestModule()).build(); + + private FileSystem ciphertextFs; + private FileSystem cleartextFs; + + @Before + public void setupFileSystems() { + ciphertextFs = new InMemoryFileSystem(); + cleartextFs = cryptoFsComp.cryptoFileSystemFactory().get(ciphertextFs, "TopSecret"); + cleartextFs.create(); + } + + @Test + public void testEncryptionOfLongFolderNames() { + final String shortName = "normal folder name"; + final String longName = "this will be a long filename after encryption, because its encrypted name is longer than onehundredandeighty characters"; + + final Folder shortFolder = cleartextFs.folder(shortName); + final Folder longFolder = cleartextFs.folder(longName); + + shortFolder.create(); + longFolder.create(); + + // because of the long file, a metadata folder should exist on the physical layer: + Assert.assertEquals(1, ciphertextFs.folder("m").folders().count()); + Assert.assertTrue(ciphertextFs.folder("m").exists()); + + // but the shortened filenames must not be visible on the cleartext layer: + Assert.assertArrayEquals(new String[] {shortName, longName}, cleartextFs.folders().map(Node::name).sorted().toArray()); + } + + @Test + public void testEncryptionAndDecryptionOfFiles() { + // write test content to encrypted file + try (WritableFile writable = cleartextFs.file("test1.txt").openWritable()) { + writable.write(ByteBuffer.wrap("Hello ".getBytes())); + writable.write(ByteBuffer.wrap("World".getBytes())); + } + + File physicalFile = ciphertextFs.folder("d").folders().findAny().get().folders().findAny().get().files().findAny().get(); + Assert.assertTrue(physicalFile.exists()); + + // read test content from decrypted file + try (ReadableFile readable = cleartextFs.file("test1.txt").openReadable()) { + ByteBuffer buf1 = ByteBuffer.allocate(5); + readable.read(buf1); + buf1.flip(); + Assert.assertEquals("Hello", new String(buf1.array(), 0, buf1.remaining())); + ByteBuffer buf2 = ByteBuffer.allocate(10); + readable.read(buf2); + buf2.flip(); + Assert.assertArrayEquals(" World".getBytes(), Arrays.copyOfRange(buf2.array(), 0, buf2.remaining())); + } + } + + @Test + public void testRandomAccess() { + File cleartextFile = cleartextFs.file("test"); + try (WritableFile writable = cleartextFile.openWritable()) { + ByteBuffer buf = ByteBuffer.allocate(25000); + for (int i = 0; i < 40; i++) { // 40 * 25k = 1M + buf.clear(); + Arrays.fill(buf.array(), (byte) i); + writable.write(buf); + } + } + + Folder ciphertextRootFolder = ciphertextFs.folder("d").folders().findAny().get().folders().findAny().get(); + Assert.assertTrue(ciphertextRootFolder.exists()); + File ciphertextFile = ciphertextRootFolder.files().findAny().get(); + Assert.assertTrue(ciphertextFile.exists()); + + try (ReadableFile readable = cleartextFile.openReadable()) { + ByteBuffer buf = ByteBuffer.allocate(1); + for (int i = 0; i < 40; i++) { + buf.clear(); + readable.position(i * 25000 + (long) Math.random() * 24999); // "random access", told you so. + readable.read(buf); + buf.flip(); + Assert.assertEquals(i, buf.get()); + } + } + } + +} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/DirectoryPrinter.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/DirectoryPrinter.java deleted file mode 100644 index 53e6b6c9b..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/DirectoryPrinter.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Sebastian Stenzel and others. - * This file is licensed under the terms of the MIT license. - * See the LICENSE.txt file for more info. - * - * Contributors: - * Sebastian Stenzel - initial API and implementation - *******************************************************************************/ -package org.cryptomator.filesystem.crypto; - -import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor; - -import org.cryptomator.filesystem.Folder; - -public final class DirectoryPrinter { - - private DirectoryPrinter() { - } - - public static String print(Folder rootFolder) { - StringBuilder result = new StringBuilder(); - StringBuilder indentation = new StringBuilder(); - fileSystemVisitor() // - .beforeFolder(folder -> { - result.append(indentation).append(folder.name()).append("/\n"); - indentation.append(" "); - }) // - .afterFolder(folder -> { - indentation.delete(indentation.length() - 2, indentation.length()); - }).forEachFile(file -> { - result.append(indentation).append(file.name()).append('\n'); - }) // - .visit(rootFolder); - return result.toString(); - } - -} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/EncryptAndShortenIntegrationTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/EncryptAndShortenIntegrationTest.java deleted file mode 100644 index af2c2f3dd..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/EncryptAndShortenIntegrationTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Sebastian Stenzel and others. - * This file is licensed under the terms of the MIT license. - * See the LICENSE.txt file for more info. - * - * Contributors: - * Sebastian Stenzel - initial API and implementation - *******************************************************************************/ -package org.cryptomator.filesystem.crypto; - -import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.function.Predicate; - -import org.cryptomator.crypto.engine.Cryptor; -import org.cryptomator.crypto.engine.impl.TestCryptorImplFactory; -import org.cryptomator.filesystem.File; -import org.cryptomator.filesystem.FileSystem; -import org.cryptomator.filesystem.Folder; -import org.cryptomator.filesystem.Node; -import org.cryptomator.filesystem.ReadableFile; -import org.cryptomator.filesystem.WritableFile; -import org.cryptomator.filesystem.blacklisting.BlacklistingFileSystem; -import org.cryptomator.filesystem.inmem.InMemoryFileSystem; -import org.cryptomator.filesystem.shortening.ShorteningFileSystem; -import org.junit.Assert; -import org.junit.Test; - -public class EncryptAndShortenIntegrationTest { - - // private static final Logger LOG = LoggerFactory.getLogger(EncryptAndShortenIntegrationTest.class); - - @Test - public void testEncryptionOfLongFolderNames() { - final FileSystem physicalFs = new InMemoryFileSystem(); - final Predicate isMetadataFolder = (Node node) -> node.equals(physicalFs.folder("m")); - final FileSystem metadataHidingFs = new BlacklistingFileSystem(physicalFs, isMetadataFolder); - final FileSystem shorteningFs = new ShorteningFileSystem(metadataHidingFs, physicalFs.folder("m"), 70); - - final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl(); - cryptor.randomizeMasterkey(); - final FileSystem fs = new CryptoFileSystem(shorteningFs, cryptor, "foo"); - fs.create(); - final Folder shortFolder = fs.folder("normal folder name"); - shortFolder.create(); - final Folder longFolder = fs.folder("this will be a long filename after encryption"); - longFolder.create(); - - // on the first (physical) layer all files including metadata files are visible: - // the long name will produce a metadata file on the physical layer: - // LOG.debug("Physical file system:\n" + DirectoryPrinter.print(physicalFs)); - Assert.assertEquals(1, physicalFs.folder("m").folders().count()); - Assert.assertTrue(physicalFs.folder("m").exists()); - - // on the second (blacklisting) layer we hide the metadata folder: - // LOG.debug("Filtered files:\n" + DirectoryPrinter.print(metadataHidingFs)); - Assert.assertEquals(1, metadataHidingFs.folders().count()); // only "d", no "m". - - // on the third layer all .lng files are resolved to their actual names: - // LOG.debug("Unlimited filename length:\n" + DirectoryPrinter.print(shorteningFs)); - fileSystemVisitor() // - .forEachNode(node -> { - Assert.assertFalse(node.name().endsWith(".lng")); - }) // - .visit(shorteningFs); - - // on the fourth (cleartext) layer we have cleartext names on the root level: - // LOG.debug("Cleartext files:\n" + DirectoryPrinter.print(fs)); - Assert.assertArrayEquals(new String[] {"normal folder name", "this will be a long filename after encryption"}, fs.folders().map(Node::name).sorted().toArray()); - } - - @Test - public void testEncryptionAndDecryptionOfFiles() { - final FileSystem physicalFs = new InMemoryFileSystem(); - final FileSystem shorteningFs = new ShorteningFileSystem(physicalFs, physicalFs.folder("m"), 70); - final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl(); - cryptor.randomizeMasterkey(); - final FileSystem fs = new CryptoFileSystem(shorteningFs, cryptor, "foo"); - fs.create(); - - // write test content to encrypted file - try (WritableFile writable = fs.file("test1.txt").openWritable()) { - writable.write(ByteBuffer.wrap("Hello ".getBytes())); - writable.write(ByteBuffer.wrap("World".getBytes())); - } - - File physicalFile = physicalFs.folder("d").folders().findAny().get().folders().findAny().get().files().findAny().get(); - Assert.assertTrue(physicalFile.exists()); - - // read test content from decrypted file - try (ReadableFile readable = fs.file("test1.txt").openReadable()) { - ByteBuffer buf1 = ByteBuffer.allocate(5); - readable.read(buf1); - buf1.flip(); - Assert.assertEquals("Hello", new String(buf1.array(), 0, buf1.remaining())); - ByteBuffer buf2 = ByteBuffer.allocate(10); - readable.read(buf2); - buf2.flip(); - Assert.assertArrayEquals(" World".getBytes(), Arrays.copyOfRange(buf2.array(), 0, buf2.remaining())); - } - } - -} diff --git a/main/filesystem-nameshortening/pom.xml b/main/filesystem-nameshortening/pom.xml index f45096044..2ece68ff2 100644 --- a/main/filesystem-nameshortening/pom.xml +++ b/main/filesystem-nameshortening/pom.xml @@ -42,6 +42,17 @@ com.fasterxml.jackson.core jackson-databind + + + + com.google.dagger + dagger + + + com.google.dagger + dagger-compiler + provided + diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java index 1179605ed..23786805a 100644 --- a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java @@ -6,7 +6,7 @@ import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.Node; -public class BlacklistingFileSystem extends BlacklistingFolder implements FileSystem { +class BlacklistingFileSystem extends BlacklistingFolder implements FileSystem { public BlacklistingFileSystem(Folder root, Predicate hiddenNodes) { super(null, root, hiddenNodes); diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystemFactory.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystemFactory.java new file mode 100644 index 000000000..45296b3cf --- /dev/null +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystemFactory.java @@ -0,0 +1,22 @@ +package org.cryptomator.filesystem.blacklisting; + +import java.util.function.Predicate; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.Node; + +@Singleton +public class BlacklistingFileSystemFactory { + + @Inject + public BlacklistingFileSystemFactory() { + } + + public FileSystem get(Folder root, Predicate hiddenFiles) { + return new BlacklistingFileSystem(root, hiddenFiles); + } +} diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java index 0586d8ff3..0a5f8f1b3 100644 --- a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java @@ -3,7 +3,7 @@ package org.cryptomator.filesystem.shortening; import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; -public class ShorteningFileSystem extends ShorteningFolder implements FileSystem { +class ShorteningFileSystem extends ShorteningFolder implements FileSystem { public ShorteningFileSystem(Folder root, Folder metadataRoot, int threshold) { super(null, root, "", new FilenameShortener(metadataRoot, threshold)); diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactory.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactory.java new file mode 100644 index 000000000..5701bd244 --- /dev/null +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactory.java @@ -0,0 +1,32 @@ +package org.cryptomator.filesystem.shortening; + +import java.util.function.Predicate; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.Node; +import org.cryptomator.filesystem.blacklisting.BlacklistingFileSystemFactory; + +@Singleton +public class ShorteningFileSystemFactory { + + private static final int SHORTENING_THRESHOLD = 140; + private static final String METADATA_FOLDER_NAME = "m"; + + private final BlacklistingFileSystemFactory blacklistingFileSystemFactory; + + @Inject + public ShorteningFileSystemFactory(BlacklistingFileSystemFactory blacklistingFileSystemFactory) { + this.blacklistingFileSystemFactory = blacklistingFileSystemFactory; + } + + public FileSystem get(Folder root) { + final Folder metadataFolder = root.folder(METADATA_FOLDER_NAME); + final Predicate isMetadataFolder = (Node node) -> metadataFolder.equals(node); + final FileSystem metadataHidingFs = blacklistingFileSystemFactory.get(root, isMetadataFolder); + return new ShorteningFileSystem(metadataHidingFs, metadataFolder, SHORTENING_THRESHOLD); + } +} diff --git a/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactoryTest.java b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactoryTest.java new file mode 100644 index 000000000..c191a5bc6 --- /dev/null +++ b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemFactoryTest.java @@ -0,0 +1,59 @@ +package org.cryptomator.filesystem.shortening; + +import java.nio.ByteBuffer; + +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.WritableFile; +import org.cryptomator.filesystem.inmem.InMemoryFileSystem; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ShorteningFileSystemFactoryTest { + + private static final ShorteningFileSystemFactory shorteningFsFactory = DaggerShorteningFileSystemTestComponent.create().shorteningFileSystemFactory(); + private static final String LONG_NAME = "aaaaabbbbbcccccdddddeeeeefffffggggghhhhhiiiiijjjjjkkkkklllll" // + + "mmmmmnnnnnooooopppppqqqqqrrrrrssssstttttuuuuuvvvvvwwwwwxxxxxyyyyyzzzzz" // + + "00000111112222233333444445555566666777778888899999"; + private static final String SHORTENED_FILE = "UYPJJ35VGP2JJ4YISC5S2XQLENLR5MVC.lng"; // base32(sha1(LONG_NAME)) + '.lng' + private static final String CORRESPONDING_METADATA_FILE = "m/UY/PJ/UYPJJ35VGP2JJ4YISC5S2XQLENLR5MVC.lng"; + + private FileSystem physicalFs; + private FileSystem shortenedFs; + + @Before + public void setupFileSystems() { + physicalFs = new InMemoryFileSystem(); + shortenedFs = shorteningFsFactory.get(physicalFs); + shortenedFs.create(); + } + + @Test + public void testFileCreation() { + File file = shortenedFs.file(LONG_NAME); + Assert.assertFalse(file.exists()); + Assert.assertFalse(physicalFs.resolveFile(SHORTENED_FILE).exists()); + Assert.assertFalse(physicalFs.resolveFile(CORRESPONDING_METADATA_FILE).exists()); + try (WritableFile w = file.openWritable()) { + w.write(ByteBuffer.allocate(0)); + } + Assert.assertTrue(file.exists()); + Assert.assertTrue(physicalFs.resolveFile(SHORTENED_FILE).exists()); + Assert.assertTrue(physicalFs.resolveFile(CORRESPONDING_METADATA_FILE).exists()); + } + + @Test + public void testFolderCreation() { + Folder folder = shortenedFs.folder(LONG_NAME); + Assert.assertFalse(folder.exists()); + Assert.assertFalse(physicalFs.resolveFolder(SHORTENED_FILE).exists()); + Assert.assertFalse(physicalFs.resolveFile(CORRESPONDING_METADATA_FILE).exists()); + folder.create(); + Assert.assertTrue(folder.exists()); + Assert.assertTrue(physicalFs.resolveFolder(SHORTENED_FILE).exists()); + Assert.assertTrue(physicalFs.resolveFile(CORRESPONDING_METADATA_FILE).exists()); + } + +} diff --git a/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTestComponent.java b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTestComponent.java new file mode 100644 index 000000000..4c053aa62 --- /dev/null +++ b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTestComponent.java @@ -0,0 +1,13 @@ +package org.cryptomator.filesystem.shortening; + +import javax.inject.Singleton; + +import dagger.Component; + +@Singleton +@Component +public interface ShorteningFileSystemTestComponent { + + ShorteningFileSystemFactory shorteningFileSystemFactory(); + +}