- * Opens this file for reading. - *
- * An implementation guarantees, that per {@link FileSystem} and
- * {@code File} while a {@code ReadableFile} is open no {@link WritableFile}
- * can be open and vice versa. A {@link ReadableFile} is open when returned
- * from this method and not yet closed using {@link ReadableFile#close()}.
- *
- * A limitation to the number of {@code ReadableFiles} is in general not
- * required but may be set by a specific implementation.
- *
- * If a {@link WritableFile} for this {@code File} is open the invocation of
- * this method will block regarding the specified timeout.
- * In addition implementations may block to lock the required IO resources
- * to read the file.
- *
- * @return a {@link ReadableFile} to work with
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while opening the file, the
- * file does not exist or is a directory
- */
- ReadableFile openReadable() throws UncheckedIOException;
-
- /**
- *
- * Opens this file for writing. - *
- * If the file does not exist a new empty file is created. - *
- * An implementation guarantees, that per {@link FileSystem} and
- * {@code File} only one {@link WritableFile} is open at a time. A
- * {@code WritableFile} is open when returned from this method and not yet
- * closed using {@link WritableFile#close()} or
- * {@link WritableFile#delete()}.
- * In addition while a {@code WritableFile} is open no {@link ReadableFile}
- * can be open and vice versa.
- *
- * If a {@code Readable-} or {@code WritableFile} for this {@code File} is
- * open the invocation of this method will block regarding the specified
- * timeout.
- * Creates a {@link Stream} over all child nodes of this {@code Folder}.
- *
- * Note: The {@link Stream} may be lazily populated and thus
- * {@link IOException IOExceptions} may occurs after this method returned.
- * In this case implementors should throw a {@link UncheckedIOException}
- * from any method that produces an {@link IOException}. Thus users should
- * expect {@link UncheckedIOException UncheckedIOExceptions} when invoking
- * methods on the returned {@code Stream}.
- *
- * @return the created {@code Stream}
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while initializing the
- * stream or the {@code Folder} does not exist
- */
- Stream extends Node> children() throws UncheckedIOException;
-
- /**
- *
- * Returns the child {@link Node} in this directory of type {@link File}
- * with the specified name.
- *
- * This operation always returns a {@link File} without checking if the file
- * exists or is a {@link Folder} instead.
- */
- File file(String name) throws UncheckedIOException;
-
- /**
- * Returns a file by resolving a path relative to this folder.
- *
- * @param path A unix-style path, which is always relative to this folder, no matter if it starts with a slash or not. Path must not be empty.
- * @return File with the given path relative to this folder
- * @throws IllegalArgumentException
- * if relativePath is empty
- */
- default File resolveFile(String relativePath) throws UncheckedIOException, IllegalArgumentException {
- return PathResolver.resolveFile(this, relativePath);
- }
-
- /**
- *
- * Returns the child {@link Node} in this directory of type {@link Folder}
- * with the specified name.
- *
- * This operation always returns a {@link Folder} without checking if the
- * folder exists or is a {@link File} instead.
- */
- Folder folder(String name) throws UncheckedIOException;
-
- /**
- * Returns a folder by resolving a path relative to this folder.
- *
- * @param path A unix-style path, which is always relative to this folder, no matter if it starts with a slash or not. Path may be empty.
- * @return Folder with the given path relative to this folder. Returns
- * A node's identity (i.e. {@link #hashCode()} and {@link #equals(Object)}) depends on its parent node and its name (forming the node's path).
- * These properties are meant to be immutable. This means that e.g. moving a node doesn't modify the node's identity but rather transfers properties to the destination node.
- *
- * @author Markus Kreusch
- * @see Folder
- * @see File
- */
-public interface Node {
-
- String name() throws UncheckedIOException;
-
- /**
- * @return Optional parent folder. No parent is present for the root node (see {@link FileSystem#parent()}).
- */
- Optional extends Folder> parent() throws UncheckedIOException;
-
- /**
- * @return
- * Deletes the node if it exists.
- *
- * Does nothing if the node does not exist.
- */
- void delete() throws UncheckedIOException;
-
- /**
- *
- * Determines the last modified date of this node.
- *
- * @returns the last modified date of the file
- */
- Instant lastModified() throws UncheckedIOException;
-
- /**
- *
- * Sets the last modified date of the file.
- *
- * @param lastModified the time to set as creation time
- */
- void setLastModified(Instant lastModified) throws UncheckedIOException;
-
- /**
- *
- * Determines the creation time of this node.
- *
- * Note: Getting the creation time may not be supported by all {@link FileSystem FileSystems}.
- *
- * @returns the creation time of the file or {@link Optional#empty()} if not supported
- */
- default Optional
- * Sets the creation time of this node.
- *
- * Setting the creation time may not be supported by all {@link FileSystem FileSystems}. If the {@code FileSystem} this {@code Node} belongs to does not support the
- * setting the creation time the behavior of this method is unspecified.
- *
- * @param creationTime the time to set as creation time
- */
- default void setCreationTime(Instant creationTime) throws UncheckedIOException {
- throw new UncheckedIOException(new IOException("CreationTime not supported"));
- }
-
- /**
- * @return the {@link FileSystem} this Node belongs to
- */
- default FileSystem fileSystem() {
- return parent() //
- .map(Node::fileSystem) //
- .orElseGet(() -> (FileSystem) this);
- }
-
- default boolean belongsToSameFilesystem(Node other) {
- return fileSystem() == other.fileSystem();
- }
-
-}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/OpenFiles.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/OpenFiles.java
deleted file mode 100644
index 40a775067..000000000
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/OpenFiles.java
+++ /dev/null
@@ -1,71 +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;
-
-import java.io.UncheckedIOException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.stream.Stream;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class OpenFiles implements AutoCloseable {
-
- private final static Logger LOG = LoggerFactory.getLogger(OpenFiles.class);
-
- private final Map
- * Tries to fill the remaining space in the given byte buffer with data from
- * this readable bytes from the current position.
- *
- * May read less bytes if the end of this readable bytes has been reached.
- *
- * @param target
- * the byte buffer to fill
- * @return the number of bytes actually read, or {@code -1} if the end of
- * file has been reached
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while reading from this
- * {@code ReadableBytes}
- */
- @Override
- int read(ByteBuffer target) throws UncheckedIOException;
-
- /**
- *
- * Fast-forwards or rewinds the file to the specified position.
- *
- * Consecutive reads on the file will begin at the new position.
- *
- * @param position
- * the position to set the file to
- * @throws UncheckedIOException
- * if an {@link IOException} occurs
- *
- */
- void position(long position) throws UncheckedIOException;
-
- @Override
- void close() throws UncheckedIOException;
-
-}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java
deleted file mode 100644
index d5080ae79..000000000
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Markus Kreusch
- * This file is licensed under the terms of the MIT license.
- * See the LICENSE.txt file for more info.
- ******************************************************************************/
-package org.cryptomator.filesystem;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.WritableByteChannel;
-
-public interface WritableFile extends WritableByteChannel {
-
- void truncate() throws UncheckedIOException;
-
- /**
- * Writes the data in the given byte buffer to this readable bytes at the
- * current position.
- *
- * @param source
- * the byte buffer to use
- * @return the number of bytes written, always equal to
- * {@code source.remaining()}
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while writing
- */
- @Override
- int write(ByteBuffer source) throws UncheckedIOException;
-
- /**
- *
- * Fast-forwards or rewinds the file to the specified position.
- *
- * Consecutive writes on the file will begin at the new position.
- *
- * If the position is set to a value greater than the current end of file
- * consecutive writes will write data to the given position. The value of
- * all bytes between this position and the previous end of file will be
- * unspecified.
- *
- * @param position
- * the position to set the file to
- * @throws UncheckedIOException
- * if an {@link IOException} occurs
- */
- void position(long position) throws UncheckedIOException;
-
- /**
- *
- * Closes this {@code WritableFile} which finally commits all operations
- * performed on it to the underlying file system.
- *
- * After a {@code WritableFile} has been closed all other operations will
- * throw an {@link UncheckedIOException}.
- *
- * Invoking this method on a {@link WritableFile} which has already been
- * closed does nothing.
- */
- @Override
- void close() throws UncheckedIOException;
-
-}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
deleted file mode 100644
index af119c90c..000000000
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
+++ /dev/null
@@ -1,82 +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.delegating;
-
-import java.io.UncheckedIOException;
-import java.util.Optional;
-
-import org.cryptomator.filesystem.File;
-import org.cryptomator.filesystem.ReadableFile;
-import org.cryptomator.filesystem.WritableFile;
-
-public abstract class DelegatingFile
- * In general the formula to align a requested read with a physical read is
- * In addition implementations may block to lock the required IO resources
- * to read the file.
- *
- * @return a {@link WritableFile} to work with
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while opening the file or
- * the file is a directory
- */
- WritableFile openWritable() throws UncheckedIOException;
-
- default void copyTo(File destination) {
- Copier.copy(this, destination);
- }
-
- /**
- * Moves this file including content to a new location specified by destination.
- */
- void moveTo(File destination) throws UncheckedIOException;
-
-}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java
deleted file mode 100644
index 138fcb95e..000000000
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Markus Kreusch
- * This file is licensed under the terms of the MIT license.
- * See the LICENSE.txt file for more info.
- ******************************************************************************/
-package org.cryptomator.filesystem;
-
-import java.util.Optional;
-
-/**
- * The root folder of a file system.
- *
- * @author Markus Kreusch
- */
-public interface FileSystem extends Folder {
-
- /**
- * @return an empty {@link Optional} because a {@link FileSystem} represents
- * the root {@link Folder} and thus does not have a parent
- */
- @Override
- default Optional extends Folder> parent() {
- return Optional.empty();
- }
-
- Optionalthis if path is empty.
- */
- default Folder resolveFolder(String relativePath) throws UncheckedIOException {
- return PathResolver.resolveFolder(this, relativePath);
- }
-
- /**
- * Creates the directory including all parent directories, if it doesn't
- * exist yet. No effect, if folder already exists.
- *
- * @throws UncheckedIOException
- * if an {@link IOException} occurs while creating the folder or
- * one of its parents
- */
- void create() throws UncheckedIOException;
-
- /**
- * Recusively copies this directory and all its contents to (not into) the
- * given destination, creating nonexisting parent directories. If the target
- * exists it is deleted before performing the copy.
- *
- * @param target
- * Destination folder. Must not be a descendant of this folder.
- */
- default void copyTo(Folder target) throws UncheckedIOException {
- Copier.copy(this, target);
- }
-
- /**
- * Moves this directory and its contents to the given destination. If the
- * target exists it is deleted before performing the move.
- */
- void moveTo(Folder target);
-
- /**
- * @return the result of {@link #children()} filtered to contain only
- * {@link File Files}
- */
- default Stream extends File> files() throws UncheckedIOException {
- return children() //
- .filter(File.class::isInstance) //
- .map(File.class::cast);
- }
-
- /**
- * @return the result of {@link #children()} filtered to contain only
- * {@link Folder Folders}
- */
- default Stream extends Folder> folders() throws UncheckedIOException {
- return children() //
- .filter(Folder.class::isInstance) //
- .map(Folder.class::cast);
- }
-
- /**
- * Recursively checks whether this folder or any subfolder contains the
- * given node.
- *
- * @param node
- * Potential child, grandchild, ...
- * @return true if this folder is an ancestor of the node.
- */
- default boolean isAncestorOf(Node node) {
- if (!node.parent().isPresent()) {
- return false;
- } else if (node.parent().get().equals(this)) {
- return true;
- } else {
- return this.isAncestorOf(node.parent().get());
- }
- }
-
-}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderVisitor.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderVisitor.java
deleted file mode 100644
index c46de4a17..000000000
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderVisitor.java
+++ /dev/null
@@ -1,131 +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;
-
-import static java.lang.String.format;
-
-import java.util.function.Consumer;
-
-public class FolderVisitor {
-
- private final Consumertrue if the node exists.
- */
- boolean exists() throws UncheckedIOException;
-
- /**
- *
- *
- *
- *
- * @param dir The directory from which to resolve the path.
- * @param relativePath The path relative to a given directory.
- * @return The folder with the given path relative to the given dir.
- */
- public static Folder resolveFolder(Folder dir, String relativePath) {
- final String[] fragments = StringUtils.split(relativePath, '/');
- if (ArrayUtils.isEmpty(fragments)) {
- return dir;
- }
- return resolveFolder(dir, Arrays.stream(fragments).iterator());
- }
-
- /**
- * Resolves a relative path (separated by '/') to a file. Besides returning a File, this method is identical to {@link #resolveFile(Folder, String)}.
- *
- * @param dir The directory from which to resolve the path.
- * @param relativePath The path relative to a given directory.
- * @return The file with the given path relative to the given dir.
- * @throws IllegalArgumentException
- * if relativePath is empty, as this path would resolve to the directory itself, which obviously can't be a file.
- */
- public static File resolveFile(Folder dir, String relativePath) {
- final String[] fragments = StringUtils.split(relativePath, '/');
- if (ArrayUtils.isEmpty(fragments)) {
- throw new IllegalArgumentException("Empty relativePath");
- }
- final Folder folder = resolveFolder(dir, Arrays.stream(fragments).limit(fragments.length - 1).iterator());
- final String filename = fragments[fragments.length - 1];
- return folder.file(filename);
- }
-
- private static Folder resolveFolder(Folder dir, Iterator
- *
- *
- *
- * dir
- * path
- * result
- *
- *
- * /foo/bar
- * foo/bar
- * /foo/bar/foo/bar
- *
- *
- * /foo/bar
- * ../baz
- * /foo/baz
- *
- *
- * /foo/bar
- * ./foo/..
- * /foo/bar
- *
- *
- * /foo/bar
- * /
- * /foo/bar
- *
- *
- * /foo/bar
- *
- * /foo/bar
- *
- *
- *
- * /foo/bar
- * ../../..
- * Exception
- *
- * DaggerCryptoFileSystemTestComponent.builder().cryptoEngineModule(new CryptoEngineTestModule()).build()
- *
- */
-@Singleton
-@Component(modules = CryptoEngineModule.class)
-public interface CryptoFileSystemTestComponent {
-
- CryptoFileSystemFactory cryptoFileSystemFactory();
-
- ShorteningFileSystemFactory shorteningFileSystemFactory();
-
-}
diff --git a/main/filesystem-crypto-integration-tests/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemIntegrationTest.java b/main/filesystem-crypto-integration-tests/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemIntegrationTest.java
deleted file mode 100644
index 9d8b26869..000000000
--- a/main/filesystem-crypto-integration-tests/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemIntegrationTest.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 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 java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.Future;
-
-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;
-import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CryptoFileSystemIntegrationTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(CryptoFileSystemIntegrationTest.class);
-
- private final CryptoFileSystemTestComponent cryptoFsComp = DaggerCryptoFileSystemTestComponent.builder().cryptoEngineModule(new CryptoEngineTestModule()).build();
-
- private CryptoFileSystemDelegate cryptoDelegate;
- private FileSystem ciphertextFs;
- private FileSystem cleartextFs;
-
- @Before
- public void setupFileSystems() {
- cryptoDelegate = Mockito.mock(CryptoFileSystemDelegate.class);
- ciphertextFs = new InMemoryFileSystem();
- FileSystem shorteningFs = cryptoFsComp.shorteningFileSystemFactory().get(ciphertextFs);
- cryptoFsComp.cryptoFileSystemFactory().initializeNew(shorteningFs, "TopSecret");
- cleartextFs = cryptoFsComp.cryptoFileSystemFactory().unlockExisting(shorteningFs, "TopSecret", cryptoDelegate);
- }
-
- @Test(timeout = 1000)
- public void testVaultStructureInitializationAndBackupBehaviour() throws UncheckedIOException, IOException {
- final FileSystem physicalFs = new InMemoryFileSystem();
- final File masterkeyFile = physicalFs.file("masterkey.cryptomator");
- final File masterkeyBkupFile = physicalFs.file("masterkey.cryptomator.bkup");
- final Folder physicalDataRoot = physicalFs.folder("d");
- Assert.assertFalse(masterkeyFile.exists());
- Assert.assertFalse(masterkeyBkupFile.exists());
- Assert.assertFalse(physicalDataRoot.exists());
-
- cryptoFsComp.cryptoFileSystemFactory().initializeNew(physicalFs, "asd");
- Assert.assertTrue(masterkeyFile.exists());
- Assert.assertFalse(masterkeyBkupFile.exists());
- Assert.assertFalse(physicalDataRoot.exists());
-
- @SuppressWarnings("unused")
- final FileSystem cryptoFs = cryptoFsComp.cryptoFileSystemFactory().unlockExisting(physicalFs, "asd", cryptoDelegate);
- Assert.assertTrue(masterkeyBkupFile.exists());
- Assert.assertTrue(physicalDataRoot.exists());
- Assert.assertEquals(3, physicalFs.children().count()); // d + masterkey.cryptomator + masterkey.cryptomator.bkup
- Assert.assertEquals(1, physicalDataRoot.folders().count()); // ROOT directory
- }
-
- @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 testForcedDecryptionOfManipulatedFile() {
- // write test content to encrypted file
- try (WritableFile writable = cleartextFs.file("test1.txt").openWritable()) {
- writable.write(ByteBuffer.wrap("Hello World".getBytes()));
- }
-
- File physicalFile = ciphertextFs.folder("d").folders().findAny().get().folders().findAny().get().files().findAny().get();
- Assert.assertTrue(physicalFile.exists());
-
- // toggle last bit
- try (WritableFile writable = physicalFile.openWritable(); ReadableFile readable = physicalFile.openReadable()) {
- ByteBuffer buf = ByteBuffer.allocate((int) physicalFile.size());
- readable.read(buf);
- buf.array()[buf.limit() - 1] ^= 0x01;
- buf.flip();
- writable.write(buf);
- }
-
- // whitelist
- Mockito.when(cryptoDelegate.shouldSkipAuthentication("/test1.txt")).thenReturn(true);
-
- // read test content from decrypted file
- try (ReadableFile readable = cleartextFs.file("test1.txt").openReadable()) {
- ByteBuffer buf = ByteBuffer.allocate(11);
- readable.read(buf);
- buf.flip();
- Assert.assertArrayEquals("Hello World".getBytes(), buf.array());
- }
- }
-
- @Test(timeout = 20000) // assuming a minimum speed of 10mb/s during encryption and decryption 20s should be enough
- public void testEncryptionAndDecryptionSpeed() throws InterruptedException, IOException {
- File file = cleartextFs.file("benchmark.test");
-
- final long encStart = System.nanoTime();
- try (WritableFile writable = file.openWritable()) {
- final ByteBuffer cleartext = ByteBuffer.allocate(100000); // 100k
- for (int i = 0; i < 1000; i++) { // 100M total
- cleartext.rewind();
- writable.write(cleartext);
- }
- }
- final long encEnd = System.nanoTime();
- LOG.debug("Encryption of 100M took {}ms", (encEnd - encStart) / 1000 / 1000);
-
- final long decStart = System.nanoTime();
- try (ReadableFile readable = file.openReadable()) {
- final ByteBuffer cleartext = ByteBuffer.allocate(100000); // 100k
- for (int i = 0; i < 1000; i++) { // 100M total
- cleartext.clear();
- readable.read(cleartext);
- cleartext.flip();
- Assert.assertEquals(cleartext.get(), 0x00);
- }
- }
- final long decEnd = System.nanoTime();
- LOG.debug("Decryption of 100M took {}ms", (decEnd - decStart) / 1000 / 1000);
-
- file.delete();
- }
-
- @Test
- public void testRandomAccessOnLastBlock() {
- // prepare test data:
- ByteBuffer testData = ByteBuffer.allocate(16000 * Integer.BYTES); // < 64kb
- for (int i = 0; i < 16000; i++) {
- testData.putInt(i);
- }
-
- // write test data to file:
- File cleartextFile = cleartextFs.file("test");
- try (WritableFile writable = cleartextFile.openWritable()) {
- testData.flip();
- writable.write(testData);
- }
-
- // read last block:
- try (ReadableFile readable = cleartextFile.openReadable()) {
- ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
- buf.clear();
- readable.position(15999 * Integer.BYTES);
- readable.read(buf);
- buf.flip();
- Assert.assertEquals(15999, buf.getInt());
- }
- }
-
- @Test
- public void testSequentialRandomAccess() {
- // prepare test data:
- ByteBuffer testData = ByteBuffer.allocate(1_000_000 * Integer.BYTES); // = 4MB
- for (int i = 0; i < 1000000; i++) {
- testData.putInt(i);
- }
-
- // write test data to file:
- File cleartextFile = cleartextFs.file("test");
- try (WritableFile writable = cleartextFile.openWritable()) {
- testData.flip();
- writable.write(testData);
- }
-
- // shuffle our test positions:
- Listfalse. Should be true by default.
- * @return A possibly new FileContentDecryptor instance which is capable of decrypting ciphertexts associated with the given file header.
- */
- FileContentDecryptor createFileContentDecryptor(ByteBuffer header, long firstCiphertextByte, boolean authenticate) throws IllegalArgumentException, AuthenticationFailedException;
-
- /**
- * @param header The full fixed-length header of an encrypted file or {@link Optional#empty()}. The caller is required to pass the exact amount of bytes returned by {@link #getHeaderSize()}.
- * If the header is empty, a new one will be created by the returned encryptor.
- * @param firstCleartextByte Position of the first cleartext byte passed to the encryptor. If the encryptor can not fast-forward to the requested byte, an exception is thrown.
- * If firstCiphertextByte is an invalid starting point, i.e. doesn't align with the encryptors internal block size, an IllegalArgumentException will be thrown.
- * @return A possibly new FileContentEncryptor instance which is capable of encrypting cleartext associated with the given file header.
- */
- FileContentEncryptor createFileContentEncryptor(OptionalN, larger than 1, a power of 2 and less than 2^(128 * costParam / 8)
- * @param blockSize Block size r
- * @param keyLengthInBytes Key output length dkLen
- * @return Derived key
- * @see RFC Draft
- */
- public static byte[] scrypt(CharSequence passphrase, byte[] salt, int costParam, int blockSize, int keyLengthInBytes) {
- // This is an attempt to get the password bytes without copies of the password being created in some dark places inside the JVM:
- final ByteBuffer buf = UTF_8.encode(CharBuffer.wrap(passphrase));
- final byte[] pw = new byte[buf.remaining()];
- buf.get(pw);
- try {
- return SCrypt.generate(pw, salt, costParam, blockSize, 1, keyLengthInBytes);
- } finally {
- Arrays.fill(pw, (byte) 0); // overwrite bytes
- buf.rewind(); // just resets markers
- buf.put(pw); // this is where we overwrite the actual bytes
- }
- }
-
-}
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/ThreadLocalAesCtrCipher.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/ThreadLocalAesCtrCipher.java
deleted file mode 100644
index f54676282..000000000
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/ThreadLocalAesCtrCipher.java
+++ /dev/null
@@ -1,36 +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.crypto.engine.impl;
-
-import java.security.NoSuchAlgorithmException;
-
-import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
-
-final class ThreadLocalAesCtrCipher {
-
- private ThreadLocalAesCtrCipher() {
- }
-
- private static final String AES_CTR = "AES/CTR/NoPadding";
- private static final ThreadLocalfloor(x / blockSize) * blockSize
- * For example blockSize=10 result in the following block-aligned read/write attempts:
- *
- *
- *
- *
- */
-class BlockAlignedFileSystem extends BlockAlignedFolder implements DelegatingFileSystem {
-
- public BlockAlignedFileSystem(Folder delegate, int blockSize) {
- super(null, delegate, blockSize);
- }
-
- @Override
- public Folder getDelegate() {
- return delegate;
- }
-
-}
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFileSystemFactory.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFileSystemFactory.java
deleted file mode 100644
index f98efb479..000000000
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFileSystemFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 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.crypto.engine.impl.Constants.PAYLOAD_SIZE;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-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, PAYLOAD_SIZE);
- }
-}
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFolder.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFolder.java
deleted file mode 100644
index 5a930ad6a..000000000
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/BlockAlignedFolder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015, 2016 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 org.cryptomator.filesystem.File;
-import org.cryptomator.filesystem.Folder;
-import org.cryptomator.filesystem.delegating.DelegatingFolder;
-
-class BlockAlignedFolder extends DelegatingFolder
- *
- *
- *
- * Requested Read
- * Physical Read
- *
- * 0
- * 0
- *
- * 5
- * 0
- *
- * 9
- * 0
- *
- * 10
- * 10
- *
- * 11
- * 10
- *
- *
- * 35
- * 30
- * true for data recovery purposes.
- *
- * @param cleartextPath Unix-style vault-relative path
- * @return Must always default to false, except when authentication should be skipped.
- */
- boolean shouldSkipAuthentication(String cleartextPath);
-
-}
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
deleted file mode 100644
index fad864529..000000000
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystemFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 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.crypto.Constants.MASTERKEY_FILENAME;
-
-import java.io.UncheckedIOException;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.cryptomator.crypto.engine.Cryptor;
-import org.cryptomator.crypto.engine.InvalidPassphraseException;
-import org.cryptomator.filesystem.FileSystem;
-import org.cryptomator.filesystem.Folder;
-
-@Singleton
-public class CryptoFileSystemFactory {
-
- private final Masterkeys masterkeys;
- private final BlockAlignedFileSystemFactory blockAlignedFileSystemFactory;
-
- @Inject
- public CryptoFileSystemFactory(Masterkeys masterkeys, BlockAlignedFileSystemFactory blockAlignedFileSystemFactory) {
- this.masterkeys = masterkeys;
- this.blockAlignedFileSystemFactory = blockAlignedFileSystemFactory;
- }
-
- public boolean isValidVaultStructure(Folder vaultLocation) {
- return vaultLocation.file(MASTERKEY_FILENAME).exists();
- }
-
- public void initializeNew(Folder vaultLocation, CharSequence passphrase) {
- masterkeys.initialize(vaultLocation, passphrase);
- }
-
- public FileSystem unlockExisting(Folder vaultLocation, CharSequence passphrase, CryptoFileSystemDelegate delegate) throws InvalidPassphraseException {
- final Cryptor cryptor = masterkeys.decrypt(vaultLocation, passphrase);
- masterkeys.backup(vaultLocation);
- final FileSystem cryptoFs = new CryptoFileSystem(vaultLocation, cryptor, delegate, passphrase);
- return blockAlignedFileSystemFactory.get(cryptoFs);
- }
-
- public void changePassphrase(Folder vaultLocation, CharSequence oldPassphrase, CharSequence newPassphrase) throws InvalidPassphraseException {
- masterkeys.backup(vaultLocation);
- try {
- masterkeys.changePassphrase(vaultLocation, oldPassphrase, newPassphrase);
- // At this point the backup is still using the old password.
- // It will be changed as soon as the user unlocks the vault the next time.
- // This way he can still restore the old password, if he doesn't remember the new one.
- } catch (UncheckedIOException e) {
- masterkeys.restoreBackup(vaultLocation);
- }
- }
-}
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
deleted file mode 100644
index af9698d12..000000000
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015, 2016 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 java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.lang3.StringUtils.removeStart;
-import static org.cryptomator.filesystem.crypto.Constants.DIR_PREFIX;
-
-import java.io.FileNotFoundException;
-import java.io.UncheckedIOException;
-import java.nio.file.FileAlreadyExistsException;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Predicate;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.StringUtils;
-import org.cryptomator.common.LazyInitializer;
-import org.cryptomator.common.WeakValuedCache;
-import org.cryptomator.common.streams.AutoClosingStream;
-import org.cryptomator.crypto.engine.CryptoException;
-import org.cryptomator.crypto.engine.Cryptor;
-import org.cryptomator.filesystem.Deleter;
-import org.cryptomator.filesystem.File;
-import org.cryptomator.filesystem.Folder;
-import org.cryptomator.filesystem.Node;
-import org.cryptomator.io.FileContents;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class CryptoFolder extends CryptoNode implements Folder {
-
- private static final Logger LOG = LoggerFactory.getLogger(CryptoFolder.class);
- private final WeakValuedCache