diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImpl.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImpl.java index b5476a183..a8d0abdd5 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImpl.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImpl.java @@ -11,6 +11,7 @@ package org.cryptomator.crypto.engine.impl; import static org.cryptomator.crypto.engine.impl.FileContentCryptorImpl.CHUNK_SIZE; import static org.cryptomator.crypto.engine.impl.FileContentCryptorImpl.MAC_SIZE; import static org.cryptomator.crypto.engine.impl.FileContentCryptorImpl.NONCE_SIZE; +import static org.cryptomator.crypto.engine.impl.FileContentCryptorImpl.PAYLOAD_SIZE; import java.io.IOException; import java.io.UncheckedIOException; @@ -31,6 +32,7 @@ import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; +import org.apache.commons.codec.binary.Hex; import org.cryptomator.crypto.engine.AuthenticationFailedException; import org.cryptomator.crypto.engine.FileContentCryptor; import org.cryptomator.crypto.engine.FileContentDecryptor; @@ -47,7 +49,7 @@ class FileContentDecryptorImpl implements FileContentDecryptor { private final Supplier hmacSha256; private final FileHeader header; private final boolean authenticate; - private final LongAdder cleartextBytesScheduledForDecryption = new LongAdder(); + private final LongAdder ciphertextBytesScheduledForDecryption = new LongAdder(); private final LongAdder cleartextBytesDecrypted = new LongAdder(); private ByteBuffer ciphertextBuffer = ByteBuffer.allocate(CHUNK_SIZE); private long chunkNumber = 0; @@ -66,13 +68,15 @@ class FileContentDecryptorImpl implements FileContentDecryptor { @Override public void append(ByteBuffer ciphertext) throws InterruptedException { - if (cleartextBytesScheduledForDecryption.sum() >= contentLength()) { - submitEof(); - } else if (ciphertext == FileContentCryptor.EOF) { + long numChunksNeeded = (contentLength() - 1) / PAYLOAD_SIZE + 1; + long numCiphertextBytesNeeded = numChunksNeeded * CHUNK_SIZE; + + if (ciphertext == FileContentCryptor.EOF || ciphertextBytesScheduledForDecryption.sum() >= numCiphertextBytesNeeded) { submitCiphertextBuffer(); submitEof(); } else { - while (ciphertext.hasRemaining() && cleartextBytesScheduledForDecryption.sum() < contentLength()) { + ciphertextBytesScheduledForDecryption.add(ciphertext.remaining()); + while (ciphertext.hasRemaining()) { ByteBuffers.copy(ciphertext, ciphertextBuffer); submitCiphertextBufferIfFull(); } @@ -96,7 +100,6 @@ class FileContentDecryptorImpl implements FileContentDecryptor { private void submitCiphertextBuffer() throws InterruptedException { ciphertextBuffer.flip(); if (ciphertextBuffer.hasRemaining()) { - cleartextBytesScheduledForDecryption.add(ciphertextBuffer.remaining() - MAC_SIZE - NONCE_SIZE); Callable encryptionJob = new DecryptionJob(ciphertextBuffer, chunkNumber++); dataProcessor.submit(encryptionJob); } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java index 0c4e57d07..4cbcd3263 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java @@ -31,7 +31,6 @@ class CryptoWritableFile implements WritableFile { private FileContentEncryptor encryptor; private Future writeTask; - private boolean contentChanged = false; public CryptoWritableFile(FileContentCryptor cryptor, WritableFile file) { this.file = file; @@ -54,7 +53,6 @@ class CryptoWritableFile implements WritableFile { @Override public int write(ByteBuffer source) { - contentChanged = true; final int size = source.remaining(); final ByteBuffer cleartextCopy = ByteBuffer.allocate(size); ByteBuffers.copy(source, cleartextCopy); @@ -74,7 +72,6 @@ class CryptoWritableFile implements WritableFile { @Override public void truncate() { - contentChanged = true; terminateAndWaitForWriteTask(); file.truncate(); initialize(0); @@ -88,7 +85,7 @@ class CryptoWritableFile implements WritableFile { @Override public void close() { try { - if (contentChanged && file.isOpen()) { + if (file.isOpen()) { terminateAndWaitForWriteTask(); writeHeader(); } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java index 33bd5c51f..ed0b9b9b3 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java @@ -73,6 +73,7 @@ class DavFolder extends DavNode { private void addMemberFile(DavFile memberFile, InputStream inputStream) { try (ReadableByteChannel src = Channels.newChannel(inputStream); WritableFile dst = node.file(memberFile.getDisplayName()).openWritable()) { + dst.truncate(); ByteStreams.copy(src, dst); } catch (IOException e) { throw new UncheckedIOException(e);