From 951a02a9a582c4efb8e7bffa04eba3c2af6a3cff Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 19 Dec 2015 11:26:35 +0100 Subject: [PATCH] cleanup --- .../cryptomator/filesystem/ReadableBytes.java | 2 +- .../crypto/engine/FileContentCryptor.java | 11 +++---- .../crypto/engine/FileContentDecryptor.java | 2 +- .../crypto/engine/FileContentEncryptor.java | 2 +- .../crypto/engine/FilenameCryptor.java | 4 +-- .../crypto/engine/impl/CryptorImpl.java | 30 +++++++++---------- .../engine/impl/FileContentCryptorImpl.java | 17 ++--------- .../engine/impl/FilenameCryptorImpl.java | 13 -------- .../crypto/engine/impl/TheDestroyer.java | 28 ----------------- .../crypto/fs/CryptoReadableFile.java | 13 ++++---- .../crypto/fs/CryptoWritableFile.java | 2 +- .../crypto/engine/NoFileContentCryptor.java | 4 +-- .../filesystem/inmem/InMemoryFile.java | 7 +++-- .../cryptomator/filesystem/nio/NioFile.java | 2 +- 14 files changed, 42 insertions(+), 95 deletions(-) delete mode 100644 main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/TheDestroyer.java diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java index 315d60f28..bc38a81a2 100644 --- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java +++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java @@ -41,6 +41,6 @@ public interface ReadableBytes { * if an {@link IOException} occurs while reading from this * {@code ReadableBytes} */ - void read(ByteBuffer target, int position) throws UncheckedIOException; + void read(ByteBuffer target, long position) throws UncheckedIOException; } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentCryptor.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentCryptor.java index 2ad156548..c00bcca12 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentCryptor.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentCryptor.java @@ -3,9 +3,10 @@ package org.cryptomator.crypto.engine; import java.nio.ByteBuffer; import java.util.Optional; -import javax.security.auth.Destroyable; - -public interface FileContentCryptor extends Destroyable { +/** + * Factory for stateful {@link FileContentEncryptor Encryptor}/{@link FileContentDecryptor Decryptor} instances, that are capable of processing data exactly once. + */ +public interface FileContentCryptor { /** * @return The fixed number of bytes of the file header. The header length is implementation-specific. @@ -16,13 +17,13 @@ public interface FileContentCryptor extends Destroyable { * @param header The full fixed-length header of an encrypted file. The caller is required to pass the exact amount of bytes returned by {@link #getHeaderSize()}. * @return A possibly new FileContentDecryptor instance which is capable of decrypting ciphertexts associated with the given file header. */ - FileContentDecryptor getFileContentDecryptor(ByteBuffer header); + FileContentDecryptor createFileContentDecryptor(ByteBuffer header); /** * @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. * @return A possibly new FileContentEncryptor instance which is capable of encrypting cleartext associated with the given file header. */ - FileContentEncryptor getFileContentEncryptor(Optional header); + FileContentEncryptor createFileContentEncryptor(Optional header); } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentDecryptor.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentDecryptor.java index d88b5e495..dc334cc44 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentDecryptor.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentDecryptor.java @@ -4,7 +4,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.BlockingQueue; /** - * Not necessarily thread-safe. + * Stateful, thus not thread-safe. */ public interface FileContentDecryptor { diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentEncryptor.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentEncryptor.java index 4e180e2cd..76928c4b6 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentEncryptor.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentEncryptor.java @@ -4,7 +4,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.BlockingQueue; /** - * Not necessarily thread-safe. + * Stateful, thus not thread-safe. */ public interface FileContentEncryptor { diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java index 38e4c3c19..595ebe1e4 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java @@ -8,15 +8,13 @@ *******************************************************************************/ package org.cryptomator.crypto.engine; -import javax.security.auth.Destroyable; - /** * Provides deterministic encryption capabilities as filenames must not change on subsequent encryption attempts, * otherwise each change results in major directory structure changes which would be a terrible idea for cloud storage encryption. * * @see Wikipedia on deterministic encryption */ -public interface FilenameCryptor extends Destroyable { +public interface FilenameCryptor { /** * @return constant length string, that is unlikely to collide with any other name. diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptorImpl.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptorImpl.java index bb2714bb7..e5cd54f20 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptorImpl.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptorImpl.java @@ -18,6 +18,7 @@ import java.util.concurrent.atomic.AtomicReference; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.security.auth.DestroyFailedException; +import javax.security.auth.Destroyable; import org.cryptomator.crypto.engine.Cryptor; import org.cryptomator.crypto.engine.FileContentCryptor; @@ -52,12 +53,11 @@ public class CryptorImpl implements Cryptor { if (existingCryptor != null) { return existingCryptor; } else { - final FilenameCryptorImpl newCryptor = new FilenameCryptorImpl(encryptionKey, macKey); + final FilenameCryptor newCryptor = new FilenameCryptorImpl(encryptionKey, macKey); if (filenameCryptor.compareAndSet(null, newCryptor)) { return newCryptor; } else { // CAS failed: other thread set an object - newCryptor.destroy(); return filenameCryptor.get(); } } @@ -70,12 +70,11 @@ public class CryptorImpl implements Cryptor { if (existingCryptor != null) { return existingCryptor; } else { - final FileContentCryptorImpl newCryptor = new FileContentCryptorImpl(encryptionKey, macKey); + final FileContentCryptor newCryptor = new FileContentCryptorImpl(encryptionKey, macKey); if (fileContentCryptor.compareAndSet(null, newCryptor)) { return newCryptor; } else { // CAS failed: other thread set an object - newCryptor.destroy(); return fileContentCryptor.get(); } } @@ -162,22 +161,21 @@ public class CryptorImpl implements Cryptor { @Override public void destroy() throws DestroyFailedException { - TheDestroyer.destroyQuietly(encryptionKey); - TheDestroyer.destroyQuietly(macKey); - if (filenameCryptor.get() != null) { - TheDestroyer.destroyQuietly(getFilenameCryptor()); - } - if (fileContentCryptor.get() != null) { - TheDestroyer.destroyQuietly(getFileContentCryptor()); - } + destroyQuietly(encryptionKey); + destroyQuietly(macKey); } @Override public boolean isDestroyed() { - return encryptionKey.isDestroyed() // - && macKey.isDestroyed() // - && (filenameCryptor.get() == null || filenameCryptor.get().isDestroyed()) // - && (fileContentCryptor.get() == null || fileContentCryptor.get().isDestroyed()); + return encryptionKey.isDestroyed() && macKey.isDestroyed(); + } + + private void destroyQuietly(Destroyable d) { + try { + d.destroy(); + } catch (DestroyFailedException e) { + // ignore + } } } 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 3afa30654..3448c3427 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 @@ -28,26 +28,13 @@ class FileContentCryptorImpl implements FileContentCryptor { } @Override - public FileContentDecryptor getFileContentDecryptor(ByteBuffer header) { + public FileContentDecryptor createFileContentDecryptor(ByteBuffer header) { throw new UnsupportedOperationException("Method not implemented"); } @Override - public FileContentEncryptor getFileContentEncryptor(Optional header) { + public FileContentEncryptor createFileContentEncryptor(Optional header) { throw new UnsupportedOperationException("Method not implemented"); } - /* ======================= destruction ======================= */ - - @Override - public void destroy() { - TheDestroyer.destroyQuietly(encryptionKey); - TheDestroyer.destroyQuietly(macKey); - } - - @Override - public boolean isDestroyed() { - return encryptionKey.isDestroyed() && macKey.isDestroyed(); - } - } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java index 508f39f27..cd6695b3d 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java @@ -84,17 +84,4 @@ class FilenameCryptorImpl implements FilenameCryptor { } } - /* ======================= destruction ======================= */ - - @Override - public void destroy() { - TheDestroyer.destroyQuietly(encryptionKey); - TheDestroyer.destroyQuietly(macKey); - } - - @Override - public boolean isDestroyed() { - return encryptionKey.isDestroyed() && macKey.isDestroyed(); - } - } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/TheDestroyer.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/TheDestroyer.java deleted file mode 100644 index e16ddda64..000000000 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/TheDestroyer.java +++ /dev/null @@ -1,28 +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 javax.security.auth.DestroyFailedException; -import javax.security.auth.Destroyable; - -final class TheDestroyer { - - private TheDestroyer() { - - } - - public static void destroyQuietly(Destroyable d) { - try { - d.destroy(); - } catch (DestroyFailedException e) { - // ignore - } - } - -} diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoReadableFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoReadableFile.java index f201eb544..45e2b1d9e 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoReadableFile.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoReadableFile.java @@ -15,19 +15,20 @@ import org.cryptomator.io.ByteBuffers; class CryptoReadableFile implements ReadableFile { private static final int READ_BUFFER_SIZE = 32 * 1024 + 32; // aligned with encrypted chunk size + MAC size + private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); private final ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); private final FileContentDecryptor decryptor; private final ReadableFile file; private Future readAheadTask; - private ByteBuffer bufferedCleartext; + private ByteBuffer bufferedCleartext = EMPTY_BUFFER; public CryptoReadableFile(FileContentCryptor cryptor, ReadableFile file) { final int headerSize = cryptor.getHeaderSize(); final ByteBuffer header = ByteBuffer.allocate(headerSize); file.read(header, 0); header.flip(); - this.decryptor = cryptor.getFileContentDecryptor(header); + this.decryptor = cryptor.createFileContentDecryptor(header); this.file = file; this.prepareReadAtPhysicalPosition(headerSize + 0); } @@ -35,6 +36,7 @@ class CryptoReadableFile implements ReadableFile { private void prepareReadAtPhysicalPosition(long pos) { if (readAheadTask != null) { readAheadTask.cancel(true); + bufferedCleartext = EMPTY_BUFFER; decryptor.cleartext().clear(); } readAheadTask = executorService.submit(new Reader(pos)); @@ -53,7 +55,7 @@ class CryptoReadableFile implements ReadableFile { } private void bufferCleartext() throws InterruptedException { - if (bufferedCleartext == null || !bufferedCleartext.hasRemaining()) { + if (!bufferedCleartext.hasRemaining()) { bufferedCleartext = decryptor.cleartext().take(); } } @@ -64,7 +66,7 @@ class CryptoReadableFile implements ReadableFile { } @Override - public void read(ByteBuffer target, int position) { + public void read(ByteBuffer target, long position) { throw new UnsupportedOperationException("Partial read not implemented yet."); } @@ -89,8 +91,7 @@ class CryptoReadableFile implements ReadableFile { @Override public Void call() { - // TODO change to file.read(ByteBuffer, long) - file.read(ByteBuffer.allocate(0), (int) startpos); + file.read(EMPTY_BUFFER, startpos); int bytesRead = -1; do { ByteBuffer ciphertext = ByteBuffer.allocate(READ_BUFFER_SIZE); diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoWritableFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoWritableFile.java index f537b102f..591d29f1d 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoWritableFile.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/fs/CryptoWritableFile.java @@ -23,7 +23,7 @@ class CryptoWritableFile implements WritableFile { private final Future writeTask; public CryptoWritableFile(FileContentCryptor cryptor, WritableFile file) { - this.encryptor = cryptor.getFileContentEncryptor(Optional.empty()); + this.encryptor = cryptor.createFileContentEncryptor(Optional.empty()); this.file = file; writeHeader(); this.writeTask = executorService.submit(new Writer()); diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFileContentCryptor.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFileContentCryptor.java index 5a12a7d54..2e28ec236 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFileContentCryptor.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFileContentCryptor.java @@ -13,7 +13,7 @@ class NoFileContentCryptor implements FileContentCryptor { } @Override - public FileContentDecryptor getFileContentDecryptor(ByteBuffer header) { + public FileContentDecryptor createFileContentDecryptor(ByteBuffer header) { if (header.remaining() != getHeaderSize()) { throw new IllegalArgumentException("Invalid header size."); } @@ -21,7 +21,7 @@ class NoFileContentCryptor implements FileContentCryptor { } @Override - public FileContentEncryptor getFileContentEncryptor(Optional header) { + public FileContentEncryptor createFileContentEncryptor(Optional header) { return new Encryptor(); } diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java index 621e17606..02f92084a 100644 --- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java +++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java @@ -57,8 +57,11 @@ class InMemoryFile extends InMemoryNode implements File, ReadableFile, WritableF } @Override - public void read(ByteBuffer target, int position) { - content.position(position); + public void read(ByteBuffer target, long position) { + if (position > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Can not keep files of virtually unlimited size in memory."); + } + content.position((int) position); ByteBuffers.copy(content, target); } diff --git a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFile.java b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFile.java index 7aa1608ef..722dff6da 100644 --- a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFile.java +++ b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFile.java @@ -44,7 +44,7 @@ class NioFile extends NioNode implements File { } @Override - public void read(ByteBuffer target, int position) throws UncheckedIOException { + public void read(ByteBuffer target, long position) throws UncheckedIOException { } @Override