mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-19 14:34:20 +00:00
separated filename shortening layer from metadata hiding layer
This commit is contained in:
+3
-20
@@ -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.");
|
||||
|
||||
+20
-13
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user