separated filename shortening layer from metadata hiding layer

This commit is contained in:
Sebastian Stenzel
2015-12-29 16:24:42 +01:00
parent aa89f60c2f
commit 9385c3bf6d
20 changed files with 370 additions and 317 deletions
@@ -14,13 +14,13 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.DestroyFailedException;
import javax.security.auth.Destroyable;
import org.cryptomator.common.LazyInitializer;
import org.cryptomator.crypto.engine.Cryptor;
import org.cryptomator.crypto.engine.FileContentCryptor;
import org.cryptomator.crypto.engine.FilenameCryptor;
@@ -67,7 +67,7 @@ public class CryptorImpl implements Cryptor {
@Override
public FilenameCryptor getFilenameCryptor() {
assertKeysExist();
return initializeLazily(filenameCryptor, () -> {
return LazyInitializer.initializeLazily(filenameCryptor, () -> {
return new FilenameCryptorImpl(encryptionKey, macKey);
});
}
@@ -75,28 +75,11 @@ public class CryptorImpl implements Cryptor {
@Override
public FileContentCryptor getFileContentCryptor() {
assertKeysExist();
return initializeLazily(fileContentCryptor, () -> {
return LazyInitializer.initializeLazily(fileContentCryptor, () -> {
return new FileContentCryptorImpl(encryptionKey, macKey, randomSource);
});
}
/**
* threadsafe lazy initialization pattern as proposed on http://stackoverflow.com/a/30247202/4014509
*/
private <T> T initializeLazily(AtomicReference<T> reference, Supplier<T> factory) {
final T existingInstance = reference.get();
if (existingInstance != null) {
return existingInstance;
} else {
final T newInstance = factory.get();
if (reference.compareAndSet(null, newInstance)) {
return newInstance;
} else {
return reference.get();
}
}
}
private void assertKeysExist() {
if (encryptionKey == null || encryptionKey.isDestroyed()) {
throw new IllegalStateException("No or invalid encryptionKey.");
@@ -4,6 +4,7 @@ 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;
@@ -13,20 +14,23 @@ 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.shortening.ShorteningFileSystem;
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);
// private static final Logger LOG = LoggerFactory.getLogger(EncryptAndShortenIntegrationTest.class);
@Test
public void testEncryptionOfLongFolderNames() {
final FileSystem physicalFs = new InMemoryFileSystem();
final FileSystem shorteningFs = new ShorteningFileSystem(physicalFs, physicalFs.folder("m"), 70);
final Predicate<Node> 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");
@@ -36,24 +40,27 @@ public class EncryptAndShortenIntegrationTest {
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));
// 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 layer all .lng files are resolved to their actual
// names:
// LOG.debug("Unlimited filename length:\n" +
// DirectoryPrinter.print(shorteningFs));
// 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 third (cleartext layer) we have cleartext names on the root
// level:
// 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());
Assert.assertArrayEquals(new String[] {"normal folder name", "this will be a long filename after encryption"}, fs.folders().map(Node::name).sorted().toArray());
}
@Test